Tests, that work!
This commit is contained in:
@@ -4,12 +4,20 @@ module BinaryOps(
|
|||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
|
import Data.Bits(xor,(.&.),(.|.))
|
||||||
|
import Data.Map.Strict(Map)
|
||||||
|
import qualified Data.Map.Strict as Map
|
||||||
import File
|
import File
|
||||||
import Gen(toLit)
|
import Gen(toLit)
|
||||||
|
import Generators
|
||||||
import Language.Rust.Data.Ident
|
import Language.Rust.Data.Ident
|
||||||
import Language.Rust.Data.Position
|
import Language.Rust.Data.Position
|
||||||
import Language.Rust.Quote
|
import Language.Rust.Quote
|
||||||
import Language.Rust.Syntax
|
import Language.Rust.Syntax
|
||||||
|
import System.Random(RandomGen)
|
||||||
|
|
||||||
|
numTestCases :: Int
|
||||||
|
numTestCases = 3000
|
||||||
|
|
||||||
binaryOps :: File
|
binaryOps :: File
|
||||||
binaryOps = File {
|
binaryOps = File {
|
||||||
@@ -17,7 +25,7 @@ binaryOps = File {
|
|||||||
outputName = "binary",
|
outputName = "binary",
|
||||||
isUnsigned = True,
|
isUnsigned = True,
|
||||||
generator = declareBinaryOperators,
|
generator = declareBinaryOperators,
|
||||||
testCase = Nothing
|
testCase = Just generateTests
|
||||||
}
|
}
|
||||||
|
|
||||||
declareBinaryOperators :: Word -> SourceFile Span
|
declareBinaryOperators :: Word -> SourceFile Span
|
||||||
@@ -29,6 +37,7 @@ declareBinaryOperators bitsize =
|
|||||||
xorOps = generateBinOps "BitXor" struct_name "bitxor" BitXorOp entries
|
xorOps = generateBinOps "BitXor" struct_name "bitxor" BitXorOp entries
|
||||||
baseNegationStmts = negationStatements "self" entries
|
baseNegationStmts = negationStatements "self" entries
|
||||||
refNegationStmts = negationStatements "output" entries
|
refNegationStmts = negationStatements "output" entries
|
||||||
|
testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty
|
||||||
in [sourceFile|
|
in [sourceFile|
|
||||||
use core::ops::{BitAnd,BitAndAssign};
|
use core::ops::{BitAnd,BitAndAssign};
|
||||||
use core::ops::{BitOr,BitOrAssign};
|
use core::ops::{BitOr,BitOrAssign};
|
||||||
@@ -37,6 +46,8 @@ declareBinaryOperators bitsize =
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use crate::CryptoNum;
|
use crate::CryptoNum;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
use crate::testing::{build_test_path,run_test};
|
||||||
|
#[cfg(test)]
|
||||||
use quickcheck::quickcheck;
|
use quickcheck::quickcheck;
|
||||||
use super::$$struct_name;
|
use super::$$struct_name;
|
||||||
|
|
||||||
@@ -109,6 +120,33 @@ declareBinaryOperators bitsize =
|
|||||||
(&a | $$struct_name::zero()) == a
|
(&a | $$struct_name::zero()) == a
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
#[test]
|
||||||
|
fn KATs() {
|
||||||
|
run_test(build_test_path("binary", $$(testFileLit)), 6, |case| {
|
||||||
|
let (neg0, xbytes) = case.get("x").unwrap();
|
||||||
|
let (neg1, ybytes) = case.get("y").unwrap();
|
||||||
|
let (neg2, abytes) = case.get("a").unwrap();
|
||||||
|
let (neg3, obytes) = case.get("o").unwrap();
|
||||||
|
let (neg4, ebytes) = case.get("e").unwrap();
|
||||||
|
let (neg5, nbytes) = case.get("n").unwrap();
|
||||||
|
|
||||||
|
assert!(!neg0 && !neg1 && !neg2 && !neg3 && !neg4 && !neg5);
|
||||||
|
let x = $$struct_name::from_bytes(&xbytes);
|
||||||
|
let y = $$struct_name::from_bytes(&ybytes);
|
||||||
|
let a = $$struct_name::from_bytes(&abytes);
|
||||||
|
let o = $$struct_name::from_bytes(&obytes);
|
||||||
|
let e = $$struct_name::from_bytes(&ebytes);
|
||||||
|
let n = $$struct_name::from_bytes(&nbytes);
|
||||||
|
|
||||||
|
assert_eq!(a, &x & &y);
|
||||||
|
assert_eq!(o, &x | &y);
|
||||||
|
assert_eq!(e, &x ^ &y);
|
||||||
|
assert_eq!(n, !x);
|
||||||
|
});
|
||||||
|
}
|
||||||
|]
|
|]
|
||||||
|
|
||||||
negationStatements :: String -> Word -> [Stmt Span]
|
negationStatements :: String -> Word -> [Stmt Span]
|
||||||
@@ -201,3 +239,17 @@ generateAllTheVariants traitname func sname oper entries = [
|
|||||||
Semi (AssignOp [] oper [expr| $$(left).value[$$(i)] |]
|
Semi (AssignOp [] oper [expr| $$(left).value[$$(i)] |]
|
||||||
[expr| $$(right).value[$$(i)] |]
|
[expr| $$(right).value[$$(i)] |]
|
||||||
mempty) mempty
|
mempty) mempty
|
||||||
|
|
||||||
|
generateTests :: RandomGen g => Word -> g -> [Map String String]
|
||||||
|
generateTests size g = go g numTestCases
|
||||||
|
where
|
||||||
|
go _ 0 = []
|
||||||
|
go g0 i =
|
||||||
|
let (x, g1) = generateNum g0 size
|
||||||
|
(y, g2) = generateNum g1 size
|
||||||
|
tcase = Map.fromList [("x", showX x), ("y", showX y),
|
||||||
|
("a", showX (x .&. y)),
|
||||||
|
("o", showX (x .|. y)),
|
||||||
|
("e", showX (x `xor` y)),
|
||||||
|
("n", showX ( ((2 ^ size) - 1) `xor` x ))]
|
||||||
|
in tcase : go g2 (i - 1)
|
||||||
|
|||||||
@@ -2,11 +2,18 @@
|
|||||||
module Compare(comparisons)
|
module Compare(comparisons)
|
||||||
where
|
where
|
||||||
|
|
||||||
|
import Data.Map.Strict(Map)
|
||||||
|
import qualified Data.Map.Strict as Map
|
||||||
import File
|
import File
|
||||||
|
import Generators
|
||||||
import Language.Rust.Data.Ident
|
import Language.Rust.Data.Ident
|
||||||
import Language.Rust.Data.Position
|
import Language.Rust.Data.Position
|
||||||
import Language.Rust.Quote
|
import Language.Rust.Quote
|
||||||
import Language.Rust.Syntax
|
import Language.Rust.Syntax
|
||||||
|
import System.Random(RandomGen)
|
||||||
|
|
||||||
|
numTestCases :: Int
|
||||||
|
numTestCases = 3000
|
||||||
|
|
||||||
comparisons :: File
|
comparisons :: File
|
||||||
comparisons = File {
|
comparisons = File {
|
||||||
@@ -14,7 +21,7 @@ comparisons = File {
|
|||||||
outputName = "compare",
|
outputName = "compare",
|
||||||
isUnsigned = True,
|
isUnsigned = True,
|
||||||
generator = declareComparators,
|
generator = declareComparators,
|
||||||
testCase = Nothing
|
testCase = Just generateTests
|
||||||
}
|
}
|
||||||
|
|
||||||
declareComparators :: Word -> SourceFile Span
|
declareComparators :: Word -> SourceFile Span
|
||||||
@@ -23,9 +30,14 @@ declareComparators bitsize =
|
|||||||
entries = bitsize `div` 64
|
entries = bitsize `div` 64
|
||||||
eqStatements = buildEqStatements 0 entries
|
eqStatements = buildEqStatements 0 entries
|
||||||
compareExp = buildCompareExp 0 entries
|
compareExp = buildCompareExp 0 entries
|
||||||
|
testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty
|
||||||
in [sourceFile|
|
in [sourceFile|
|
||||||
use core::cmp::{Eq,Ordering,PartialEq};
|
use core::cmp::{Eq,Ordering,PartialEq};
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
use crate::CryptoNum;
|
||||||
|
#[cfg(test)]
|
||||||
|
use crate::testing::{build_test_path,run_test};
|
||||||
|
#[cfg(test)]
|
||||||
use quickcheck::quickcheck;
|
use quickcheck::quickcheck;
|
||||||
use super::$$sname;
|
use super::$$sname;
|
||||||
|
|
||||||
@@ -73,6 +85,40 @@ declareComparators bitsize =
|
|||||||
if a <= b && b <= c { a <= c } else { true }
|
if a <= b && b <= c { a <= c } else { true }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
#[test]
|
||||||
|
fn KATs() {
|
||||||
|
run_test(build_test_path("compare", $$(testFileLit)), 8, |case| {
|
||||||
|
let (neg0, xbytes) = case.get("x").unwrap();
|
||||||
|
let (neg1, ybytes) = case.get("y").unwrap();
|
||||||
|
let (neg2, ebytes) = case.get("e").unwrap();
|
||||||
|
let (neg3, nbytes) = case.get("n").unwrap();
|
||||||
|
let (neg4, gbytes) = case.get("g").unwrap();
|
||||||
|
let (neg5, hbytes) = case.get("h").unwrap();
|
||||||
|
let (neg6, lbytes) = case.get("l").unwrap();
|
||||||
|
let (neg7, kbytes) = case.get("k").unwrap();
|
||||||
|
|
||||||
|
assert!(!neg0 && !neg1 && !neg2 && !neg3 &&
|
||||||
|
!neg4 && !neg5 && !neg6 && !neg7);
|
||||||
|
let x = $$sname::from_bytes(&xbytes);
|
||||||
|
let y = $$sname::from_bytes(&ybytes);
|
||||||
|
let e = 1 == ebytes[0];
|
||||||
|
let n = 1 == nbytes[0];
|
||||||
|
let g = 1 == gbytes[0];
|
||||||
|
let h = 1 == hbytes[0];
|
||||||
|
let l = 1 == lbytes[0];
|
||||||
|
let k = 1 == kbytes[0];
|
||||||
|
|
||||||
|
assert_eq!(e, x == y);
|
||||||
|
assert_eq!(n, x != y);
|
||||||
|
assert_eq!(g, x > y);
|
||||||
|
assert_eq!(h, x >= y);
|
||||||
|
assert_eq!(l, x < y);
|
||||||
|
assert_eq!(k, x <= y);
|
||||||
|
});
|
||||||
|
}
|
||||||
|]
|
|]
|
||||||
|
|
||||||
buildEqStatements :: Word -> Word -> [Stmt Span]
|
buildEqStatements :: Word -> Word -> [Stmt Span]
|
||||||
@@ -95,3 +141,19 @@ buildCompareExp i numEntries
|
|||||||
in [expr| $$(rest).then(self.value[$$(x)].cmp(&other.value[$$(x)])) |]
|
in [expr| $$(rest).then(self.value[$$(x)].cmp(&other.value[$$(x)])) |]
|
||||||
where
|
where
|
||||||
x = Lit [] (Int Dec (fromIntegral i) Unsuffixed mempty) mempty
|
x = Lit [] (Int Dec (fromIntegral i) Unsuffixed mempty) mempty
|
||||||
|
|
||||||
|
generateTests :: RandomGen g => Word -> g -> [Map String String]
|
||||||
|
generateTests size g = go g numTestCases
|
||||||
|
where
|
||||||
|
go _ 0 = []
|
||||||
|
go g0 i =
|
||||||
|
let (x, g1) = generateNum g0 size
|
||||||
|
(y, g2) = generateNum g1 size
|
||||||
|
tcase = Map.fromList [("x", showX x), ("y", showX y),
|
||||||
|
("e", showB (x == y)),
|
||||||
|
("n", showB (x /= y)),
|
||||||
|
("g", showB (x > y)),
|
||||||
|
("h", showB (x >= y)),
|
||||||
|
("l", showB (x < y)),
|
||||||
|
("k", showB (x <= y))]
|
||||||
|
in tcase : go g2 (i - 1)
|
||||||
|
|||||||
@@ -39,8 +39,10 @@ declareConversions bitsize =
|
|||||||
in [sourceFile|
|
in [sourceFile|
|
||||||
use core::convert::{From,TryFrom};
|
use core::convert::{From,TryFrom};
|
||||||
use crate::CryptoNum;
|
use crate::CryptoNum;
|
||||||
use super::$$sname;
|
|
||||||
use crate::ConversionError;
|
use crate::ConversionError;
|
||||||
|
#[cfg(test)]
|
||||||
|
use quickcheck::quickcheck;
|
||||||
|
use super::$$sname;
|
||||||
|
|
||||||
$@{u8_prims}
|
$@{u8_prims}
|
||||||
$@{u16_prims}
|
$@{u16_prims}
|
||||||
@@ -55,6 +57,28 @@ declareConversions bitsize =
|
|||||||
$@{i64_prims}
|
$@{i64_prims}
|
||||||
$@{isz_prims}
|
$@{isz_prims}
|
||||||
$@{i128_prims}
|
$@{i128_prims}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
quickcheck! {
|
||||||
|
fn u8_recovers(x: u8) -> bool {
|
||||||
|
x == u8::try_from($$sname::from(x)).unwrap()
|
||||||
|
}
|
||||||
|
fn u16_recovers(x: u16) -> bool {
|
||||||
|
x == u16::try_from($$sname::from(x)).unwrap()
|
||||||
|
}
|
||||||
|
fn u32_recovers(x: u32) -> bool {
|
||||||
|
x == u32::try_from($$sname::from(x)).unwrap()
|
||||||
|
}
|
||||||
|
fn u64_recovers(x: u64) -> bool {
|
||||||
|
x == u64::try_from($$sname::from(x)).unwrap()
|
||||||
|
}
|
||||||
|
fn usize_recovers(x: usize) -> bool {
|
||||||
|
x == usize::try_from($$sname::from(x)).unwrap()
|
||||||
|
}
|
||||||
|
fn u128_recovers(x: u128) -> bool {
|
||||||
|
x == u128::try_from($$sname::from(x)).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|]
|
|]
|
||||||
|
|
||||||
generateU128Primitives :: Ident -> Word -> [Item Span]
|
generateU128Primitives :: Ident -> Word -> [Item Span]
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ declareCryptoNumInstance bitsize =
|
|||||||
Tree (Token mempty (LiteralTok (IntegerTok (show bytelen)) Nothing))
|
Tree (Token mempty (LiteralTok (IntegerTok (show bytelen)) Nothing))
|
||||||
])
|
])
|
||||||
entrieslit = toLit entries
|
entrieslit = toLit entries
|
||||||
|
testFileLit = Lit [] (Str (testFile bitsize) Cooked Unsuffixed mempty) mempty
|
||||||
in [sourceFile|
|
in [sourceFile|
|
||||||
use core::cmp::min;
|
use core::cmp::min;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -137,7 +138,7 @@ declareCryptoNumInstance bitsize =
|
|||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
#[test]
|
#[test]
|
||||||
fn KATs() {
|
fn KATs() {
|
||||||
run_test(build_test_path("base", stringify!($$sname)), 8, |case| {
|
run_test(build_test_path("cryptonum", $$(testFileLit)), 8, |case| {
|
||||||
let (neg0, xbytes) = case.get("x").unwrap();
|
let (neg0, xbytes) = case.get("x").unwrap();
|
||||||
let (neg1, mbytes) = case.get("m").unwrap();
|
let (neg1, mbytes) = case.get("m").unwrap();
|
||||||
let (neg2, zbytes) = case.get("z").unwrap();
|
let (neg2, zbytes) = case.get("z").unwrap();
|
||||||
@@ -184,7 +185,7 @@ generateTests size g = go g numTestCases
|
|||||||
(m, g2) = generateNum g1 size
|
(m, g2) = generateNum g1 size
|
||||||
(b, g3) = generateNum g2 16
|
(b, g3) = generateNum g2 16
|
||||||
m' = m `mod` (fromIntegral size `div` 64)
|
m' = m `mod` (fromIntegral size `div` 64)
|
||||||
r = m `mod` (2 ^ (64 * m'))
|
r = x `mod` (2 ^ (64 * m'))
|
||||||
t = x `testBit` (fromIntegral b)
|
t = x `testBit` (fromIntegral b)
|
||||||
tcase = Map.fromList [("x", showX x), ("z", showB (x == 0)),
|
tcase = Map.fromList [("x", showX x), ("z", showB (x == 0)),
|
||||||
("e", showB (even x)), ("o", showB (odd x)),
|
("e", showB (even x)), ("o", showB (odd x)),
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
module File(
|
module File(
|
||||||
File(..),
|
File(..),
|
||||||
Task(..),
|
Task(..),
|
||||||
generateTasks
|
generateTasks,
|
||||||
|
testFile
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
@@ -34,6 +35,9 @@ data Task = Task {
|
|||||||
writer :: Handle -> IO ()
|
writer :: Handle -> IO ()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testFile :: Word -> FilePath
|
||||||
|
testFile size = "U" ++ show5 size ++ ".test"
|
||||||
|
|
||||||
show5 :: Word -> String
|
show5 :: Word -> String
|
||||||
show5 = go . show
|
show5 = go . show
|
||||||
where
|
where
|
||||||
@@ -65,8 +69,7 @@ generateTasks rng files sizes = basicTasks ++ moduleTasks
|
|||||||
mainTask : tasks
|
mainTask : tasks
|
||||||
Just caseGenerator ->
|
Just caseGenerator ->
|
||||||
let testTask = Task {
|
let testTask = Task {
|
||||||
outputFile = "testdata" </> outputName file </>
|
outputFile = "testdata" </> outputName file </> testFile size,
|
||||||
("U" ++ show5 size ++ ".test"),
|
|
||||||
writer = \ hndl -> writeTestCase hndl (caseGenerator size myg)
|
writer = \ hndl -> writeTestCase hndl (caseGenerator size myg)
|
||||||
}
|
}
|
||||||
in testTask : mainTask : tasks
|
in testTask : mainTask : tasks
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ fn next_value_set(line: &str) -> (String, bool, Vec<u8>)
|
|||||||
let key = items.next().unwrap();
|
let key = items.next().unwrap();
|
||||||
let valbits = items.next().unwrap();
|
let valbits = items.next().unwrap();
|
||||||
let neg = valbits.contains('-');
|
let neg = valbits.contains('-');
|
||||||
let valbitsnoneg = valbits.trim_start_matches("-");
|
let valbitsnoneg = valbits.trim_start_matches('-');
|
||||||
|
|
||||||
let mut nibble_iter = valbitsnoneg.chars().rev();
|
let mut nibble_iter = valbitsnoneg.chars().rev();
|
||||||
let mut val = Vec::new();
|
let mut val = Vec::new();
|
||||||
|
|||||||
Reference in New Issue
Block a user