// File: obliviousram[P]PathOHeap/src/PlainHeapComparisonTest.cpp
// Function: PlainHeapComparisonTest::run()
void PlainHeapComparisonTest::run() {
  int bucket_size = 3;
  int num_blocks = pow(2, 20);
  this->max_heap_size = num_blocks;
  UntrustedStorageInterface* storage = new ServerStorage();
  RandForOHeapInterface* random = new RandomForOHeap();
  OHeapInterface* oheap = new OHeapReadPathEviction(storage, random, bucket_size, num_blocks, false);

  // Test: compare the OHeap to a 'plain' heap by performing several million random operations on
  // both, making sure that the results match.

  // Since C++ heaps use "pop max" while this OHeap implementation uses "pop min", negate all items
  // in the plain heap.

  const int num_ops = 10000000;
  const int frequency = 10000;

  for (int i = 1; i <= num_ops; i++) {
    std::pair<Operation, int> op_v = this->randomOp();
    Operation op = op_v.first;
    int v = op_v.second;

    if (op == PUSH) {
      this->plain_heap.push_back(-v);
      std::push_heap(this->plain_heap.begin(), this->plain_heap.end());
      
      oheap->insertBlock(v, this->sampleData(v));
    } else if (op == POP) {
      std::pop_heap(this->plain_heap.begin(), this->plain_heap.end());
      int plain_v = -this->plain_heap.back();
      this->plain_heap.pop_back();

      int oheap_v = oheap->extractMin().k;

      if (plain_v != oheap_v) {
        std::cout << "Error! " << plain_v << " and " << oheap_v << " don't match!" << std::endl;
      }
    }

    if (i % frequency == 0) {
      std::cout << "Performed " << i << " operations; current heap size is " << this->plain_heap.size() << std::endl;
    }
  }

  delete oheap;
  delete random;
  delete storage;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x150, %rsp            # imm = 0x150
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0xf0(%rbp)
movl $0x3, -0xc(%rbp)
movsd 0x38af(%rip), %xmm0     # 0x100e8
movsd 0x3967(%rip), %xmm1     # 0x101a8
callq 0x2290
movq -0xf0(%rbp), %rax
cvttsd2si %xmm0, %ecx
movl %ecx, -0x10(%rbp)
movl -0x10(%rbp), %ecx
movl %ecx, 0x18(%rax)
movl $0x28, %edi
callq 0x2190
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xe8(%rbp)
callq 0xd5a0
jmp 0xc878
movq -0xe8(%rbp), %rax
movq %rax, -0x18(%rbp)
movl $0x20, %edi
callq 0x2190
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xf8(%rbp)
callq 0xd200
jmp 0xc8a1
movq -0xf8(%rbp), %rax
movq %rax, -0x30(%rbp)
movl $0x58, %edi
callq 0x2190
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x100(%rbp)
movq -0x18(%rbp), %rsi
movq -0x30(%rbp), %rdx
movl -0xc(%rbp), %ecx
movl -0x10(%rbp), %r8d
xorl %r9d, %r9d
callq 0x7970
jmp 0xc8dc
movq -0x100(%rbp), %rax
movq %rax, -0x38(%rbp)
movl $0x989680, -0x3c(%rbp)  # imm = 0x989680
movl $0x2710, -0x40(%rbp)    # imm = 0x2710
movl $0x1, -0x44(%rbp)
cmpl $0x989680, -0x44(%rbp)  # imm = 0x989680
jg 0xcbb6
movq -0xf0(%rbp), %rdi
callq 0xc770
movq %rax, -0x4c(%rbp)
movl -0x4c(%rbp), %eax
movl %eax, -0x50(%rbp)
movl -0x48(%rbp), %eax
movl %eax, -0x54(%rbp)
cmpl $0x0, -0x50(%rbp)
jne 0xca45
movq -0xf0(%rbp), %rdi
xorl %eax, %eax
subl -0x54(%rbp), %eax
movl %eax, -0x58(%rbp)
leaq -0x58(%rbp), %rsi
callq 0x9d20
movq -0xf0(%rbp), %rdi
callq 0x52a0
movq -0xf0(%rbp), %rdi
movq %rax, -0x60(%rbp)
callq 0x5130
movq %rax, -0x68(%rbp)
movq -0x60(%rbp), %rdi
movq -0x68(%rbp), %rsi
callq 0xcc60
movq -0x38(%rbp), %rax
movq %rax, -0x110(%rbp)
movl -0x54(%rbp), %eax
movl %eax, -0x104(%rbp)
movl -0x54(%rbp), %esi
leaq -0x88(%rbp), %rdi
callq 0xc6c0
movq -0x110(%rbp), %rdi
movl -0x104(%rbp), %esi
movq (%rdi), %rax
leaq -0x88(%rbp), %rcx
movq (%rcx), %rdx
movq %rdx, (%rsp)
movq 0x8(%rcx), %rdx
movq %rdx, 0x8(%rsp)
movq 0x10(%rcx), %rdx
movq %rdx, 0x10(%rsp)
movq 0x18(%rcx), %rcx
movq %rcx, 0x18(%rsp)
callq *0x8(%rax)
movq %rax, -0x90(%rbp)
jmp 0xcb38
movq -0xe8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
movl $0x28, %esi
callq 0x21a0
jmp 0xcc25
movq -0xf8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
movl $0x20, %esi
callq 0x21a0
jmp 0xcc25
movq -0x100(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x20(%rbp)
movl %eax, -0x24(%rbp)
movl $0x58, %esi
callq 0x21a0
jmp 0xcc25
cmpl $0x1, -0x50(%rbp)
jne 0xcb36
movq -0xf0(%rbp), %rdi
callq 0x52a0
movq -0xf0(%rbp), %rdi
movq %rax, -0x98(%rbp)
callq 0x5130
movq %rax, -0xa0(%rbp)
movq -0x98(%rbp), %rdi
movq -0xa0(%rbp), %rsi
callq 0xccd0
movq -0xf0(%rbp), %rdi
callq 0xaf70
movq -0xf0(%rbp), %rdi
movq %rax, %rcx
xorl %eax, %eax
subl (%rcx), %eax
movl %eax, -0xa4(%rbp)
callq 0xcd30
movq -0x38(%rbp), %rsi
movq (%rsi), %rax
leaq -0xe0(%rbp), %rdi
callq *0x18(%rax)
movl -0xd0(%rbp), %eax
movl %eax, -0xa8(%rbp)
movl -0xa4(%rbp), %eax
cmpl -0xa8(%rbp), %eax
je 0xcb34
movq 0xb4f1(%rip), %rdi      # 0x17fd0
leaq 0x37fd(%rip), %rsi      # 0x102e3
callq 0x2180
movq %rax, %rdi
movl -0xa4(%rbp), %esi
callq 0x2280
movq %rax, %rdi
leaq 0x37e8(%rip), %rsi      # 0x102eb
callq 0x2180
movq %rax, %rdi
movl -0xa8(%rbp), %esi
callq 0x2280
movq %rax, %rdi
leaq 0x37d1(%rip), %rsi      # 0x102f1
callq 0x2180
movq %rax, %rdi
movq 0xb481(%rip), %rsi      # 0x17fb0
callq 0x21b0
jmp 0xcb36
jmp 0xcb38
movl -0x44(%rbp), %eax
movl $0x2710, %ecx           # imm = 0x2710
cltd
idivl %ecx
cmpl $0x0, %edx
jne 0xcba6
movq 0xb481(%rip), %rdi      # 0x17fd0
leaq 0x37a9(%rip), %rsi      # 0x102ff
callq 0x2180
movq %rax, %rdi
movl -0x44(%rbp), %esi
callq 0x2280
movq %rax, %rdi
leaq 0x379a(%rip), %rsi      # 0x1030a
callq 0x2180
movq -0xf0(%rbp), %rdi
movq %rax, -0x118(%rbp)
callq 0x53a0
movq -0x118(%rbp), %rdi
movq %rax, %rsi
callq 0x2060
movq %rax, %rdi
movq 0xb40f(%rip), %rsi      # 0x17fb0
callq 0x21b0
jmp 0xcba8
movl -0x44(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x44(%rbp)
jmp 0xc8fc
movq -0x38(%rbp), %rax
movq %rax, -0x120(%rbp)
cmpq $0x0, %rax
je 0xcbd8
movq -0x120(%rbp), %rdi
movl $0x8, %esi
callq 0x21a0
movq -0x30(%rbp), %rax
movq %rax, -0x128(%rbp)
cmpq $0x0, %rax
je 0xcbfa
movq -0x128(%rbp), %rdi
movl $0x8, %esi
callq 0x21a0
movq -0x18(%rbp), %rax
movq %rax, -0x130(%rbp)
cmpq $0x0, %rax
je 0xcc1c
movq -0x130(%rbp), %rdi
movl $0x8, %esi
callq 0x21a0
addq $0x150, %rsp            # imm = 0x150
popq %rbp
retq
movq -0x20(%rbp), %rdi
callq 0x22a0
nop