NAME=pd:h help output
FILE=bins/hbc/bespoke_eval.hbc
CMDS=<<EOF
pd:h?~Hermes
EOF
EXPECT=<<EOF
Hermes bytecode decompiler via libhbc
EOF
RUN

NAME=pd:h help subcommands
FILE=bins/hbc/bespoke_eval.hbc
CMDS=<<EOF
pd:h?~pd:hf
EOF
EXPECT=<<EOF
  pd:hf          - List all functions
EOF
RUN

NAME=r2hermes-? help eval command
FILE=bins/hbc/bespoke_eval.hbc
CMDS=<<EOF
r2hermes-?~r2hermes-E
EOF
EXPECT=<<EOF
r2hermes-E[jq]   - List direct eval instruction sites (j=JSON, q=addresses only)
EOF
RUN

NAME=r2hermes-H file info small
FILE=bins/hbc/bespoke_eval.hbc
CMDS=<<EOF
r2hermes-H~Version
EOF
EXPECT=<<EOF
  Version: 96
EOF
RUN

NAME=r2hermes-H file length small
FILE=bins/hbc/bespoke_eval.hbc
CMDS=<<EOF
r2hermes-H~File Length
EOF
EXPECT=<<EOF
  File Length: 292 bytes
EOF
RUN

NAME=r2hermes-H function count small
FILE=bins/hbc/bespoke_eval.hbc
CMDS=<<EOF
r2hermes-H~Functions
EOF
EXPECT=<<EOF
  Functions: 1
  Functions With Debug Info: 1
EOF
RUN

NAME=r2hermes-H string count small
FILE=bins/hbc/bespoke_eval.hbc
CMDS=<<EOF
r2hermes-H~Strings
EOF
EXPECT=<<EOF
  Strings: 2
  Overflow Strings: 0
EOF
RUN

NAME=r2hermes-H file info large
FILE=bins/hbc/index.android.bundle
CMDS=<<EOF
r2hermes-H~Functions
EOF
EXPECT=<<EOF
  Functions: 5388
  Functions With Debug Info: 0
EOF
RUN

NAME=r2hermes-H strings large
FILE=bins/hbc/index.android.bundle
CMDS=<<EOF
r2hermes-H~Strings
EOF
EXPECT=<<EOF
  Strings: 6170
  Overflow Strings: 7
EOF
RUN

NAME=r2hermes-H identifiers large
FILE=bins/hbc/index.android.bundle
CMDS=<<EOF
r2hermes-H~Identifiers
EOF
EXPECT=<<EOF
  Identifiers: 3449
EOF
RUN

NAME=pd:hf function count large
FILE=bins/hbc/index.android.bundle
CMDS=<<EOF
pd:hf~?
EOF
EXPECT=<<EOF
5389
EOF
RUN

NAME=pd:hc decompile function 0 small
FILE=bins/hbc/bespoke_eval.hbc
CMDS=<<EOF
pd:hc 0
EOF
EXPECT=<<EOF
function global() {
  r0 = "print(123);";
  r0 = eval (r0);
  return r0;
}
EOF
RUN

NAME=pd:hc decompile function eval
FILE=bins/hbc/bespoke_eval.hbc
CMDS=<<EOF
pd:hc 0~eval
EOF
EXPECT=<<EOF
  r0 = eval (r0);
EOF
RUN

NAME=r2hermes-E list eval sites
FILE=bins/hbc/bespoke_eval.hbc
CMDS=<<EOF
r2hermes-E
EOF
EXPECT=<<EOF
0x100000b4 f=0 +0x4 func=0x100000b0 strict=false name=global
EOF
RUN

NAME=r2hermes-Eq list eval addresses
FILE=bins/hbc/bespoke_eval.hbc
CMDS=<<EOF
r2hermes-Eq
EOF
EXPECT=<<EOF
0x100000b4
EOF
RUN

