// File: yoavweiss[P]cache-digests-cuckoo/cuckoo.cpp
// Function: Cuckoo::runTests()
void Cuckoo::runTests() {
    // Test bigEndianRead
    std::string hashStr = "1234567";
    unsigned long hashNumber = bigEndianRead((const unsigned char*)hashStr.c_str(), 1, 4);
    if (hashNumber != 842216501) {
        printf("Fail - hashNumber %lu", hashNumber);
    }
    // Test bigEndianWrite
    unsigned char testDigest[10];
    testDigest[0] = 49;
    bigEndianWrite(testDigest, 1, 4, 842216501);
    testDigest[5] = 0;
    if ((char*)testDigest != std::string("12345")) {
        printf("Fail - bigEndianWrite got %s\n", testDigest);
    }
    // Test readFingerprint
    hashStr = "0123456789abcdef";
    unsigned char fingerprintHash[17];
    fingerprintHash[16] = 0;
    strncpy((char*)fingerprintHash, hashStr.c_str(), 16);
    unsigned long fingerprintValue = readFingerprint(fingerprintHash, 121, 7);
    if (fingerprintValue != 102)
        printf("FAIL - readFingerprint %lu\n", fingerprintValue);
    fingerprintValue = readFingerprint(fingerprintHash, 117, 7);
    if (fingerprintValue!= 86)
        printf("FAIL - readFingerprint %lu\n", fingerprintValue);
    char shaInStr[65] = "2442a9b40768c5ccff9366514374eeca86fd6a3156b11d5f7aaad7b1e3fbbb08";
    unsigned char fingerprintHash2[32];
    for (int i = 0; i < 32; ++i) {
        unsigned char letter = hex(shaInStr[2*i]) * 16 + hex(shaInStr[2*i+1]);
        fingerprintHash2[i] = letter;
    }
    fingerprintValue = readFingerprint(fingerprintHash2, 247, 9);
    if (fingerprintValue!= 264)
        printf("FAIL - readFingerprint %lu\n", fingerprintValue);


    // Test writeFingerprint
    writeFingerprint(fingerprintHash, 8, 8, 90);
    writeFingerprint(fingerprintHash, 20, 4, 5);
    writeFingerprint(fingerprintHash, 28, 3, 6);
    if (strcmp((const char*)fingerprintHash, "0Z5=456789abcdef"))
        printf("FAIL - writeFingerprint %s\n", fingerprintHash);

    // Test hash calculation
    std::string keyStr = key("https://example.com/bla.gif", "34bfac");
    unsigned long hashValue = hash(keyStr, 2513);
    if (hashValue != 1233)
        printf("FAIL - hash calculation %lu\n", hashValue);

    // Test fingerprint
    keyStr = key("https://example.com/bla.gif", "34bfac");
    fingerprintValue = fingerprint(keyStr, 9);
    if (fingerprintValue != 264)
        printf("FAIL - fingerprint calculation %lu\n", fingerprintValue);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x2c0, %rsp            # imm = 0x2C0
movq %rdi, -0x8(%rbp)
leaq -0x29(%rbp), %rdi
movq %rdi, -0x238(%rbp)
callq 0x2340
movq -0x238(%rbp), %rdx
leaq 0x27d8(%rip), %rsi      # 0x61e5
leaq -0x28(%rbp), %rdi
callq 0x2280
jmp 0x3a18
leaq -0x29(%rbp), %rdi
callq 0x2230
leaq -0x28(%rbp), %rdi
callq 0x2100
movq %rax, %rdi
movl $0x1, %esi
movl $0x4, %edx
callq 0x2b50
movq %rax, -0x48(%rbp)
cmpq $0x32333435, -0x48(%rbp) # imm = 0x32333435
je 0x3a8b
movq -0x48(%rbp), %rsi
leaq 0x2798(%rip), %rdi      # 0x61ed
xorl %eax, %eax
callq 0x2040
jmp 0x3a5e
jmp 0x3a8b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
leaq -0x29(%rbp), %rdi
callq 0x2230
jmp 0x4154
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x414b
movb $0x31, -0x52(%rbp)
leaq -0x52(%rbp), %rdi
movq %rdi, -0x248(%rbp)
movl $0x1, %esi
movl $0x4, %edx
movl $0x32333435, %ecx       # imm = 0x32333435
callq 0x2600
movb $0x0, -0x4d(%rbp)
leaq -0x79(%rbp), %rdi
movq %rdi, -0x240(%rbp)
callq 0x2340
movq -0x240(%rbp), %rdx
leaq 0x2733(%rip), %rsi      # 0x6203
leaq -0x78(%rbp), %rdi
callq 0x2280
jmp 0x3adb
movq -0x248(%rbp), %rdi
leaq -0x78(%rbp), %rsi
callq 0x43a0
movb %al, -0x249(%rbp)
jmp 0x3af3
leaq -0x78(%rbp), %rdi
callq 0x2190
leaq -0x79(%rbp), %rdi
callq 0x2230
movb -0x249(%rbp), %al
testb $0x1, %al
jne 0x3b11
jmp 0x3b58
leaq 0x26f1(%rip), %rdi      # 0x6209
xorl %eax, %eax
leaq -0x52(%rbp), %rsi
callq 0x2040
jmp 0x3b25
jmp 0x3b58
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x3b4a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
leaq -0x78(%rbp), %rdi
callq 0x2190
leaq -0x79(%rbp), %rdi
callq 0x2230
jmp 0x414b
leaq 0x26c8(%rip), %rsi      # 0x6227
leaq -0x28(%rbp), %rdi
callq 0x2270
jmp 0x3b6a
movb $0x0, -0x80(%rbp)
leaq -0x28(%rbp), %rdi
callq 0x2100
movq %rax, %rsi
leaq -0x90(%rbp), %rdi
movq %rdi, -0x260(%rbp)
movl $0x10, %edx
callq 0x2130
movq -0x260(%rbp), %rdi
movl $0x79, %esi
movl $0x7, %edx
callq 0x2f50
movq %rax, -0x258(%rbp)
jmp 0x3bb1
movq -0x258(%rbp), %rax
movq %rax, -0x98(%rbp)
cmpq $0x66, -0x98(%rbp)
je 0x3be2
movq -0x98(%rbp), %rsi
leaq 0x2661(%rip), %rdi      # 0x6238
xorl %eax, %eax
callq 0x2040
jmp 0x3be0
jmp 0x3be2
leaq -0x90(%rbp), %rdi
movl $0x75, %esi
movl $0x7, %edx
callq 0x2f50
movq %rax, -0x268(%rbp)
jmp 0x3c01
movq -0x268(%rbp), %rax
movq %rax, -0x98(%rbp)
cmpq $0x56, -0x98(%rbp)
je 0x3c32
movq -0x98(%rbp), %rsi
leaq 0x2611(%rip), %rdi      # 0x6238
xorl %eax, %eax
callq 0x2040
jmp 0x3c30
jmp 0x3c32
leaq -0xe0(%rbp), %rdi
leaq 0x26b0(%rip), %rsi      # 0x62f0
movl $0x41, %edx
callq 0x2200
movl $0x0, -0x104(%rbp)
cmpl $0x20, -0x104(%rbp)
jge 0x3cd2
movl -0x104(%rbp), %eax
shll %eax
cltq
movzbl -0xe0(%rbp,%rax), %edi
callq 0x3960
movzbl %al, %eax
shll $0x4, %eax
movl %eax, -0x26c(%rbp)
movl -0x104(%rbp), %eax
shll %eax
addl $0x1, %eax
cltq
movzbl -0xe0(%rbp,%rax), %edi
callq 0x3960
movb %al, %cl
movl -0x26c(%rbp), %eax
movzbl %cl, %ecx
addl %ecx, %eax
movb %al, -0x105(%rbp)
movb -0x105(%rbp), %cl
movslq -0x104(%rbp), %rax
movb %cl, -0x100(%rbp,%rax)
movl -0x104(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x104(%rbp)
jmp 0x3c54
leaq -0x100(%rbp), %rdi
movl $0xf7, %esi
movl $0x9, %edx
callq 0x2f50
movq %rax, -0x278(%rbp)
jmp 0x3cf1
movq -0x278(%rbp), %rax
movq %rax, -0x98(%rbp)
cmpq $0x108, -0x98(%rbp) # imm = 0x108
je 0x3d25
movq -0x98(%rbp), %rsi
leaq 0x251e(%rip), %rdi      # 0x6238
xorl %eax, %eax
callq 0x2040
jmp 0x3d23
jmp 0x3d25
leaq -0x90(%rbp), %rdi
movl $0x8, %edx
movl $0x5a, %ecx
movl %edx, %esi
callq 0x3070
jmp 0x3d3f
leaq -0x90(%rbp), %rdi
movl $0x14, %esi
movl $0x4, %edx
movl $0x5, %ecx
callq 0x3070
jmp 0x3d5c
leaq -0x90(%rbp), %rdi
movl $0x1c, %esi
movl $0x3, %edx
movl $0x6, %ecx
callq 0x3070
jmp 0x3d79
leaq -0x90(%rbp), %rdi
leaq 0x24cd(%rip), %rsi      # 0x6254
callq 0x22a0
cmpl $0x0, %eax
je 0x3daa
leaq 0x24cd(%rip), %rdi      # 0x6265
xorl %eax, %eax
leaq -0x90(%rbp), %rsi
callq 0x2040
jmp 0x3da8
jmp 0x3daa
leaq -0x149(%rbp), %rdi
movq %rdi, -0x280(%rbp)
callq 0x2340
movq -0x280(%rbp), %rdx
leaq 0x24b6(%rip), %rsi      # 0x6281
leaq -0x148(%rbp), %rdi
callq 0x2280
jmp 0x3dd9
leaq -0x171(%rbp), %rdi
movq %rdi, -0x288(%rbp)
callq 0x2340
movq -0x288(%rbp), %rdx
leaq 0x24a3(%rip), %rsi      # 0x629d
leaq -0x170(%rbp), %rdi
callq 0x2280
jmp 0x3e08
leaq -0x128(%rbp), %rdi
leaq -0x148(%rbp), %rsi
leaq -0x170(%rbp), %rdx
callq 0x2bb0
jmp 0x3e24
leaq -0x170(%rbp), %rdi
callq 0x2190
leaq -0x171(%rbp), %rdi
callq 0x2230
leaq -0x148(%rbp), %rdi
callq 0x2190
leaq -0x149(%rbp), %rdi
callq 0x2230
leaq -0x1a0(%rbp), %rdi
leaq -0x128(%rbp), %rsi
callq 0x2110
jmp 0x3e69
leaq -0x1a0(%rbp), %rdi
movl $0x9d1, %esi            # imm = 0x9D1
callq 0x2cc0
movl %eax, -0x28c(%rbp)
jmp 0x3e82
movl -0x28c(%rbp), %eax
movl %eax, %eax
movq %rax, -0x298(%rbp)
leaq -0x1a0(%rbp), %rdi
callq 0x2190
movq -0x298(%rbp), %rax
movq %rax, -0x180(%rbp)
cmpq $0x4d1, -0x180(%rbp) # imm = 0x4D1
je 0x3f63
movq -0x180(%rbp), %rsi
leaq 0x23da(%rip), %rdi      # 0x62a4
xorl %eax, %eax
callq 0x2040
jmp 0x3ed3
jmp 0x3f63
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x3f24
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x3f0c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
leaq -0x170(%rbp), %rdi
callq 0x2190
leaq -0x171(%rbp), %rdi
callq 0x2230
leaq -0x148(%rbp), %rdi
callq 0x2190
leaq -0x149(%rbp), %rdi
callq 0x2230
jmp 0x414b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x413f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
leaq -0x1a0(%rbp), %rdi
callq 0x2190
jmp 0x413f
leaq -0x1e1(%rbp), %rdi
movq %rdi, -0x2a0(%rbp)
callq 0x2340
movq -0x2a0(%rbp), %rdx
leaq 0x22fd(%rip), %rsi      # 0x6281
leaq -0x1e0(%rbp), %rdi
callq 0x2280
jmp 0x3f92
leaq -0x209(%rbp), %rdi
movq %rdi, -0x2a8(%rbp)
callq 0x2340
movq -0x2a8(%rbp), %rdx
leaq 0x22ea(%rip), %rsi      # 0x629d
leaq -0x208(%rbp), %rdi
callq 0x2280
jmp 0x3fc1
leaq -0x1c0(%rbp), %rdi
leaq -0x1e0(%rbp), %rsi
leaq -0x208(%rbp), %rdx
callq 0x2bb0
jmp 0x3fdd
leaq -0x128(%rbp), %rdi
movq %rdi, -0x2b0(%rbp)
leaq -0x1c0(%rbp), %rsi
movq %rsi, -0x2b8(%rbp)
callq 0x2240
movq -0x2b8(%rbp), %rdi
callq 0x2190
leaq -0x208(%rbp), %rdi
callq 0x2190
leaq -0x209(%rbp), %rdi
callq 0x2230
leaq -0x1e0(%rbp), %rdi
callq 0x2190
leaq -0x1e1(%rbp), %rdi
callq 0x2230
movq -0x2b0(%rbp), %rsi
leaq -0x230(%rbp), %rdi
callq 0x2110
jmp 0x404f
leaq -0x230(%rbp), %rdi
movl $0x9, %esi
callq 0x2d60
movq %rax, -0x2c0(%rbp)
jmp 0x4069
movq -0x2c0(%rbp), %rax
movq %rax, -0x98(%rbp)
leaq -0x230(%rbp), %rdi
callq 0x2190
cmpq $0x108, -0x98(%rbp) # imm = 0x108
je 0x4121
movq -0x98(%rbp), %rsi
leaq 0x221f(%rip), %rdi      # 0x62c1
xorl %eax, %eax
callq 0x2040
jmp 0x40ab
jmp 0x4121
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x40f9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
jmp 0x40e1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
leaq -0x208(%rbp), %rdi
callq 0x2190
leaq -0x209(%rbp), %rdi
callq 0x2230
leaq -0x1e0(%rbp), %rdi
callq 0x2190
leaq -0x1e1(%rbp), %rdi
callq 0x2230
jmp 0x413f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x38(%rbp)
movl %eax, -0x3c(%rbp)
leaq -0x230(%rbp), %rdi
callq 0x2190
jmp 0x413f
leaq -0x128(%rbp), %rdi
callq 0x2190
leaq -0x28(%rbp), %rdi
callq 0x2190
addq $0x2c0, %rsp            # imm = 0x2C0
popq %rbp
retq
leaq -0x128(%rbp), %rdi
callq 0x2190
leaq -0x28(%rbp), %rdi
callq 0x2190
movq -0x38(%rbp), %rdi
callq 0x2330
nopl (%rax)