#include #include #include "Catch2.h" #include #include #include using namespace Leonetienne::GCrypt; // Tests that writing and retrieving data from a block works TEST_CASE(__FILE__"/Write-read", "[Block]") { // Setup Block block; // Exercise for (std::size_t i = 0; i < 16; i++) { block.Get(i) = i * 1024; } // Verify for (std::size_t i = 0; i < 16; i++) { REQUIRE(block.Get(i) == i * 1024); } } // Tests that the copy constructor works TEST_CASE(__FILE__"/CCtor", "[Block]") { // Setup Block block; for (std::size_t i = 0; i < 16; i++) { block.Get(i) = i * 1024; } // Exercise Block block2(block); // Verify for (std::size_t i = 0; i < 16; i++) { REQUIRE(block2.Get(i) == i * 1024); } } // Tests that operator= works TEST_CASE(__FILE__"/operator=", "[Block]") { // Setup Block block; for (std::size_t i = 0; i < 16; i++) { block.Get(i) = i * 1024; } // Exercise Block block2; block2 = block; // Verify for (std::size_t i = 0; i < 16; i++) { REQUIRE(block2.Get(i) == i * 1024); } } // Tests that converting to, and from, strings works TEST_CASE(__FILE__"/StringConversion", "[Block]") { // Setup srand(time(0)); std::stringstream ss; for (std::size_t i = 0; i < 512; i++) { ss << (rand()%2 == 0 ? '1' : '0'); } // Exercise Block block(ss.str()); // Verify REQUIRE(block.ToString() == ss.str()); } // Tests that operator* is the same as *= TEST_CASE(__FILE__"/operator*&=", "[Block]") { // Setup Block block1; for (std::size_t i = 0; i < 16; i++) { block1.Get(i) = i * 1024; } Block block2; for (std::size_t i = 0; i < 16; i++) { block2.Get(i) = i * 1024 * 2; } // Exercise Block block3 = block1 * block2; block1 *= block2; // Verify REQUIRE(block1 == block3); } // Tests that operator^ (xor) works TEST_CASE(__FILE__"/xor", "[Block]") { // Setup Block block; for (std::size_t i = 0; i < 16; i++) { block.Get(i) = i * 1024; } Block xorRH; for (std::size_t i = 0; i < 16; i++) { xorRH.Get(i) = i * 5099; } // Exercise Block result = block ^ xorRH; Block manualResult; for (std::size_t i = 0; i < 16; i++) { manualResult.Get(i) = (i * 1024) ^ (i * 5099); } // Verify REQUIRE(result == manualResult); } // Tests that operator^ is the same as ^= TEST_CASE(__FILE__"/operator^&=", "[Block]") { // Setup Block block1; for (std::size_t i = 0; i < 16; i++) { block1.Get(i) = i * 1024; } Block block2; for (std::size_t i = 0; i < 16; i++) { block2.Get(i) = i * 5099 * 2; } // Exercise Block block3 = block1 ^ block2; block1 ^= block2; // Verify REQUIRE(block1 == block3); } // Tests that operator+ (add) works TEST_CASE(__FILE__"/add", "[Block]") { // Setup Block block; for (std::size_t i = 0; i < 16; i++) { block.Get(i) = i * 1024; } Block addRH; for (std::size_t i = 0; i < 16; i++) { addRH.Get(i) = i * 5099; } // Exercise Block result = block + addRH; Block manualResult; for (std::size_t i = 0; i < 16; i++) { manualResult.Get(i) = (i * 1024) + (i * 5099); } // Verify REQUIRE(result == manualResult); } // Tests that operator+ is the same as += TEST_CASE(__FILE__"/operator+&=", "[Block]") { // Setup Block block1; for (std::size_t i = 0; i < 16; i++) { block1.Get(i) = i * 1024; } Block block2; for (std::size_t i = 0; i < 16; i++) { block2.Get(i) = i * 5099 * 2; } // Exercise Block block3 = block1 + block2; block1 += block2; // Verify REQUIRE(block1 == block3); } // Tests that operator- (subtract) works TEST_CASE(__FILE__"/subtract", "[Block]") { // Setup Block block; for (std::size_t i = 0; i < 16; i++) { block.Get(i) = i * 1024; } Block subRH; for (std::size_t i = 0; i < 16; i++) { subRH.Get(i) = i * 5099; } // Exercise Block result = block - subRH; Block manualResult; for (std::size_t i = 0; i < 16; i++) { manualResult.Get(i) = (i * 1024) - (i * 5099); } // Verify REQUIRE(result == manualResult); } // Tests that operator- is the same as -= TEST_CASE(__FILE__"/operator-&=", "[Block]") { // Setup Block block1; for (std::size_t i = 0; i < 16; i++) { block1.Get(i) = i * 1024; } Block block2; for (std::size_t i = 0; i < 16; i++) { block2.Get(i) = i * 5099 * 2; } // Exercise Block block3 = block1 - block2; block1 -= block2; // Verify REQUIRE(block1 == block3); } // Tests that subtraction undoes addition, and vica versa TEST_CASE(__FILE__"/subtraction-undoes-addition", "[Block]") { // Setup const Block a = Key::FromPassword("Halleluja"); const Block b = Key::FromPassword("Ananas"); // Exercise const Block a_plus_b = a + b; const Block a_plus_b_minus_b = a_plus_b - b; // Verify REQUIRE(a == a_plus_b_minus_b); } // Tests that operator== works correctly TEST_CASE(__FILE__"/operator==", "[Block]") { // Setup Block block; for (std::size_t i = 0; i < 16; i++) { block.Get(i) = i * 1024; } SECTION("Expected true") { Block sameBlock; for (std::size_t i = 0; i < 16; i++) { sameBlock.Get(i) = i * 1024; } REQUIRE(block == sameBlock); } SECTION("Expected false") { Block otherBlock; for (std::size_t i = 0; i < 16; i++) { otherBlock.Get(i) = i * 1024 + 1; } REQUIRE_FALSE(block == otherBlock); } } // Tests that operator!= works correctly TEST_CASE(__FILE__"/operator!=", "[Block]") { // Setup Block block; for (std::size_t i = 0; i < 16; i++) { block.Get(i) = i * 1024; } SECTION("Expected false") { Block sameBlock; for (std::size_t i = 0; i < 16; i++) { sameBlock.Get(i) = i * 1024; } REQUIRE_FALSE(block != sameBlock); } SECTION("Expected true") { Block otherBlock; for (std::size_t i = 0; i < 16; i++) { otherBlock.Get(i) = i * 1024 + 1; } REQUIRE(block != otherBlock); } } // Tests that getting the data via the matrix accessor works TEST_CASE(__FILE__"/matrix-accessor", "[Block]") { // Setup Block block; for (std::size_t i = 0; i < 16; i++) { block.Get(i) = i; } // Exercise REQUIRE(block.Get(0,0) == 0); REQUIRE(block.Get(1,0) == 1); REQUIRE(block.Get(2,0) == 2); REQUIRE(block.Get(3,0) == 3); REQUIRE(block.Get(0,1) == 4); REQUIRE(block.Get(1,1) == 5); REQUIRE(block.Get(2,1) == 6); REQUIRE(block.Get(3,1) == 7); REQUIRE(block.Get(0,2) == 8); REQUIRE(block.Get(1,2) == 9); REQUIRE(block.Get(2,2) == 10); REQUIRE(block.Get(3,2) == 11); REQUIRE(block.Get(0,3) == 12); REQUIRE(block.Get(1,3) == 13); REQUIRE(block.Get(2,3) == 14); REQUIRE(block.Get(3,3) == 15); } // Tests that the reset method works TEST_CASE(__FILE__"/reset", "[Block]") { // Setup Block block; for (std::size_t i = 0; i < 16; i++) { block.Get(i) = i + 33; } // Exercise block.Reset(); // Verify for (std::size_t i = 0; i < 16; i++) { REQUIRE(block[i] == 0); } } // Tests that shift rows up works TEST_CASE(__FILE__"/shift-rows-up", "[Block]") { // Setup Block a; a.Get(0,0) = 10; a.Get(0,1) = 11; a.Get(0,2) = 12; a.Get(0,3) = 13; a.Get(1,0) = 20; a.Get(1,1) = 21; a.Get(1,2) = 22; a.Get(1,3) = 23; a.Get(2,0) = 30; a.Get(2,1) = 31; a.Get(2,2) = 32; a.Get(2,3) = 33; a.Get(3,0) = 40; a.Get(3,1) = 41; a.Get(3,2) = 42; a.Get(3,3) = 43; Block e; /* expected */ e.Get(0,0) = 20; e.Get(0,1) = 21; e.Get(0,2) = 22; e.Get(0,3) = 23; e.Get(1,0) = 30; e.Get(1,1) = 31; e.Get(1,2) = 32; e.Get(1,3) = 33; e.Get(2,0) = 40; e.Get(2,1) = 41; e.Get(2,2) = 42; e.Get(2,3) = 43; e.Get(3,0) = 10; e.Get(3,1) = 11; e.Get(3,2) = 12; e.Get(3,3) = 13; // Exercise a.ShiftRowsUpInplace(); // Verify REQUIRE(a == e); } // Tests that ShiftRowsUpInplace() does the exact same thing as ShiftRowsUp() TEST_CASE(__FILE__"/shift-rows-up-same-as-inplace", "[Block]") { // Setup Block a = Key::FromPassword("Halleluja"); const Block initial_a = a; // Exercise and verify a.ShiftRowsUpInplace(); REQUIRE(a == initial_a.ShiftRowsUp()); } // Tests that shift rows down works TEST_CASE(__FILE__"/shift-rows-down", "[Block]") { // Setup Block a; a.Get(0,0) = 10; a.Get(0,1) = 11; a.Get(0,2) = 12; a.Get(0,3) = 13; a.Get(1,0) = 20; a.Get(1,1) = 21; a.Get(1,2) = 22; a.Get(1,3) = 23; a.Get(2,0) = 30; a.Get(2,1) = 31; a.Get(2,2) = 32; a.Get(2,3) = 33; a.Get(3,0) = 40; a.Get(3,1) = 41; a.Get(3,2) = 42; a.Get(3,3) = 43; Block e; /* expected */ e.Get(0,0) = 40; e.Get(0,1) = 41; e.Get(0,2) = 42; e.Get(0,3) = 43; e.Get(1,0) = 10; e.Get(1,1) = 11; e.Get(1,2) = 12; e.Get(1,3) = 13; e.Get(2,0) = 20; e.Get(2,1) = 21; e.Get(2,2) = 22; e.Get(2,3) = 23; e.Get(3,0) = 30; e.Get(3,1) = 31; e.Get(3,2) = 32; e.Get(3,3) = 33; // Exercise a.ShiftRowsDownInplace(); // Verify REQUIRE(a == e); } // Tests that ShiftRowsDownInplace() does the exact same thing as ShiftRowsDown() TEST_CASE(__FILE__"/shift-rows-down-same-as-inplace", "[Block]") { // Setup Block a = Key::FromPassword("Halleluja"); const Block initial_a = a; // Exercise and verify a.ShiftRowsDownInplace(); REQUIRE(a == initial_a.ShiftRowsDown()); } // Tests that shift columns left works TEST_CASE(__FILE__"/shift-columns-left", "[Block]") { // Setup Block a; a.Get(0,0) = 10; a.Get(0,1) = 11; a.Get(0,2) = 12; a.Get(0,3) = 13; a.Get(1,0) = 20; a.Get(1,1) = 21; a.Get(1,2) = 22; a.Get(1,3) = 23; a.Get(2,0) = 30; a.Get(2,1) = 31; a.Get(2,2) = 32; a.Get(2,3) = 33; a.Get(3,0) = 40; a.Get(3,1) = 41; a.Get(3,2) = 42; a.Get(3,3) = 43; Block e; /* expected */ e.Get(0,0) = 11; e.Get(0,1) = 12; e.Get(0,2) = 13; e.Get(0,3) = 10; e.Get(1,0) = 21; e.Get(1,1) = 22; e.Get(1,2) = 23; e.Get(1,3) = 20; e.Get(2,0) = 31; e.Get(2,1) = 32; e.Get(2,2) = 33; e.Get(2,3) = 30; e.Get(3,0) = 41; e.Get(3,1) = 42; e.Get(3,2) = 43; e.Get(3,3) = 40; // Exercise a.ShiftColumnsLeftInplace(); // Verify REQUIRE(a == e); } // Tests that ShiftColumnsLeftInplace()() does the exact same thing as ShiftColumnsLeft() TEST_CASE(__FILE__"/shift-columns-left-same-as-inplace", "[Block]") { // Setup Block a = Key::FromPassword("Halleluja"); const Block initial_a = a; // Exercise and verify a.ShiftColumnsLeftInplace(); REQUIRE(a == initial_a.ShiftColumnsLeft()); } // Tests that shift columns right works TEST_CASE(__FILE__"/shift-columns-right", "[Block]") { // Setup Block a; a.Get(0,0) = 10; a.Get(0,1) = 11; a.Get(0,2) = 12; a.Get(0,3) = 13; a.Get(1,0) = 20; a.Get(1,1) = 21; a.Get(1,2) = 22; a.Get(1,3) = 23; a.Get(2,0) = 30; a.Get(2,1) = 31; a.Get(2,2) = 32; a.Get(2,3) = 33; a.Get(3,0) = 40; a.Get(3,1) = 41; a.Get(3,2) = 42; a.Get(3,3) = 43; Block e; /* expected */ e.Get(0,0) = 13; e.Get(0,1) = 10; e.Get(0,2) = 11; e.Get(0,3) = 12; e.Get(1,0) = 23; e.Get(1,1) = 20; e.Get(1,2) = 21; e.Get(1,3) = 22; e.Get(2,0) = 33; e.Get(2,1) = 30; e.Get(2,2) = 31; e.Get(2,3) = 32; e.Get(3,0) = 43; e.Get(3,1) = 40; e.Get(3,2) = 41; e.Get(3,3) = 42; // Exercise a.ShiftColumnsRightInplace(); // Verify REQUIRE(a == e); } // Tests that ShiftColumnsRightInplace()() does the exact same thing as ShiftColumnsRight() TEST_CASE(__FILE__"/shift-columns-right-same-as-inplace", "[Block]") { // Setup Block a = Key::FromPassword("Halleluja"); const Block initial_a = a; // Exercise and verify a.ShiftColumnsRightInplace(); REQUIRE(a == initial_a.ShiftColumnsRight()); } // Tests that shift cells left works TEST_CASE(__FILE__"/shift-cells-left", "[Block]") { // Setup Block a; for (std::size_t i = 0; i < 16; i++) { a.Get(i) = i; } Block expected; for (std::size_t i = 0; i < 15; i++) { expected.Get(i) = i+1; } expected.Get(15) = 0; // Exercise a.ShiftCellsLeftInplace(); // Verify REQUIRE(a == expected); } // Tests that ShiftCellsLeftInplace()() does the exact same thing as ShiftCellsLeft() TEST_CASE(__FILE__"/shift-cells-left-same-as-inplace", "[Block]") { // Setup Block a = Key::FromPassword("Halleluja"); const Block initial_a = a; // Exercise and verify a.ShiftCellsLeftInplace(); REQUIRE(a == initial_a.ShiftCellsLeft()); } // Tests that shift cells right works TEST_CASE(__FILE__"/shift-cells-right", "[Block]") { // Setup Block a; for (std::size_t i = 0; i < 16; i++) { a.Get(i) = i; } Block expected; for (std::size_t i = 1; i < 16; i++) { expected.Get(i) = i-1; } expected.Get(0) = 15; // Exercise a.ShiftCellsRightInplace(); // Verify REQUIRE(a == expected); } // Tests that ShiftCellsRightInplace()() does the exact same thing as ShiftCellsRight() TEST_CASE(__FILE__"/shift-cells-right-same-as-inplace", "[Block]") { // Setup Block a = Key::FromPassword("Halleluja"); const Block initial_a = a; // Exercise and verify a.ShiftCellsRightInplace(); REQUIRE(a == initial_a.ShiftCellsRight()); } // Tests that shifting down undoes shifting up, and vica versa TEST_CASE(__FILE__"/shift-down-undoes-shift-up", "[Block]") { // Setup Block a = Key::FromPassword("Halleluja"); const Block initial_a = a; // Exercise a.ShiftRowsUpInplace(); a.ShiftRowsDownInplace(); // Verify REQUIRE(a == initial_a); } // Tests that shifting left undoes shifting right, and vica versa TEST_CASE(__FILE__"/shift-left-undoes-shift-right", "[Block]") { // Setup Block a = Key::FromPassword("Halleluja"); const Block initial_a = a; // Exercise a.ShiftColumnsRightInplace(); a.ShiftColumnsLeftInplace(); // Verify REQUIRE(a == initial_a); } // Tests that shifting cells left undoes shifting cells right, and vica versa TEST_CASE(__FILE__"/cellshift-left-undoes-cellshift-right", "[Block]") { // Setup Block a = Key::FromPassword("Halleluja"); const Block initial_a = a; // Exercise a.ShiftCellsRightInplace(); a.ShiftCellsLeftInplace(); // Verify REQUIRE(a == initial_a); } // Tests that multiple, combined shifts and additions can be undone TEST_CASE(__FILE__"/multiple-combined-shifts-and-additions-can-be-undone", "[Block]") { // Setup Block a = Key::FromPassword("Halleluja"); Block key = Key::FromPassword("Papaya"); const Block initial_a = a; // Exercise (mix-up) for (std::size_t i = 0; i < 64; i++) { a.ShiftRowsUpInplace(); a.ShiftColumnsLeftInplace(); a += key; a.ShiftCellsRightInplace(); } // Exercise (un-mix) for (std::size_t i = 0; i < 64; i++) { a.ShiftCellsLeftInplace(); a -= key; a.ShiftColumnsRightInplace(); a.ShiftRowsDownInplace(); } // Verify REQUIRE(a == initial_a); } // Tests that the get-bit method works TEST_CASE(__FILE__"/get-bit", "[Block]") { // Setup Block a = Key::FromPassword("Halleluja"); // Exercise std::stringstream ss; for (std::size_t i = 0; i < 512; i++) { ss << a.GetBit(i); } // Verify REQUIRE(ss.str() == a.ToString()); }