btcs

bitcoin script parser/evaluator/compiler/decompiler
git clone git://jb55.com/btcs
Log | Files | Refs | README | LICENSE

test.c (6202B)


      1 
      2 #include "script.h"
      3 #include "op.h"
      4 #include "alloc.h"
      5 #include "valstack.h"
      6 #include "compiler.h"
      7 #include "tap.c/tap.h"
      8 
      9 typedef void (program)(struct stack *script, struct stack *stack,\
     10                        struct result *result, struct stack *expected);
     11 
     12 #define RUNTEST(test) run_test(script, stack, expected, result, test)
     13 #define TEST(test) static inline void test(struct stack *script UNUSED, \
     14                                            struct stack *stack, \
     15                                            struct result *result,   \
     16                                            struct stack *expected UNUSED  \
     17                                           )
     18 
     19 
     20 static void
     21 cmp_data(const u8 *a, const u8 *b, int alen, int blen, const char *msg) {
     22   int i = 0;
     23   if (memcmp(a, b, blen) != 0) {
     24     printf("#\n# Failed data cmp test\n# > ");
     25     for (i = 0; i < alen; ++i)
     26       printf("%02x ", a[i] & 0xff);
     27 
     28     printf("\n# > ");
     29     for (i = 0; i < blen; ++i)
     30       printf("%02x ", b[i] & 0xff);
     31 
     32     printf("\n#\n");
     33     fail("%s", msg);
     34   }
     35   else
     36     pass("%s", msg);
     37 }
     38 /* static void */
     39 /* test_nip(struct stack *stack, struct stack *expected) { */
     40 /*   stack_push_op(OP_1); */
     41 /* } */
     42 
     43 
     44 static inline void
     45 ok_stacks_equal(struct stack *s1, struct stack *s2, const char *context) {
     46   void **b1 = s1->bottom;
     47   void **b2 = s2->bottom;
     48   struct val v1;
     49   struct val v2;
     50 
     51   size_t s1size = stack_size(s1);
     52   size_t s2size = stack_size(s2);
     53 
     54   cmp_ok(s1size, "==", s2size, "%s: expected stack size", context);
     55 
     56   for (size_t i = 0; i < s1size; ++i) {
     57     v1 = stack_top_val(s1, i);
     58     v2 = stack_top_val(s2, i);
     59 
     60     if (!val_eq(v1, v2)) {
     61       is(val_name(v1), val_name(v2), "%s: stack vals match", context);
     62     }
     63   }
     64 }
     65 
     66 TEST(test_simple) {
     67   u8 in_script[] = { OP_1 };
     68 
     69   script_eval(in_script, 1, stack, result);
     70   ok(!result->error, "test_simple: no errors");
     71   ok(result->op_count == 1, "test_simple: op count is 1");
     72   ok(result->last_op == OP_1, "test_simple: last op is OP_1");
     73 
     74   stack_push_val(expected, smallintval(1));
     75   ok_stacks_equal(stack, expected, "test_simple");
     76 }
     77 
     78 TEST(test_nip) {
     79   u8 in_script[] = { OP_1, OP_2, OP_NIP };
     80 
     81   script_eval(in_script, ARRAY_SIZE(in_script), stack, result);
     82   ok(!result->error, "test_nip: no errors returned");
     83   ok(result->op_count == 3, "test_nip: op_count is 3");
     84 
     85   stack_push_val(expected, smallintval(2));
     86   ok_stacks_equal(stack, expected, "test_nip");
     87 }
     88 
     89 TEST(test_2dup_not_enough_input) {
     90   u8 in_script[] = { OP_1, OP_2DUP };
     91 
     92   int res = script_eval(in_script, ARRAY_SIZE(in_script), stack, result);
     93   ok(res == 0, "2dup fail on small stack");
     94 }
     95 
     96 TEST(negative_integer) {
     97   static u8 buf[6];
     98   int buflen;
     99   u8 expected_in[] = { 0x01, 0x82 };
    100   u8 expected_out[] = { 0x82 };
    101   script_eval(expected_in, sizeof(expected_in), stack, result);
    102   stack_serialize(stack, buf, sizeof(buf), &buflen);
    103   cmp_data(buf, expected_out, buflen, sizeof(expected_out), "negative 2 serializes ok");
    104 }
    105 
    106 TEST(add_negative_two) {
    107   static u8 buf[12];
    108   int len;
    109   static u8 in_script[] = { 0x01, 0x82, 0x01, 0x82, OP_ADD };
    110   static u8 expected_out[] = { 0x84 };
    111   script_eval(in_script, ARRAY_SIZE(in_script), stack, result);
    112   stack_serialize(stack, buf, sizeof(buf), &len);
    113   cmp_data(buf, expected_out, len, ARRAY_SIZE(expected_out), "add negative two twice");
    114 }
    115 
    116 TEST(big_int_serializes_ok) {
    117   int len;
    118   static u8 buf[12];
    119   static u8 expected_in[] = { 0x04, 0xff, 0xff, 0xff, 0x7f,
    120                               0x04, 0xff, 0xff, 0xff, 0x7f, OP_ADD };
    121   static u8 expected_out[] = { 0xfe, 0xff, 0xff, 0xff, 0 };
    122 
    123   script_push_int(script, 2147483647LL);
    124   script_push_int(script, 2147483647LL);
    125   stack_push_op(script, OP_ADD);
    126 
    127   script_serialize(script, buf, ARRAY_SIZE(buf), &len);
    128 
    129   cmp_data(buf, expected_in, len, ARRAY_SIZE(expected_in),
    130            "big int input serializes ok");
    131 
    132   script_eval(buf, sizeof(expected_in), stack, result);
    133   stack_serialize(stack, buf, sizeof(buf), &len);
    134 
    135   cmp_data(buf, expected_out, len, ARRAY_SIZE(expected_out),
    136            "big int output serializes ok");
    137 }
    138 
    139 TEST(test_small_int) {
    140   int len;
    141   static u8 buf[6];
    142   static u8 expected_in[] = { 0x01, 0x7f };
    143   static u8 expected_out[] = { 0x7f };
    144 
    145   script_push_int(script, 127);
    146   script_serialize(script, buf, sizeof(buf), &len);
    147   cmp_data(buf, expected_in, len, sizeof(expected_in),
    148            "small integer input serializes ok");
    149 
    150   script_eval(buf, sizeof(expected_in), stack, result);
    151   stack_serialize(stack, buf, sizeof(buf), &len);
    152   cmp_data(buf, expected_out, len, sizeof(expected_out),
    153            "small integer output serializes ok");
    154 }
    155 
    156 void test_sn_serialize_small() {
    157   static u8 buf[2] = {0};
    158   struct num sn;
    159   static u8 expected_serial[] = { 0x01, 0x7f };
    160   u16 len;
    161   sn_from_int(127, &sn);
    162   sn_serialize(&sn, buf, sizeof(buf), &len);
    163 
    164   cmp_data(buf, expected_serial, len, sizeof(expected_serial),
    165            "small scriptnum (127) serializes ok");
    166 }
    167 
    168 // TODO test scriptnum overflows
    169 // TODO test scriptnum negative zero boolean logic
    170 // TODO test scriptnum add into overflow + hash
    171 // TODO test unpooled scriptnum index is == -1 for various constructors
    172 
    173 /* TODO test ops:
    174  *
    175  *    OP_1ADD
    176  *    OP_1SUB
    177  *    OP_NEGATE
    178  *    OP_ABS
    179  *    OP_NOT
    180  *    OP_0NOTEQUAL
    181  *
    182  */
    183 
    184 
    185 static inline void
    186 run_test(struct stack *script, struct stack *stack, struct stack *expected,
    187          struct result *result, program *prog)
    188 {
    189   stack_clear(script);
    190   stack_clear(stack);
    191   stack_clear(expected);
    192   prog(script, stack, result, expected);
    193 }
    194 
    195 
    196 int
    197 main(int argc UNUSED, char *argv[] UNUSED) {
    198   struct stack _stack, _expected, _script;
    199   struct result _result;
    200   struct stack *script   = &_script;
    201   struct stack *stack    = &_stack;
    202   struct stack *expected = &_expected;
    203   struct result *result  = &_result;
    204 
    205   alloc_arenas();
    206 
    207   plan(15);
    208 
    209   stack_init(script);
    210   stack_init(stack);
    211   stack_init(expected);
    212 
    213   RUNTEST(test_simple);
    214   RUNTEST(test_nip);
    215   RUNTEST(test_2dup_not_enough_input);
    216   RUNTEST(negative_integer);
    217   RUNTEST(add_negative_two);
    218   RUNTEST(big_int_serializes_ok);
    219   RUNTEST(test_small_int);
    220 
    221   stack_free(script);
    222   stack_free(expected);
    223   stack_free(stack);
    224 
    225   free_arenas(0);
    226 
    227   done_testing();
    228   return 0;
    229 }