// File: /workspace/github_cpp_makefile_star2_O2/shreyas-gopalakrishna[P]Concurrent-Skip-list/unit_test_2.cpp
// Function: main
int main(int argc, char *argv[]){

    cout << "\n---------- Unit Test - 2 ----------" << endl;

    cout << "\nThis Unit test uses 8 Threads. Numbers (1-2000) are inserted into the skip list parallelly." << endl;
    cout << "Then a few numbers at random are removed from the skip list parallelly. And next a few numbers are searched in the skip list." << endl;
    cout << "Finally, few Range operations are done in the skip list parallelly. " << endl;
    cout << "This is an automated test, and only the test results are displayed. " << endl;
    

	generate_input(2000);

    skiplist = SkipList(numbers_insert.size(), 0.5);

    vector<thread> threads;
    int chunk_size;

    // insert
    try{
        chunk_size = ceil(float(numbers_insert.size()) / num_threads);
        for(size_t i = 0; i < numbers_insert.size(); i = i + chunk_size){
            threads.push_back(thread(skiplist_add, i, i+chunk_size));
        }
        for (auto &th : threads) {
            th.join();
        }
        threads.clear();
        cout << "Unit Test 1: Insert: PASS" << endl;
    }catch(const std::exception& e){
        cout << "Unit Test 1: Insert: FAIL" << endl;
    }

    // checking if insert is done
    if(skiplist.search(numbers_insert[0]) == to_string(numbers_insert[0])){
        cout << "Unit Test 2: Insert: PASS" << endl;
    }else{
        cout << "Unit Test 2: Insert: FAIL" << endl;
    }

    // checking if insert is done
    if(skiplist.search(numbers_insert[1]) == to_string(numbers_insert[1])){
        cout << "Unit Test 3: Insert: PASS" << endl;
    }else{
        cout << "Unit Test 3: Insert: FAIL" << endl;
    }

    // delete
    try{
        chunk_size = ceil(float(numbers_delete.size()) / num_threads);
        for(size_t i = 0; i < numbers_delete.size(); i = i + chunk_size){
            threads.push_back(thread(skiplist_remove, i, i+chunk_size));
        }
        for (auto &th : threads) {
            th.join();
        }
        threads.clear();
        cout << "Unit Test 4: Delete: PASS" << endl;
    }catch(const std::exception& e){
        cout << "Unit Test 4: Delete: FAIL" << endl;
    }

    // checking if delete is done
    if(skiplist.search(numbers_delete[0]) == ""){
        cout << "Unit Test 5: Delete: PASS" << endl;
    }else{
        cout << "Unit Test 5: Delete: FAIL" << endl;
    }

    // checking if delete is done
    if(skiplist.search(numbers_delete[1]) == ""){
        cout << "Unit Test 6: Delete: PASS" << endl;
    }else{
        cout << "Unit Test 6: Delete: FAIL" << endl;
    }

    // search
    try{
        chunk_size = ceil(float(numbers_get.size()) / num_threads);
        for(size_t i = 0; i < numbers_get.size(); i = i + chunk_size){
            threads.push_back(thread(skiplist_search, i, i+chunk_size));
        }
        for (auto &th : threads) {
            th.join();
        }
        threads.clear();
        cout << "Unit Test 7: Search: PASS" << endl;
    }catch(const std::exception& e){
        cout << "Unit Test 7: Search: FAIL" << endl;
    }

    // checking if search is done
    if(skiplist.search(numbers_get[0]) == to_string(numbers_get[0]) || skiplist.search(numbers_get[0]) == ""){
        cout << "Unit Test 8: Search: PASS" << endl;
    }else{
        cout << "Unit Test 8: Insert: FAIL" << endl;
    }

    // checking if Search is done
    if(skiplist.search(numbers_delete[0]) == ""){
        cout << "Unit Test 9: Search: PASS" << endl;
    }else{
        cout << "Unit Test 9: Search: FAIL" << endl;
    }
    
    // ranges
    try{
        for(size_t i = 0; i < num_threads; i++){
            threads.push_back(thread(skiplist_range, numbers_range[i].first, numbers_range[i].second));
        }
        for (auto &th : threads) {
            th.join();
        }
        threads.clear();
        cout << "Unit Test 10: Range: PASS" << endl;
    }catch(const std::exception& e){
        cout << "Unit Test 10: Range: FAIL" << endl;
    }

    map<int, string> range_output = skiplist.range(1, 2000);

    // checking range
    if(range_output.count(numbers_delete[0]) == 0){
        cout << "Unit Test 11: Range: PASS" << endl;
    }else{
        cout << "Unit Test 11: Range: FAIL" << endl;
    }

    return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x88, %rsp
movq 0x77c7(%rip), %rbx      # 0x9fd0
leaq 0x3810(%rip), %rsi      # 0x6020
movq %rbx, %rdi
callq 0x21c0
movq %rax, %rdi
callq 0x20f0
leaq 0x381e(%rip), %rsi      # 0x6045
movq %rbx, %rdi
callq 0x21c0
movq %rax, %rdi
callq 0x20f0
leaq 0x3864(%rip), %rsi      # 0x60a2
movq %rbx, %rdi
callq 0x21c0
movq %rax, %rdi
callq 0x20f0
leaq 0x38cb(%rip), %rsi      # 0x6120
movq %rbx, %rdi
callq 0x21c0
movq %rax, %rdi
callq 0x20f0
leaq 0x38f9(%rip), %rsi      # 0x6165
movq %rbx, %rdi
callq 0x21c0
movq %rax, %rdi
callq 0x20f0
movl $0x7d0, %edi            # imm = 0x7D0
callq 0x24fc
movq 0x793b(%rip), %rsi      # 0xa1c8
subq 0x792c(%rip), %rsi      # 0xa1c0
shrq $0x2, %rsi
leaq 0x18(%rsp), %rbx
movss 0x375f(%rip), %xmm0     # 0x6004
movq %rbx, %rdi
callq 0x4124
movups (%rbx), %xmm0
movups %xmm0, 0x78f9(%rip)     # 0xa1b0
movq %rbx, %rdi
callq 0x4e30
xorps %xmm0, %xmm0
movaps %xmm0, (%rsp)
andq $0x0, 0x10(%rsp)
movq 0x78f5(%rip), %rbp      # 0xa1c8
movq 0x78e6(%rip), %rbx      # 0xa1c0
movq %rbp, %rax
subq %rbx, %rax
sarq $0x2, %rax
js 0x28ed
cvtsi2ss %rax, %xmm0
jmp 0x2902
movq %rax, %rcx
shrq %rcx
andl $0x1, %eax
orq %rcx, %rax
cvtsi2ss %rax, %xmm0
addss %xmm0, %xmm0
movq 0x7877(%rip), %rax      # 0xa180
testq %rax, %rax
js 0x2915
cvtsi2ss %rax, %xmm1
jmp 0x292a
movq %rax, %rcx
shrq %rcx
andl $0x1, %eax
orq %rcx, %rax
cvtsi2ss %rax, %xmm1
addss %xmm1, %xmm1
divss %xmm1, %xmm0
callq 0x2120
cvttss2si %xmm0, %eax
movslq %eax, %r15
xorl %eax, %eax
leaq 0x48(%rsp), %r14
leaq 0x68(%rsp), %r12
movq %rsp, %r13
subq %rbx, %rbp
movq %rax, 0x18(%rsp)
sarq $0x2, %rbp
cmpq %rbp, %rax
jae 0x29a4
addq %r15, %rax
movq %rax, 0x68(%rsp)
movq %r14, %rdi
leaq -0x331(%rip), %rsi      # 0x263b
leaq 0x18(%rsp), %rdx
movq %r12, %rcx
callq 0x328a
movq %r13, %rdi
movq %r14, %rsi
callq 0x38c0
movq %r14, %rdi
callq 0x330c
movq 0x18(%rsp), %rax
addq %r15, %rax
movq 0x782d(%rip), %rbp      # 0xa1c8
movq 0x781e(%rip), %rbx      # 0xa1c0
jmp 0x2949
movq (%rsp), %rbx
movq 0x8(%rsp), %r14
cmpq %r14, %rbx
je 0x29c0
movq %rbx, %rdi
callq 0x22a0
addq $0x8, %rbx
jmp 0x29ad
movq %rsp, %rdi
callq 0x331a
movq 0x7601(%rip), %rdi      # 0x9fd0
leaq 0x37d4(%rip), %rsi      # 0x61aa
callq 0x21c0
movq %rax, %rdi
callq 0x20f0
movq 0x77d6(%rip), %rax      # 0xa1c0
movl (%rax), %edx
leaq 0x77bd(%rip), %rsi      # 0xa1b0
leaq 0x18(%rsp), %rdi
callq 0x4670
movq 0x77bc(%rip), %rax      # 0xa1c0
movl (%rax), %esi
leaq 0x48(%rsp), %rdi
callq 0x3230
leaq 0x18(%rsp), %rbx
leaq 0x48(%rsp), %r14
movq %rbx, %rdi
movq %r14, %rsi
callq 0x332d
movl %eax, %ebp
movq %r14, %rdi
callq 0x20d0
movq %rbx, %rdi
callq 0x20d0
leaq 0x37a0(%rip), %rax      # 0x61de
leaq 0x37b3(%rip), %rsi      # 0x61f8
testb %bpl, %bpl
cmovneq %rax, %rsi
movq 0x757d(%rip), %rdi      # 0x9fd0
callq 0x21c0
movq %rax, %rdi
callq 0x20f0
movq 0x7759(%rip), %rax      # 0xa1c0
movl 0x4(%rax), %edx
leaq 0x773f(%rip), %rsi      # 0xa1b0
leaq 0x18(%rsp), %rdi
callq 0x4670
movq 0x773e(%rip), %rax      # 0xa1c0
movl 0x4(%rax), %esi
leaq 0x48(%rsp), %rdi
callq 0x3230
leaq 0x18(%rsp), %rbx
leaq 0x48(%rsp), %r14
movq %rbx, %rdi
movq %r14, %rsi
callq 0x332d
movl %eax, %ebp
movq %r14, %rdi
callq 0x20d0
movq %rbx, %rdi
callq 0x20d0
leaq 0x3755(%rip), %rax      # 0x6212
leaq 0x3768(%rip), %rsi      # 0x622c
testb %bpl, %bpl
cmovneq %rax, %rsi
movq 0x74fe(%rip), %rdi      # 0x9fd0
callq 0x21c0
movq %rax, %rdi
callq 0x20f0
movq 0x76fa(%rip), %rbp      # 0xa1e0
movq 0x76eb(%rip), %rbx      # 0xa1d8
movq %rbp, %rax
subq %rbx, %rax
sarq $0x2, %rax
js 0x2b00
cvtsi2ss %rax, %xmm0
jmp 0x2b15
movq %rax, %rcx
shrq %rcx
andl $0x1, %eax
orq %rcx, %rax
cvtsi2ss %rax, %xmm0
addss %xmm0, %xmm0
movq 0x7664(%rip), %rax      # 0xa180
testq %rax, %rax
js 0x2b28
cvtsi2ss %rax, %xmm1
jmp 0x2b3d
movq %rax, %rcx
shrq %rcx
andl $0x1, %eax
orq %rcx, %rax
cvtsi2ss %rax, %xmm1
addss %xmm1, %xmm1
divss %xmm1, %xmm0
callq 0x2120
cvttss2si %xmm0, %eax
movslq %eax, %r15
xorl %eax, %eax
leaq 0x48(%rsp), %r14
leaq 0x68(%rsp), %r12
movq %rsp, %r13
subq %rbx, %rbp
movq %rax, 0x18(%rsp)
sarq $0x2, %rbp
cmpq %rbp, %rax
jae 0x2bb7
addq %r15, %rax
movq %rax, 0x68(%rsp)
movq %r14, %rdi
leaq -0x48b(%rip), %rsi      # 0x26f4
leaq 0x18(%rsp), %rdx
movq %r12, %rcx
callq 0x328a
movq %r13, %rdi
movq %r14, %rsi
callq 0x38c0
movq %r14, %rdi
callq 0x330c
movq 0x18(%rsp), %rax
addq %r15, %rax
movq 0x7632(%rip), %rbp      # 0xa1e0
movq 0x7623(%rip), %rbx      # 0xa1d8
jmp 0x2b5c
movq (%rsp), %rbx
movq 0x8(%rsp), %r14
cmpq %r14, %rbx
je 0x2bd3
movq %rbx, %rdi
callq 0x22a0
addq $0x8, %rbx
jmp 0x2bc0
movq %rsp, %rdi
callq 0x331a
movq 0x73ee(%rip), %rdi      # 0x9fd0
leaq 0x365d(%rip), %rsi      # 0x6246
callq 0x21c0
movq %rax, %rdi
callq 0x20f0
movq 0x75db(%rip), %rax      # 0xa1d8
movl (%rax), %edx
leaq 0x75aa(%rip), %rsi      # 0xa1b0
leaq 0x18(%rsp), %rdi
callq 0x4670
leaq 0x39e4(%rip), %rsi      # 0x65fb
leaq 0x18(%rsp), %rbx
movq %rbx, %rdi
callq 0x3356
movl %eax, %ebp
movq %rbx, %rdi
callq 0x20d0
leaq 0x3645(%rip), %rax      # 0x627a
leaq 0x3658(%rip), %rsi      # 0x6294
testb %bpl, %bpl
cmovneq %rax, %rsi
movq 0x7386(%rip), %rdi      # 0x9fd0
callq 0x21c0
movq %rax, %rdi
callq 0x20f0
movq 0x757a(%rip), %rax      # 0xa1d8
movl 0x4(%rax), %edx
leaq 0x7548(%rip), %rsi      # 0xa1b0
leaq 0x18(%rsp), %rdi
callq 0x4670
leaq 0x3982(%rip), %rsi      # 0x65fb
leaq 0x18(%rsp), %rbx
movq %rbx, %rdi
callq 0x3356
movl %eax, %ebp
movq %rbx, %rdi
callq 0x20d0
leaq 0x3617(%rip), %rax      # 0x62ae
leaq 0x362a(%rip), %rsi      # 0x62c8
testb %bpl, %bpl
cmovneq %rax, %rsi
movq 0x7324(%rip), %rdi      # 0x9fd0
callq 0x21c0
movq %rax, %rdi
callq 0x20f0
movq 0x7538(%rip), %rbp      # 0xa1f8
movq 0x7529(%rip), %rbx      # 0xa1f0
movq %rbp, %rax
subq %rbx, %rax
sarq $0x2, %rax
js 0x2cda
cvtsi2ss %rax, %xmm0
jmp 0x2cef
movq %rax, %rcx
shrq %rcx
andl $0x1, %eax
orq %rcx, %rax
cvtsi2ss %rax, %xmm0
addss %xmm0, %xmm0
movq 0x748a(%rip), %rax      # 0xa180
testq %rax, %rax
js 0x2d02
cvtsi2ss %rax, %xmm1
jmp 0x2d17
movq %rax, %rcx
shrq %rcx
andl $0x1, %eax
orq %rcx, %rax
cvtsi2ss %rax, %xmm1
addss %xmm1, %xmm1
divss %xmm1, %xmm0
callq 0x2120
cvttss2si %xmm0, %eax
movslq %eax, %r15
xorl %eax, %eax
leaq 0x48(%rsp), %r14
leaq 0x68(%rsp), %r12
movq %rsp, %r13
subq %rbx, %rbp
movq %rax, 0x18(%rsp)
sarq $0x2, %rbp
cmpq %rbp, %rax
jae 0x2d91
addq %r15, %rax
movq %rax, 0x68(%rsp)
movq %r14, %rdi
leaq -0x604(%rip), %rsi      # 0x2755
leaq 0x18(%rsp), %rdx
movq %r12, %rcx
callq 0x328a
movq %r13, %rdi
movq %r14, %rsi
callq 0x38c0
movq %r14, %rdi
callq 0x330c
movq 0x18(%rsp), %rax
addq %r15, %rax
movq 0x7470(%rip), %rbp      # 0xa1f8
movq 0x7461(%rip), %rbx      # 0xa1f0
jmp 0x2d36
movq (%rsp), %rbx
movq 0x8(%rsp), %r14
cmpq %r14, %rbx
je 0x2dad
movq %rbx, %rdi
callq 0x22a0
addq $0x8, %rbx
jmp 0x2d9a
movq %rsp, %rdi
callq 0x331a
movq 0x7214(%rip), %rdi      # 0x9fd0
leaq 0x351f(%rip), %rsi      # 0x62e2
callq 0x21c0
movq %rax, %rdi
callq 0x20f0
movq 0x7419(%rip), %rax      # 0xa1f0
movl (%rax), %edx
leaq 0x73d0(%rip), %rsi      # 0xa1b0
leaq 0x18(%rsp), %rdi
callq 0x4670
movq 0x73ff(%rip), %rax      # 0xa1f0
movl (%rax), %esi
leaq 0x48(%rsp), %rdi
callq 0x3230
leaq 0x18(%rsp), %rdi
leaq 0x48(%rsp), %rsi
callq 0x332d
testb %al, %al
je 0x2e2d
leaq 0x48(%rsp), %rdi
callq 0x20d0
leaq 0x18(%rsp), %rdi
callq 0x20d0
leaq 0x34eb(%rip), %rsi      # 0x6316
jmp 0x2e8e
movq 0x73bc(%rip), %rax      # 0xa1f0
movl (%rax), %edx
leaq 0x7373(%rip), %rsi      # 0xa1b0
leaq 0x68(%rsp), %rdi
callq 0x4670
leaq 0x37ad(%rip), %rsi      # 0x65fb
leaq 0x68(%rsp), %rbx
movq %rbx, %rdi
callq 0x3356
movl %eax, %ebp
movq %rbx, %rdi
callq 0x20d0
leaq 0x48(%rsp), %rdi
callq 0x20d0
leaq 0x18(%rsp), %rdi
callq 0x20d0
leaq 0x3496(%rip), %rax      # 0x6316
leaq 0x34a9(%rip), %rsi      # 0x6330
testb %bpl, %bpl
cmovneq %rax, %rsi
movq 0x713b(%rip), %rdi      # 0x9fd0
callq 0x21c0
movq %rax, %rdi
callq 0x20f0
movq 0x732f(%rip), %rax      # 0xa1d8
movl (%rax), %edx
leaq 0x72fe(%rip), %rsi      # 0xa1b0
leaq 0x18(%rsp), %rdi
callq 0x4670
leaq 0x3738(%rip), %rsi      # 0x65fb
leaq 0x18(%rsp), %rbx
movq %rbx, %rdi
callq 0x3356
movl %eax, %ebp
movq %rbx, %rdi
callq 0x20d0
leaq 0x3469(%rip), %rax      # 0x634a
leaq 0x347c(%rip), %rsi      # 0x6364
testb %bpl, %bpl
cmovneq %rax, %rsi
movq 0x70da(%rip), %rdi      # 0x9fd0
callq 0x21c0
movq %rax, %rdi
callq 0x20f0
pushq $0x4
popq %r12
xorl %r13d, %r13d
leaq -0x749(%rip), %rbx      # 0x27c8
leaq 0x18(%rsp), %r14
movq %rsp, %r15
cmpq 0x7260(%rip), %r13      # 0xa180
jae 0x2f5b
movq 0x72df(%rip), %rcx      # 0xa208
leaq (%rcx,%r12), %rdx
addq $-0x4, %rdx
addq %r12, %rcx
movq %r14, %rdi
movq %rbx, %rsi
callq 0x3364
movq %r15, %rdi
movq %r14, %rsi
callq 0x38c0
movq %r14, %rdi
callq 0x330c
incq %r13
addq $0x8, %r12
jmp 0x2f19
movq (%rsp), %rbx
movq 0x8(%rsp), %r14
cmpq %r14, %rbx
je 0x2f77
movq %rbx, %rdi
callq 0x22a0
addq $0x8, %rbx
jmp 0x2f64
movq %rsp, %rdi
callq 0x331a
movq 0x704a(%rip), %rdi      # 0x9fd0
leaq 0x33f1(%rip), %rsi      # 0x637e
callq 0x21c0
movq %rax, %rdi
callq 0x20f0
leaq 0x720f(%rip), %rsi      # 0xa1b0
leaq 0x18(%rsp), %rdi
pushq $0x1
popq %rdx
movl $0x7d0, %ecx            # imm = 0x7D0
callq 0x4b30
movq 0x721e(%rip), %rsi      # 0xa1d8
leaq 0x18(%rsp), %rdi
callq 0x33e2
testq %rax, %rax
leaq 0x33e4(%rip), %rax      # 0x63b2
leaq 0x33f7(%rip), %rsi      # 0x63cc
cmoveq %rax, %rsi
movq 0x6ff0(%rip), %rdi      # 0x9fd0
callq 0x21c0
movq %rax, %rdi
callq 0x20f0
leaq 0x18(%rsp), %rdi
callq 0x34b6
movq %rsp, %rdi
callq 0x33fc
xorl %eax, %eax
addq $0x88, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
leaq 0x48(%rsp), %rdi
callq 0x20d0
jmp 0x3035
jmp 0x3063
jmp 0x3063
jmp 0x3032
jmp 0x3063
jmp 0x3063
jmp 0x3063
jmp 0x3032
jmp 0x3063
movq %rax, %rbx
leaq 0x18(%rsp), %rdi
callq 0x20d0
jmp 0x3066
jmp 0x3063
jmp 0x3096
jmp 0x30ed
jmp 0x314e
jmp 0x31af
movq %rax, %rbx
leaq 0x18(%rsp), %rdi
callq 0x34b6
jmp 0x3066
movq %rax, %rbx
movq %rsp, %rdi
callq 0x33fc
movq %rbx, %rdi
callq 0x22b0
jmp 0x3096
jmp 0x30ed
jmp 0x314e
jmp 0x31af
movq %rdx, %r14
movq %rax, %rbx
leaq 0x18(%rsp), %rdi
callq 0x330c
jmp 0x309c
movq %rdx, %r14
movq %rax, %rbx
cmpl $0x1, %r14d
jne 0x3066
movq %rbx, %rdi
callq 0x2090
movq 0x6f1f(%rip), %rdi      # 0x9fd0
leaq 0x32e0(%rip), %rsi      # 0x6398
callq 0x21c0
movq %rax, %rdi
callq 0x20f0
callq 0x2290
jmp 0x2f9a
jmp 0x3063
movq %rax, %rbx
callq 0x2290
jmp 0x3066
movq %rdx, %r14
movq %rax, %rbx
leaq 0x48(%rsp), %rdi
callq 0x330c
jmp 0x30f3
movq %rdx, %r14
movq %rax, %rbx
cmpl $0x1, %r14d
jne 0x3066
movq %rbx, %rdi
callq 0x2090
movq 0x6ec4(%rip), %rdi      # 0x9fd0
leaq 0x31e9(%rip), %rsi      # 0x62fc
callq 0x21c0
movq %rax, %rdi
callq 0x20f0
callq 0x2290
jmp 0x2dd0
jmp 0x3063
movq %rax, %rbx
callq 0x2290
jmp 0x3066
movq %rdx, %r14
movq %rax, %rbx
leaq 0x48(%rsp), %rdi
callq 0x330c
jmp 0x3154
movq %rdx, %r14
movq %rax, %rbx
cmpl $0x1, %r14d
jne 0x3066
movq %rbx, %rdi
callq 0x2090
movq 0x6e63(%rip), %rdi      # 0x9fd0
leaq 0x30ec(%rip), %rsi      # 0x6260
callq 0x21c0
movq %rax, %rdi
callq 0x20f0
callq 0x2290
jmp 0x2bf6
jmp 0x3063
movq %rax, %rbx
callq 0x2290
jmp 0x3066
movq %rdx, %r14
movq %rax, %rbx
leaq 0x48(%rsp), %rdi
callq 0x330c
jmp 0x31b5
movq %rdx, %r14
movq %rax, %rbx
cmpl $0x1, %r14d
jne 0x3066
movq %rbx, %rdi
callq 0x2090
movq 0x6e02(%rip), %rdi      # 0x9fd0
leaq 0x2fef(%rip), %rsi      # 0x61c4
callq 0x21c0
movq %rax, %rdi
callq 0x20f0
callq 0x2290
jmp 0x29e3
jmp 0x3063
movq %rax, %rbx
callq 0x2290
jmp 0x3066
movq %rax, %rdi
callq 0x3322