NAME=r2hermes-Ej list eval sites json
FILE=bins/hbc/bespoke_eval.hbc
CMDS=<<EOF
r2hermes-Ej
EOF
EXPECT=<<EOF
[{"address":268435636,"function_id":0,"offset":4,"function_address":268435632,"name":"global","strict":false}]
EOF
RUN

NAME=r2hermes-E list eval sites large
FILE=bins/hbc/index.android.bundle
CMDS=<<EOF
r2hermes-E
EOF
EXPECT=<<EOF
0x100d166b f=4953 +0x28 func=0x100d1643 strict=false name=onPress
EOF
RUN

NAME=pd:hc decompile function return
FILE=bins/hbc/bespoke_eval.hbc
CMDS=<<EOF
pd:hc 0~return
EOF
EXPECT=<<EOF
  return r0;
EOF
RUN

NAME=pd:ha decompile all small
FILE=bins/hbc/bespoke_eval.hbc
CMDS=<<EOF
pd:ha~Decompiled
EOF
EXPECT=<<EOF
// Decompiled Hermes bytecode
EOF
RUN

NAME=pd:ha decompile all version
FILE=bins/hbc/bespoke_eval.hbc
CMDS=<<EOF
pd:ha~Version
EOF
EXPECT=<<EOF
// Version: 96
EOF
RUN

NAME=pd:ho decompile with offsets
FILE=bins/hbc/bespoke_eval.hbc
CMDS=<<EOF
pd:ho 0
EOF
EXPECT=<<EOF
0x000000b0: function global() {
0x000000b0:   r0 = "print(123);";
0x000000b4:   r0 = eval (r0);
0x000000b8:   return r0;
0x000000b0: }
EOF
RUN

NAME=pd:ho offset format
FILE=bins/hbc/bespoke_eval.hbc
CMDS=<<EOF
pd:ho 0~0x000000b0
EOF
EXPECT=<<EOF
0x000000b0: function global() {
0x000000b0:   r0 = "print(123);";
0x000000b0: }
EOF
RUN

