// File: yoavweiss[P]cache-digests-cuckoo/cuckoo_test.cpp
// Function: main
int main() {
    const unsigned MaxCount = 500;
    const unsigned DigestSize = 1021;
    const unsigned URLNumber = 3250;

    // Create a digest
    Cuckoo cuckoo(8, DigestSize, MaxCount);

    // Run a set of sanity tests
    cuckoo.runTests();

    unsigned char* digest = cuckoo.getDigest();
    size_t digestSize = cuckoo.getDigestSize();

    std::vector<std::string> urls;
    for (int i = 0; i < URLNumber; ++i) {
        urls.push_back(std::to_string(i));
    }
    unsigned minmaxcount = 500;
    for (auto& url : urls) {
        unsigned maxcount = cuckoo.add(url, std::string());
        if (maxcount < minmaxcount)
            minmaxcount = maxcount;
    }
    printf("Maximum cucko pushes %u\n", MaxCount - minmaxcount);

    // Write the digest to disk
    std::ofstream outfile;
    outfile.open("digest.bin", std::ios::binary);
    if (outfile.is_open()) {
        outfile.write((const char*)cuckoo.getDigest(), cuckoo.getDigestSize());
        outfile.close();
    }

    // See if the URLs are in the digest
    for (auto& url : urls) {
        if (!cuckoo.query(url, std::string()))
            printf("FAIL - %s is not in the digest\n", url.c_str());
    }
    if (cuckoo.query("blabla", std::string()))
        printf("FAIL - blabla should not be in the digest\n");

    // Remove from the digest
    for (auto& url : urls) {
        cuckoo.remove(url, std::string());
    }
    // Make sure that the URLs are no longer in the digest
    for (auto& url : urls) {
        if (cuckoo.query(url, std::string()))
            printf("FAIL - %s is still in the digest\n", url.c_str());
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x4f0, %rsp            # imm = 0x4F0
movl $0x0, -0x4(%rbp)
movl $0x1f4, -0x8(%rbp)      # imm = 0x1F4
movl $0x3fd, -0xc(%rbp)      # imm = 0x3FD
movl $0xcb2, -0x10(%rbp)     # imm = 0xCB2
leaq -0x28(%rbp), %rdi
movq %rdi, -0x468(%rbp)
movl $0x8, %esi
movl $0x3fd, %edx            # imm = 0x3FD
movl $0x1f4, %ecx            # imm = 0x1F4
callq 0x24a0
movq -0x468(%rbp), %rdi
callq 0x39e0
jmp 0x44d4
leaq -0x28(%rbp), %rdi
callq 0x4c20
movq %rax, -0x470(%rbp)
jmp 0x44e6
movq -0x470(%rbp), %rax
movq %rax, -0x40(%rbp)
leaq -0x28(%rbp), %rdi
callq 0x4c40
movq %rax, -0x478(%rbp)
jmp 0x4503
movq -0x478(%rbp), %rax
movq %rax, -0x48(%rbp)
leaq -0x60(%rbp), %rdi
callq 0x4c60
movl $0x0, -0x64(%rbp)
cmpl $0xcb2, -0x64(%rbp)     # imm = 0xCB2
jae 0x45a0
movl -0x64(%rbp), %esi
leaq -0x88(%rbp), %rdi
callq 0x4cb0
jmp 0x4538
leaq -0x60(%rbp), %rdi
leaq -0x88(%rbp), %rsi
callq 0x4c80
jmp 0x454a
leaq -0x88(%rbp), %rdi
callq 0x2190
movl -0x64(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x64(%rbp)
jmp 0x451e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
jmp 0x4c06
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
jmp 0x4bfd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
leaq -0x88(%rbp), %rdi
callq 0x2190
jmp 0x4bfd
movl $0x1f4, -0x8c(%rbp)     # imm = 0x1F4
leaq -0x60(%rbp), %rax
movq %rax, -0x98(%rbp)
movq -0x98(%rbp), %rdi
callq 0x4dd0
movq %rax, -0xa0(%rbp)
movq -0x98(%rbp), %rdi
callq 0x4e00
movq %rax, -0xa8(%rbp)
leaq -0xa0(%rbp), %rdi
leaq -0xa8(%rbp), %rsi
callq 0x4e30
testb $0x1, %al
jne 0x45f7
jmp 0x46cd
leaq -0xa0(%rbp), %rdi
callq 0x4e70
movq %rax, -0xb0(%rbp)
movq -0xb0(%rbp), %rsi
leaq -0xd8(%rbp), %rdi
callq 0x2110
jmp 0x461f
leaq -0xf8(%rbp), %rdi
movq %rdi, -0x488(%rbp)
callq 0x2290
movq -0x488(%rbp), %rdx
leaq -0x28(%rbp), %rdi
leaq -0xd8(%rbp), %rsi
callq 0x26a0
movl %eax, -0x47c(%rbp)
jmp 0x4651
leaq -0xf8(%rbp), %rdi
callq 0x2190
leaq -0xd8(%rbp), %rdi
callq 0x2190
movl -0x47c(%rbp), %eax
movl %eax, -0xb4(%rbp)
movl -0xb4(%rbp), %eax
cmpl -0x8c(%rbp), %eax
jae 0x46ba
movl -0xb4(%rbp), %eax
movl %eax, -0x8c(%rbp)
jmp 0x46ba
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
leaq -0xf8(%rbp), %rdi
callq 0x2190
leaq -0xd8(%rbp), %rdi
callq 0x2190
jmp 0x4bfd
jmp 0x46bc
leaq -0xa0(%rbp), %rdi
callq 0x4e90
jmp 0x45db
movl -0x8c(%rbp), %eax
movl $0x1f4, %esi            # imm = 0x1F4
subl %eax, %esi
leaq 0x1c50(%rip), %rdi      # 0x6331
xorl %eax, %eax
callq 0x2040
jmp 0x46ea
leaq -0x2f8(%rbp), %rdi
callq 0x2300
jmp 0x46f8
leaq 0x1c4b(%rip), %rsi      # 0x634a
leaq -0x2f8(%rbp), %rdi
movl $0x4, %edx
callq 0x2050
jmp 0x4712
leaq -0x2f8(%rbp), %rdi
callq 0x21e0
movb %al, -0x489(%rbp)
jmp 0x4726
movb -0x489(%rbp), %al
testb $0x1, %al
jne 0x4732
jmp 0x4793
leaq -0x28(%rbp), %rdi
callq 0x4c20
movq %rax, -0x498(%rbp)
jmp 0x4744
leaq -0x28(%rbp), %rdi
callq 0x4c40
movq %rax, -0x4a0(%rbp)
jmp 0x4756
movq -0x4a0(%rbp), %rdx
movq -0x498(%rbp), %rsi
leaq -0x2f8(%rbp), %rdi
callq 0x2260
jmp 0x4772
leaq -0x2f8(%rbp), %rdi
callq 0x22b0
jmp 0x4780
jmp 0x4793
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
jmp 0x4bf1
leaq -0x60(%rbp), %rax
movq %rax, -0x300(%rbp)
movq -0x300(%rbp), %rdi
callq 0x4dd0
movq %rax, -0x308(%rbp)
movq -0x300(%rbp), %rdi
callq 0x4e00
movq %rax, -0x310(%rbp)
leaq -0x308(%rbp), %rdi
leaq -0x310(%rbp), %rsi
callq 0x4e30
testb $0x1, %al
jne 0x47e0
jmp 0x48c9
leaq -0x308(%rbp), %rdi
callq 0x4e70
movq %rax, -0x318(%rbp)
movq -0x318(%rbp), %rsi
leaq -0x338(%rbp), %rdi
callq 0x2110
jmp 0x4808
leaq -0x358(%rbp), %rdi
movq %rdi, -0x4b0(%rbp)
callq 0x2290
movq -0x4b0(%rbp), %rdx
leaq -0x28(%rbp), %rdi
leaq -0x338(%rbp), %rsi
callq 0x35b0
movb %al, -0x4a1(%rbp)
jmp 0x483a
movb -0x4a1(%rbp), %al
xorb $-0x1, %al
movb %al, -0x4b1(%rbp)
leaq -0x358(%rbp), %rdi
callq 0x2190
leaq -0x338(%rbp), %rdi
callq 0x2190
movb -0x4b1(%rbp), %al
testb $0x1, %al
jne 0x486c
jmp 0x48b6
movq -0x318(%rbp), %rdi
callq 0x2100
movq %rax, %rsi
leaq 0x1ad3(%rip), %rdi      # 0x6355
xorl %eax, %eax
callq 0x2040
jmp 0x488b
jmp 0x48b6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
leaq -0x358(%rbp), %rdi
callq 0x2190
leaq -0x338(%rbp), %rdi
callq 0x2190
jmp 0x4bf1
jmp 0x48b8
leaq -0x308(%rbp), %rdi
callq 0x4e90
jmp 0x47c4
leaq -0x379(%rbp), %rdi
movq %rdi, -0x4c0(%rbp)
callq 0x2340
movq -0x4c0(%rbp), %rdx
leaq 0x1a8b(%rip), %rsi      # 0x6375
leaq -0x378(%rbp), %rdi
callq 0x2280
jmp 0x48f8
leaq -0x3a0(%rbp), %rdi
movq %rdi, -0x4d0(%rbp)
callq 0x2290
movq -0x4d0(%rbp), %rdx
leaq -0x28(%rbp), %rdi
leaq -0x378(%rbp), %rsi
callq 0x35b0
movb %al, -0x4c1(%rbp)
jmp 0x492a
leaq -0x3a0(%rbp), %rdi
callq 0x2190
leaq -0x378(%rbp), %rdi
callq 0x2190
leaq -0x379(%rbp), %rdi
callq 0x2230
movb -0x4c1(%rbp), %al
testb $0x1, %al
jne 0x495a
jmp 0x49af
leaq 0x1a1b(%rip), %rdi      # 0x637c
xorl %eax, %eax
callq 0x2040
jmp 0x496a
jmp 0x49af
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
jmp 0x499e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
leaq -0x3a0(%rbp), %rdi
callq 0x2190
leaq -0x378(%rbp), %rdi
callq 0x2190
leaq -0x379(%rbp), %rdi
callq 0x2230
jmp 0x4bf1
leaq -0x60(%rbp), %rax
movq %rax, -0x3a8(%rbp)
movq -0x3a8(%rbp), %rdi
callq 0x4dd0
movq %rax, -0x3b0(%rbp)
movq -0x3a8(%rbp), %rdi
callq 0x4e00
movq %rax, -0x3b8(%rbp)
leaq -0x3b0(%rbp), %rdi
leaq -0x3b8(%rbp), %rsi
callq 0x4e30
testb $0x1, %al
jne 0x49fc
jmp 0x4aa2
leaq -0x3b0(%rbp), %rdi
callq 0x4e70
movq %rax, -0x3c0(%rbp)
movq -0x3c0(%rbp), %rsi
leaq -0x3e0(%rbp), %rdi
callq 0x2110
jmp 0x4a24
leaq -0x400(%rbp), %rdi
movq %rdi, -0x4d8(%rbp)
callq 0x2290
movq -0x4d8(%rbp), %rdx
leaq -0x28(%rbp), %rdi
leaq -0x3e0(%rbp), %rsi
callq 0x31f0
jmp 0x4a50
leaq -0x400(%rbp), %rdi
callq 0x2190
leaq -0x3e0(%rbp), %rdi
callq 0x2190
leaq -0x3b0(%rbp), %rdi
callq 0x4e90
jmp 0x49e0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
leaq -0x400(%rbp), %rdi
callq 0x2190
leaq -0x3e0(%rbp), %rdi
callq 0x2190
jmp 0x4bf1
leaq -0x60(%rbp), %rax
movq %rax, -0x408(%rbp)
movq -0x408(%rbp), %rdi
callq 0x4dd0
movq %rax, -0x410(%rbp)
movq -0x408(%rbp), %rdi
callq 0x4e00
movq %rax, -0x418(%rbp)
leaq -0x410(%rbp), %rdi
leaq -0x418(%rbp), %rsi
callq 0x4e30
testb $0x1, %al
jne 0x4aef
jmp 0x4bc7
leaq -0x410(%rbp), %rdi
callq 0x4e70
movq %rax, -0x420(%rbp)
movq -0x420(%rbp), %rsi
leaq -0x440(%rbp), %rdi
callq 0x2110
jmp 0x4b17
leaq -0x460(%rbp), %rdi
movq %rdi, -0x4e8(%rbp)
callq 0x2290
movq -0x4e8(%rbp), %rdx
leaq -0x28(%rbp), %rdi
leaq -0x440(%rbp), %rsi
callq 0x35b0
movb %al, -0x4d9(%rbp)
jmp 0x4b49
leaq -0x460(%rbp), %rdi
callq 0x2190
leaq -0x440(%rbp), %rdi
callq 0x2190
movb -0x4d9(%rbp), %al
testb $0x1, %al
jne 0x4b6d
jmp 0x4bb4
movq -0x420(%rbp), %rdi
callq 0x2100
movq %rax, %rsi
leaq 0x1824(%rip), %rdi      # 0x63a7
xorl %eax, %eax
callq 0x2040
jmp 0x4b8c
jmp 0x4bb4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
leaq -0x460(%rbp), %rdi
callq 0x2190
leaq -0x440(%rbp), %rdi
callq 0x2190
jmp 0x4bf1
jmp 0x4bb6
leaq -0x410(%rbp), %rdi
callq 0x4e90
jmp 0x4ad3
leaq -0x2f8(%rbp), %rdi
callq 0x22c0
leaq -0x60(%rbp), %rdi
callq 0x4eb0
leaq -0x28(%rbp), %rdi
callq 0x2670
movl -0x4(%rbp), %eax
addq $0x4f0, %rsp            # imm = 0x4F0
popq %rbp
retq
leaq -0x2f8(%rbp), %rdi
callq 0x22c0
leaq -0x60(%rbp), %rdi
callq 0x4eb0
leaq -0x28(%rbp), %rdi
callq 0x2670
movq -0x30(%rbp), %rdi
callq 0x2330
nopl (%rax,%rax)