! Strict Z test, written to test frotz_zstrict_patch
!      _
! Torbjorn Andersson, 981127

Property prop1;
Property prop2;
Attribute attr1;   ! 0
Attribute attr2;   ! 1

! Note: obj1's property list will have prop2 before prop1.

Object  obj1
with   prop1 1,
       prop2 2,
has    attr1 attr2;  ! These will be set later anyway
Object  -> obj2
with   prop1;
Object  -> obj3;

[ _jin o1 o2 expected;
   @jin o1 o2 ?L1;
   print "@@64jin ", o1, " ", o2, " => FALSE ";
   if (expected)
       "(incorrect)";
   "(correct)";

   .L1;
   print "@@64jin ", o1, " ", o2, " => TRUE ";
   if (expected)
       "(correct)";
   "(incorrect)";
];

[ _get_child o expected result;
   @get_child o -> result ?L2;
   print "@@64get_child ", o, " => ", result;
   if (expected)
       " (incorrect)";
   " (correct)";

   .L2;
   print "@@64get_child ", o, " => ", result;
   if (expected)
       " (correct)";
   " (incorrect)";
];


[ _get_parent o expected result;
   @get_parent o -> result;
   print "@@64get_parent ", o, " => ", result;
   if (result)
       result = true;
   if (expected == result)
       " (correct)";
   " (incorrect)";
];

[ _get_sibling o expected result;
   @get_sibling o -> result ?L3;
   print "@@64get_sibling ", o, " => ", result;
   if (expected)
       " (incorrect)";
   " (correct)";

   .L3;
   print "@@64get_sibling ", o, " => ", result;
   if (expected)
       " (correct)";
   " (incorrect)";
];

[ _get_prop_addr o p expected result;
   @get_prop_addr o p -> result;
   print "@@64get_prop_addr ", o, " ", p, " => ", result;
   if (result)
       result = true;
   if (result == expected)
       " (correct)";
   " (incorrect)";
];

[ _get_prop o p expected result;
   @get_prop o p -> result;
   print "@@64get_prop ", o, " ", p, " => ", result;
   if (result)
       result = true;
   if (result == expected)
       " (correct)";
   " (incorrect)";
];

[ _clear_attr o a;
   @clear_attr o a;
   print_ret "@@64clear_attr ", o, " ", a;
];

[ _set_attr o a;
   @set_attr o a;
   print_ret "@@64set_attr ", o, " ", a;
];

[ _test_attr o a expected;
   @test_attr o a ?L4;
   print "@@64test_attr ", o, " ", a, " => FALSE ";
   if (expected)
       "(incorrect)";
   "(correct)";
   .L4;
   print "@@64test_attr ", o, " ", a, " => TRUE ";
   if (expected)
       "(correct)";
   if (~~o)
       "(incorrect; shouldn't set attributes in object 0)";
   "(incorrect)";
];

[ _insert_object o1 o2;
   @insert_obj o1 o2;
   print_ret "@@64insert_obj ", o1, " ", o2;
];

[ _remove_obj o;
   @remove_obj o;
   print_ret "@@64remove_obj ", o;
];

[ _get_next_prop o p expected result;
   @get_next_prop o p -> result;
   print "@@64get_next_prop ", o, " ", p, " => ", result;
   if (result)
       result = true;
   if (result == expected)
       " (correct)";
   " (incorrect)";
];

Array buffer string 120;
Array parse string 64;

[ Main x;
   print "Strict Z Test^";

   print "^According to the Z-Machine Standards Document, ~objects are
       numbered consecucutively from 1 upward, with object number 0
       being used to mean ~nothing~ (though there is formally no such
       object).~ Hence, it seems reasonable that operations on object
       number 0 should either fail or, if that is not an option, do
       nothing. These tests are written with that assumption.^";

   print "^Please note that whenever a test is flagged as ~correct~,
       that only means that an instruction returned zero or non-zero
       (or branched / didn't branch) when it was supposed to. Not
       that it necessarily returned the correct value. If no result
       is written the result was not tested, and the test was only
       included to test the stability of the interpreter.^";

   print "^Would you like to make a transcript of the test results?
       (Y/N) ";

   for (::)
   {
       read buffer parse;

       if (parse-->1 == 'yes' or 'y//')
       {
           print "^";
           @output_stream 2;
           break;
       }

       if (parse-->1 == 'no' or 'n//')
       {
           print "^";
           break;
       }

       print "Transcript? (Y/N) ";
   }

   print "Testing @@64jin:^^";

   _jin (obj1, obj2, false);
   _jin (obj2, obj1, true);
   _jin (0,    obj1, false);
   _jin (0,    0,    true);

   print "^Testing @@64get_child:^^";

   _get_child (obj1, true);
   _get_child (obj3, false);
   _get_child (0,    false);

   print "^Testing @@64get_parent:^^";

   _get_parent (obj1, false);
   _get_parent (obj2, true);
   _get_parent (0,    false);

   print "^Testing @@64get_sibling:^^";

   _get_sibling (obj1, false);
   _get_sibling (obj2, true);
   _get_sibling (0,    false);

   print "^Testing @@64get_prop_addr:^^";

   _get_prop_addr (obj1, prop1, true);
   _get_prop_addr (obj3, prop1, false);
   _get_prop_addr (0,    prop1, false);

   print "^Testing @@64get_prop:^^";

   _get_prop (obj1, prop1, true);
   _get_prop (obj2, prop1, false);
   _get_prop (0,    prop1, false);

   print "^Testing @@64clear_attr:^^";

   _clear_attr (obj1, attr1);
   _clear_attr (obj1, attr2);
   _clear_attr (0,    attr1);
   _clear_attr (0,    attr2);

   print "^Testing @@64set_attr:^^";

   _set_attr (obj1, attr1);
   _set_attr (obj1, attr2);
   _set_attr (0, attr1);

   print "^(Note: An attempt has been made to set attribute number ",
       attr1, " in object number 0. If the @@64test_attr test below
       indicates that this attribute has been set, the interpreter
       did not ignore the instruction as it should have done.)^";

   print "^Testing @@64test_attr:^^";

   _test_attr (obj1, attr1, true);
   _test_attr (obj1, attr2, true);
   _test_attr (obj2, attr1, false);
   _test_attr (obj2, attr2, false);
   _test_attr (0,    attr1, false);
   _test_attr (0,    attr2, false);

   print "^Testing @@64insert_obj:^^";

   _insert_object (obj3, obj1);
   _insert_object (0,    obj1);
   _insert_object (obj1, 0);
   _insert_object (0,    0);

   print "^Testing @@remove_obj:^^";

   _remove_obj (obj3);
   _remove_obj (0);

   print "^Testing @@get_next_prop:^^";

   _get_next_prop (obj1, prop2, true);
   _get_next_prop (obj2, prop1, false);
   _get_next_prop (0,    prop1, false);

   print "^Test completed!^";

   if ((0-->8) & 1)
   {
       print "^End of transcript^";
       @output_stream -2;
   }

   print "^Press any key.^";
   @read_char -> x;
];