NAME=pd:hj json code field
FILE=bins/hbc/bespoke_eval.hbc
CMDS=<<EOF
pd:hj 0~{code}
EOF
EXPECT=<<EOF
function global() {\n  r0 = \"print(123);\";\n  r0 = eval (r0);\n  return r0;\n}\n\n\n
EOF
RUN

NAME=pd:hj json annotation offsets
FILE=bins/hbc/bespoke_eval.hbc
CMDS=<<EOF
pd:hj 0~{annotations[0].type}
pd:hj 0~{annotations[0].offset}
EOF
EXPECT=<<EOF
offset
176
EOF
RUN

NAME=pd:h at entry point
FILE=bins/hbc/bespoke_eval.hbc
CMDS=<<EOF
s entry0
pd:h~eval
EOF
EXPECT=<<EOF
  r0 = eval (r0);
EOF
RUN

NAME=pd:hc for-in loop structuring
FILE=bins/hbc/index.android.bundle
CMDS=<<EOF
pd:hc 6~for (,continue
EOF
EXPECT=<<EOF
    for (r6 in r5)
      if (!r11) continue;
EOF
RUN

NAME=pd:hc for-in no back-edge goto or loop-top label
FILE=bins/hbc/index.android.bundle
CMDS=<<EOF
pd:hc 6~for (r6 in,goto loc_0003e68d,loc_0003e68d:
EOF
EXPECT=<<EOF
    for (r6 in r5)
EOF
RUN

NAME=pd:hc switch fallthrough case grouping
FILE=bins/hbc/index.android.bundle
CMDS=<<EOF
pd:hc 562~case 26,case 27
EOF
EXPECT=<<EOF
    case 26:
    case 27: goto loc_0004d144;
EOF
RUN

NAME=pd:hc comparison condition goto-form no double parens
FILE=bins/hbc/index.android.bundle
CMDS=<<EOF
pd:hc 5~if (r3!==r1)
EOF
EXPECT=<<EOF
    if (r3!==r1) goto loc_0003e637;
EOF
RUN

NAME=pd:hc comparison condition structured-if negated operator
FILE=bins/hbc/index.android.bundle
CMDS=<<EOF
pd:hc 46~if (r5!==r0)
EOF
EXPECT=<<EOF
  if (r5!==r0) {
EOF
RUN

NAME=pd:hc if-blocks structured in catch-containing function
FILE=bins/hbc/index.android.bundle
CMDS=<<EOF
pd:hc 12~if (r7) {
EOF
EXPECT=<<EOF
      if (r7) {
EOF
RUN

NAME=pd:hc structured try/catch for return-terminated try
FILE=bins/hbc/index.android.bundle
CMDS=<<EOF
pd:hc 189~try {,} catch (r0) {
EOF
EXPECT=<<EOF
  try {
  } catch (r0) {
EOF
RUN

NAME=pd:hc multiple independent try/catch blocks structured
FILE=bins/hbc/index.android.bundle
CMDS=<<EOF
pd:hc 344~} catch
EOF
EXPECT=<<EOF
  } catch (r0) {
  } catch (r1) {
  } catch (r1) {
EOF
RUN

NAME=pd:hc do-while loop structuring with no back-edge goto or loop-top label
FILE=bins/hbc/index.android.bundle
CMDS=<<EOF
pd:hc 513~do {,while (r1,goto
EOF
EXPECT=<<EOF
  do {
  } while (r1>r2);
EOF
RUN

NAME=pd:hc materialized guard folds into a while loop
FILE=bins/hbc/index.android.bundle
CMDS=<<EOF
pd:hc 199~while (r2,do {,goto
EOF
EXPECT=<<EOF
  while (r2<r1) {
EOF
RUN

NAME=pd:hc new Array call has no stray space after the parenthesis
FILE=bins/hbc/index.android.bundle
CMDS=<<EOF
pd:hc 513~new Array(0
EOF
EXPECT=<<EOF
  r0 = new Array(0);
EOF
RUN

NAME=pd:hc select_object args have single spacing
FILE=bins/hbc/index.android.bundle
CMDS=<<EOF
pd:hc 310~select_object(r
EOF
EXPECT=<<EOF
    r2 = select_object(r3, r2);
    r1 = select_object(r2, r1);
EOF
RUN

NAME=pd:hc forward substitution folds single-use temp into call
FILE=bins/hbc/index.android.bundle
CMDS=<<EOF
pd:hc 199~.call (undefined
EOF
EXPECT=<<EOF
  r0 = r2 .call (undefined, r1);
EOF
RUN

NAME=pd:hc if-else reconstruction with no trailing goto or join label
FILE=bins/hbc/index.android.bundle
CMDS=<<EOF
pd:hc 311~if (!r0) {,} else {,goto,loc_
EOF
EXPECT=<<EOF
  if (!r0) {
  } else {
EOF
RUN

NAME=pd:hc short-circuit OR merges consecutive same-target conditional gotos
FILE=bins/hbc/index.android.bundle
CMDS=pd:hc 730~ \|\| r2===r20 \|\|
EXPECT=<<EOF
    if (r1===r20 || r2===r20 || r3===r20 || r4===r20) goto loc_00055f28;
EOF
RUN

NAME=pd:hc while loop folds entry guard and do-while into a while header
FILE=bins/hbc/index.android.bundle
CMDS=<<EOF
pd:hc 2303~while (r2,do {,goto
EOF
EXPECT=<<EOF
  while (r2!=r1) {
EOF
RUN

NAME=pd:hc infinite loop structures as for(;;) with continue and break
FILE=bins/hbc/index.android.bundle
CMDS=<<EOF
pd:hc 3896~for (,continue,break
EOF
EXPECT=<<EOF
  for (;;) {
      continue;
    break;
EOF
RUN

NAME=pd:hc break reconstruction renders loop-exit goto as break
FILE=bins/hbc/index.android.bundle
CMDS=<<EOF
pd:hc 3406~while (r0,break,goto loc
EOF
EXPECT=<<EOF
  while (r0<r2) {
    if (r6>=r5) break;
EOF
RUN
