Merge pull request #2331 from take-cheeze/struct_test
authorYukihiro "Matz" Matsumoto <[email protected]>
Sat, 26 Dec 2015 06:46:49 +0000 (26 15:46 +0900)
committerYukihiro "Matz" Matsumoto <[email protected]>
Sat, 26 Dec 2015 06:46:49 +0000 (26 15:46 +0900)
Improve `Struct` test.

1  2 
mrbgems/mruby-struct/src/struct.c
mrbgems/mruby-struct/test/struct.rb

@@@ -4,17 -4,18 +4,17 @@@
  ** See Copyright Notice in mruby.h
  */
  
 -#include <ctype.h>
  #include <string.h>
 -#include "mruby.h"
 -#include "mruby/array.h"
 -#include "mruby/string.h"
 -#include "mruby/class.h"
 -#include "mruby/variable.h"
 -#include "mruby/hash.h"
 -#include "mruby/range.h"
 +#include <mruby.h>
 +#include <mruby/array.h>
 +#include <mruby/string.h>
 +#include <mruby/class.h>
 +#include <mruby/variable.h>
 +#include <mruby/hash.h>
 +#include <mruby/range.h>
  
 -#define RSTRUCT_LEN(st) RARRAY_LEN(st)
 -#define RSTRUCT_PTR(st) RARRAY_PTR(st)
 +#define RSTRUCT_LEN(st) mrb_ary_ptr(st)->len
 +#define RSTRUCT_PTR(st) mrb_ary_ptr(st)->ptr
  
  static struct RClass *
  struct_class(mrb_state *mrb)
@@@ -40,9 -41,9 +40,9 @@@ struct_ivar_get(mrb_state *mrb, mrb_val
  }
  
  static mrb_value
 -mrb_struct_s_members(mrb_state *mrb, mrb_value klass)
 +struct_s_members(mrb_state *mrb, struct RClass *klass)
  {
 -  mrb_value members = struct_ivar_get(mrb, klass, mrb_intern_lit(mrb, "__members__"));
 +  mrb_value members = struct_ivar_get(mrb, mrb_obj_value(klass), mrb_intern_lit(mrb, "__members__"));
  
    if (mrb_nil_p(members)) {
      mrb_raise(mrb, E_TYPE_ERROR, "uninitialized struct");
  }
  
  static mrb_value
 -mrb_struct_members(mrb_state *mrb, mrb_value s)
 -{
 -  mrb_value members = mrb_struct_s_members(mrb, mrb_obj_value(mrb_obj_class(mrb, s)));
 -  if (!strcmp(mrb_class_name(mrb, mrb_obj_class(mrb, s)), "Struct")) {
 -    if (RSTRUCT_LEN(s) != RARRAY_LEN(members)) {
 -      mrb_raisef(mrb, E_TYPE_ERROR,
 -                 "struct size differs (%S required %S given)",
 -                 mrb_fixnum_value(RARRAY_LEN(members)), mrb_fixnum_value(RSTRUCT_LEN(s)));
 -    }
 +struct_members(mrb_state *mrb, mrb_value s)
 +{
 +  mrb_value members = struct_s_members(mrb, mrb_obj_class(mrb, s));
 +  if (!mrb_array_p(s)) {
 +    mrb_raise(mrb, E_TYPE_ERROR, "corrupted struct");
 +  }
 +  if (RSTRUCT_LEN(s) != RARRAY_LEN(members)) {
 +    mrb_raisef(mrb, E_TYPE_ERROR,
 +               "struct size differs (%S required %S given)",
 +               mrb_fixnum_value(RARRAY_LEN(members)), mrb_fixnum_value(RSTRUCT_LEN(s)));
    }
    return members;
  }
@@@ -72,10 -72,15 +72,10 @@@ static mrb_valu
  mrb_struct_s_members_m(mrb_state *mrb, mrb_value klass)
  {
    mrb_value members, ary;
 -  mrb_value *p, *pend;
  
 -  members = mrb_struct_s_members(mrb, klass);
 +  members = struct_s_members(mrb, mrb_class_ptr(klass));
    ary = mrb_ary_new_capa(mrb, RARRAY_LEN(members));
 -  p = RARRAY_PTR(members); pend = p + RARRAY_LEN(members);
 -  while (p < pend) {
 -    mrb_ary_push(mrb, ary, *p);
 -    p++;
 -  }
 +  mrb_ary_replace(mrb, ary, members);
    return ary;
  }
  
@@@ -93,7 -98,7 +93,7 @@@
   */
  
  static mrb_value
 -mrb_struct_members_m(mrb_state *mrb, mrb_value obj)
 +mrb_struct_members(mrb_state *mrb, mrb_value obj)
  {
    return mrb_struct_s_members_m(mrb, mrb_obj_value(mrb_obj_class(mrb, obj)));
  }
  static mrb_value
  mrb_struct_getmember(mrb_state *mrb, mrb_value obj, mrb_sym id)
  {
 -  mrb_value members, slot, *ptr, *ptr_members;
 +  mrb_value members, slot, *ptr;
 +  const mrb_value *ptr_members;
    mrb_int i, len;
  
    ptr = RSTRUCT_PTR(obj);
 -  members = mrb_struct_members(mrb, obj);
 +  members = struct_members(mrb, obj);
    ptr_members = RARRAY_PTR(members);
    slot = mrb_symbol_value(id);
    len = RARRAY_LEN(members);
        return ptr[i];
      }
    }
 -  mrb_raisef(mrb, E_INDEX_ERROR, "`%S' is not a struct member", mrb_sym2str(mrb, id));
 +  mrb_raisef(mrb, E_INDEX_ERROR, "'%S' is not a struct member", mrb_sym2str(mrb, id));
    return mrb_nil_value();       /* not reached */
  }
  
@@@ -177,14 -181,13 +177,14 @@@ mrb_struct_set(mrb_state *mrb, mrb_valu
    const char *name;
    mrb_int i, len, slen;
    mrb_sym mid;
 -  mrb_value members, slot, *ptr, *ptr_members;
 +  mrb_value members, slot, *ptr;
 +  const mrb_value *ptr_members;
  
    /* get base id */
    name = mrb_sym2name_len(mrb, mrb->c->ci->mid, &slen);
    mid = mrb_intern(mrb, name, slen-1); /* omit last "=" */
  
 -  members = mrb_struct_members(mrb, obj);
 +  members = struct_members(mrb, obj);
    ptr_members = RARRAY_PTR(members);
    len = RARRAY_LEN(members);
    ptr = RSTRUCT_PTR(obj);
        return ptr[i] = val;
      }
    }
 -  mrb_raisef(mrb, E_INDEX_ERROR, "`%S' is not a struct member", mrb_sym2str(mrb, mid));
 +  mrb_raisef(mrb, E_INDEX_ERROR, "'%S' is not a struct member", mrb_sym2str(mrb, mid));
    return mrb_nil_value();       /* not reached */
  }
  
@@@ -221,37 -224,14 +221,37 @@@ is_const_id(mrb_state *mrb, const char 
    return ISUPPER(name[0]);
  }
  
 +static void
 +make_struct_define_accessors(mrb_state *mrb, mrb_value members, struct RClass *c)
 +{
 +  const mrb_value *ptr_members = RARRAY_PTR(members);
 +  mrb_int i;
 +  mrb_int len = RARRAY_LEN(members);
 +  int ai = mrb_gc_arena_save(mrb);
 +
 +  for (i=0; i<len; i++) {
 +    mrb_sym id = mrb_symbol(ptr_members[i]);
 +    const char *name = mrb_sym2name_len(mrb, id, NULL);
 +
 +    if (is_local_id(mrb, name) || is_const_id(mrb, name)) {
 +      if (i < N_REF_FUNC) {
 +        mrb_define_method_id(mrb, c, id, ref_func[i], MRB_ARGS_NONE());
 +      }
 +      else {
 +        mrb_define_method_id(mrb, c, id, mrb_struct_ref, MRB_ARGS_NONE());
 +      }
 +      mrb_define_method_id(mrb, c, mrb_id_attrset(mrb, id), mrb_struct_set_m, MRB_ARGS_REQ(1));
 +      mrb_gc_arena_restore(mrb, ai);
 +    }
 +  }
 +}
 +
  static mrb_value
  make_struct(mrb_state *mrb, mrb_value name, mrb_value members, struct RClass * klass)
  {
 -  mrb_value nstr, *ptr_members;
 +  mrb_value nstr;
    mrb_sym id;
 -  mrb_int i, len;
    struct RClass *c;
 -  int ai;
  
    if (mrb_nil_p(name)) {
      c = mrb_class_new(mrb, klass);
      if (!is_const_id(mrb, mrb_sym2name_len(mrb, id, NULL))) {
        mrb_name_error(mrb, id, "identifier %S needs to be constant", name);
      }
 -    if (mrb_const_defined_at(mrb, klass, id)) {
 +    if (mrb_const_defined_at(mrb, mrb_obj_value(klass), id)) {
        mrb_warn(mrb, "redefining constant Struct::%S", name);
        /* ?rb_mod_remove_const(klass, mrb_sym2name(mrb, id)); */
      }
    mrb_define_class_method(mrb, c, "[]", mrb_instance_new, MRB_ARGS_ANY());
    mrb_define_class_method(mrb, c, "members", mrb_struct_s_members_m, MRB_ARGS_NONE());
    /* RSTRUCT(nstr)->basic.c->super = c->c; */
 -  ptr_members = RARRAY_PTR(members);
 -  len = RARRAY_LEN(members);
 -  ai = mrb_gc_arena_save(mrb);
 -  for (i=0; i< len; i++) {
 -    mrb_sym id = mrb_symbol(ptr_members[i]);
 -    const char *name = mrb_sym2name_len(mrb, id, NULL);
 -
 -    if (is_local_id(mrb, name) || is_const_id(mrb, name)) {
 -      if (i < N_REF_FUNC) {
 -        mrb_define_method_id(mrb, c, id, ref_func[i], MRB_ARGS_NONE());
 -      }
 -      else {
 -        mrb_define_method_id(mrb, c, id, mrb_struct_ref, MRB_ARGS_NONE());
 -      }
 -      mrb_define_method_id(mrb, c, mrb_id_attrset(mrb, id), mrb_struct_set_m, MRB_ARGS_REQ(1));
 -      mrb_gc_arena_restore(mrb, ai);
 -    }
 -  }
 +  make_struct_define_accessors(mrb, members, c);
    return nstr;
  }
  
@@@ -356,7 -353,7 +356,7 @@@ mrb_struct_s_def(mrb_state *mrb, mrb_va
      }
      for (i=0; i<RARRAY_LEN(rest); i++) {
        id = mrb_obj_to_sym(mrb, RARRAY_PTR(rest)[i]);
 -      RARRAY_PTR(rest)[i] = mrb_symbol_value(id);
 +      mrb_ary_set(mrb, rest, i, mrb_symbol_value(id));
      }
    }
    st = make_struct(mrb, name, rest, struct_class(mrb));
@@@ -403,7 -400,7 +403,7 @@@ mrb_struct_initialize_withArg(mrb_stat
  }
  
  static mrb_value
 -mrb_struct_initialize_m(mrb_state *mrb, /*int argc, mrb_value *argv,*/ mrb_value self)
 +mrb_struct_initialize(mrb_state *mrb, mrb_value self)
  {
    mrb_value *argv;
    mrb_int argc;
    return mrb_struct_initialize_withArg(mrb, argc, argv, self);
  }
  
 -static mrb_value
 -inspect_struct(mrb_state *mrb, mrb_value s, mrb_bool recur)
 -{
 -  const char *cn = mrb_class_name(mrb, mrb_obj_class(mrb, s));
 -  mrb_value members, str = mrb_str_new_lit(mrb, "#<struct ");
 -  mrb_value *ptr, *ptr_members;
 -  mrb_int i, len;
 -
 -  if (cn) {
 -    mrb_str_append(mrb, str, mrb_str_new_cstr(mrb, cn));
 -  }
 -  if (recur) {
 -    return mrb_str_cat_lit(mrb, str, ":...>");
 -  }
 -
 -  members = mrb_struct_members(mrb, s);
 -  ptr_members = RARRAY_PTR(members);
 -  ptr = RSTRUCT_PTR(s);
 -  len = RSTRUCT_LEN(s);
 -  for (i=0; i<len; i++) {
 -    mrb_value slot;
 -    mrb_sym id;
 -    const char *name;
 -    mrb_int len;
 -
 -    if (i > 0) {
 -      mrb_str_cat_lit(mrb, str, ", ");
 -    }
 -    else if (cn) {
 -      mrb_str_cat_lit(mrb, str, " ");
 -    }
 -    slot = ptr_members[i];
 -    id = mrb_symbol(slot);
 -    name = mrb_sym2name_len(mrb, id, &len);
 -    if (is_local_id(mrb, name) || is_const_id(mrb, name)) {
 -      mrb_str_append(mrb, str, mrb_str_new(mrb, name, len));
 -    }
 -    else {
 -      mrb_str_append(mrb, str, mrb_inspect(mrb, slot));
 -    }
 -    mrb_str_cat_lit(mrb, str, "=");
 -    mrb_str_append(mrb, str, mrb_inspect(mrb, ptr[i]));
 -  }
 -  mrb_str_cat_lit(mrb, str, ">");
 -
 -  return str;
 -}
 -
 -/*
 - * call-seq:
 - *   struct.to_s      -> string
 - *   struct.inspect   -> string
 - *
 - * Describe the contents of this struct in a string.
 - */
 -static mrb_value
 -mrb_struct_inspect(mrb_state *mrb, mrb_value s)
 -{
 -  return inspect_struct(mrb, s, FALSE);
 -}
 -
  /* 15.2.18.4.9  */
  /* :nodoc: */
  static mrb_value
@@@ -442,12 -500,11 +442,12 @@@ mrb_struct_init_copy(mrb_state *mrb, mr
  static mrb_value
  struct_aref_sym(mrb_state *mrb, mrb_value s, mrb_sym id)
  {
 -  mrb_value *ptr, members, *ptr_members;
 +  mrb_value *ptr, members;
 +  const mrb_value *ptr_members;
    mrb_int i, len;
  
    ptr = RSTRUCT_PTR(s);
 -  members = mrb_struct_members(mrb, s);
 +  members = struct_members(mrb, s);
    ptr_members = RARRAY_PTR(members);
    len = RARRAY_LEN(members);
    for (i=0; i<len; i++) {
        return ptr[i];
      }
    }
-   mrb_raisef(mrb, E_INDEX_ERROR, "no member '%S' in struct", mrb_sym2str(mrb, id));
+   mrb_name_error(mrb, id, "no member '%S' in struct", mrb_sym2str(mrb, id));
    return mrb_nil_value();       /* not reached */
  }
  
@@@ -503,7 -560,7 +503,7 @@@ mrb_struct_aref(mrb_state *mrb, mrb_val
      mrb_value sym = mrb_check_intern_str(mrb, idx);
  
      if (mrb_nil_p(sym)) {
-       mrb_raisef(mrb, E_INDEX_ERROR, "no member '%S' in struct", idx);
+       mrb_name_error(mrb, mrb_intern_str(mrb, idx), "no member '%S' in struct", idx);
      }
      idx = sym;
    }
  static mrb_value
  mrb_struct_aset_sym(mrb_state *mrb, mrb_value s, mrb_sym id, mrb_value val)
  {
 -  mrb_value members, *ptr, *ptr_members;
 +  mrb_value members, *ptr;
 +  const mrb_value *ptr_members;
    mrb_int i, len;
  
 -  members = mrb_struct_members(mrb, s);
 +  members = struct_members(mrb, s);
    len = RARRAY_LEN(members);
    if (RSTRUCT_LEN(s) != len) {
      mrb_raisef(mrb, E_TYPE_ERROR,
        return val;
      }
    }
-   mrb_raisef(mrb, E_INDEX_ERROR, "no member '%S' in struct", mrb_sym2str(mrb, id));
+   mrb_name_error(mrb, id, "no member '%S' in struct", mrb_sym2str(mrb, id));
    return val;                   /* not reach */
  }
  
@@@ -574,7 -630,7 +574,7 @@@ mrb_struct_aset(mrb_state *mrb, mrb_val
      mrb_value sym = mrb_check_intern_str(mrb, idx);
  
      if (mrb_nil_p(sym)) {
-       mrb_raisef(mrb, E_INDEX_ERROR, "no member '%S' in struct", idx);
+       mrb_name_error(mrb, mrb_intern_str(mrb, idx), "no member '%S' in struct", idx);
      }
      idx = sym;
    }
@@@ -621,27 -677,34 +621,27 @@@ mrb_struct_equal(mrb_state *mrb, mrb_va
    mrb_value s2;
    mrb_value *ptr, *ptr2;
    mrb_int i, len;
 -  mrb_bool equal_p;
  
    mrb_get_args(mrb, "o", &s2);
    if (mrb_obj_equal(mrb, s, s2)) {
 -    equal_p = 1;
 +    return mrb_true_value();
    }
 -  else if (!strcmp(mrb_class_name(mrb, mrb_obj_class(mrb, s)), "Struct") ||
 -           mrb_obj_class(mrb, s) != mrb_obj_class(mrb, s2)) {
 -    equal_p = 0;
 +  if (mrb_obj_class(mrb, s) != mrb_obj_class(mrb, s2)) {
 +    return mrb_false_value();
    }
 -  else if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
 +  if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
      mrb_bug(mrb, "inconsistent struct"); /* should never happen */
 -    equal_p = 0; /* This substuture is just to suppress warnings. never called. */
    }
 -  else {
 -    ptr = RSTRUCT_PTR(s);
 -    ptr2 = RSTRUCT_PTR(s2);
 -    len = RSTRUCT_LEN(s);
 -    equal_p = 1;
 -    for (i=0; i<len; i++) {
 -      if (!mrb_equal(mrb, ptr[i], ptr2[i])) {
 -        equal_p = 0;
 -        break;
 -      }
 +  ptr = RSTRUCT_PTR(s);
 +  ptr2 = RSTRUCT_PTR(s2);
 +  len = RSTRUCT_LEN(s);
 +  for (i=0; i<len; i++) {
 +    if (!mrb_equal(mrb, ptr[i], ptr2[i])) {
 +      return mrb_false_value();
      }
    }
  
 -  return mrb_bool_value(equal_p);
 +  return mrb_true_value();
  }
  
  /* 15.2.18.4.12(x)  */
@@@ -658,27 -721,34 +658,27 @@@ mrb_struct_eql(mrb_state *mrb, mrb_valu
    mrb_value s2;
    mrb_value *ptr, *ptr2;
    mrb_int i, len;
 -  mrb_bool eql_p;
  
    mrb_get_args(mrb, "o", &s2);
    if (mrb_obj_equal(mrb, s, s2)) {
 -    eql_p = 1;
 +    return mrb_true_value();
    }
 -  else if (strcmp(mrb_class_name(mrb, mrb_obj_class(mrb, s2)), "Struct") ||
 -           mrb_obj_class(mrb, s) != mrb_obj_class(mrb, s2)) {
 -    eql_p = 0;
 +  if (mrb_obj_class(mrb, s) != mrb_obj_class(mrb, s2)) {
 +    return mrb_false_value();
    }
 -  else if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
 +  if (RSTRUCT_LEN(s) != RSTRUCT_LEN(s2)) {
      mrb_bug(mrb, "inconsistent struct"); /* should never happen */
 -    eql_p = 0; /* This substuture is just to suppress warnings. never called. */
    }
 -  else {
 -    ptr = RSTRUCT_PTR(s);
 -    ptr2 = RSTRUCT_PTR(s2);
 -    len = RSTRUCT_LEN(s);
 -    eql_p = 1;
 -    for (i=0; i<len; i++) {
 -      if (!mrb_eql(mrb, ptr[i], ptr2[i])) {
 -        eql_p = 0;
 -        break;
 -      }
 +  ptr = RSTRUCT_PTR(s);
 +  ptr2 = RSTRUCT_PTR(s2);
 +  len = RSTRUCT_LEN(s);
 +  for (i=0; i<len; i++) {
 +    if (!mrb_eql(mrb, ptr[i], ptr2[i])) {
 +      return mrb_false_value();
      }
    }
  
 -  return mrb_bool_value(eql_p);
 +  return mrb_true_value();
  }
  
  /*
@@@ -719,7 -789,7 +719,7 @@@ mrb_struct_to_h(mrb_state *mrb, mrb_val
    mrb_value members, ret;
    mrb_int i;
  
 -  members = mrb_struct_s_members(mrb, mrb_obj_value(mrb_class(mrb, self)));
 +  members = struct_s_members(mrb, mrb_class(mrb, self));
    ret = mrb_hash_new_capa(mrb, RARRAY_LEN(members));
  
    for (i = 0; i < RARRAY_LEN(members); ++i) {
@@@ -748,8 -818,8 +748,8 @@@ mrb_struct_values_at(mrb_state *mrb, mr
   *  The <code>Struct</code> class is a generator of specific classes,
   *  each one of which is defined to hold a set of variables and their
   *  accessors. In these examples, we'll call the generated class
 - *  ``<i>Customer</i>Class,'' and we'll show an example instance of that
 - *  class as ``<i>Customer</i>Inst.''
 + *  "<i>Customer</i>Class," and we'll show an example instance of that
 + *  class as "<i>Customer</i>Inst."
   *
   *  In the descriptions that follow, the parameter <i>symbol</i> refers
   *  to a symbol, which is either a quoted string or a
@@@ -766,9 -836,11 +766,9 @@@ mrb_mruby_struct_gem_init(mrb_state* mr
    mrb_define_method(mrb, st,       "==",              mrb_struct_equal,       MRB_ARGS_REQ(1)); /* 15.2.18.4.1  */
    mrb_define_method(mrb, st,       "[]",              mrb_struct_aref,        MRB_ARGS_REQ(1)); /* 15.2.18.4.2  */
    mrb_define_method(mrb, st,       "[]=",             mrb_struct_aset,        MRB_ARGS_REQ(2)); /* 15.2.18.4.3  */
 -  mrb_define_method(mrb, st,       "members",         mrb_struct_members_m,   MRB_ARGS_NONE()); /* 15.2.18.4.6  */
 -  mrb_define_method(mrb, st,       "initialize",      mrb_struct_initialize_m,MRB_ARGS_ANY());  /* 15.2.18.4.8  */
 +  mrb_define_method(mrb, st,       "members",         mrb_struct_members,     MRB_ARGS_NONE()); /* 15.2.18.4.6  */
 +  mrb_define_method(mrb, st,       "initialize",      mrb_struct_initialize,  MRB_ARGS_ANY());  /* 15.2.18.4.8  */
    mrb_define_method(mrb, st,       "initialize_copy", mrb_struct_init_copy,   MRB_ARGS_REQ(1)); /* 15.2.18.4.9  */
 -  mrb_define_method(mrb, st,       "inspect",         mrb_struct_inspect,     MRB_ARGS_NONE()); /* 15.2.18.4.10(x)  */
 -  mrb_define_alias(mrb, st,        "to_s", "inspect");                                      /* 15.2.18.4.11(x)  */
    mrb_define_method(mrb, st,       "eql?",            mrb_struct_eql,         MRB_ARGS_REQ(1)); /* 15.2.18.4.12(x)  */
  
    mrb_define_method(mrb, st,        "size",           mrb_struct_len,         MRB_ARGS_NONE());
@@@ -2,42 -2,55 +2,55 @@@
  # Struct ISO Test
  
  assert('Struct', '15.2.18') do
-   Struct.class == Class
+   assert_equal Class, Struct.class
  end
  
  assert('Struct.new', '15.2.18.3.1') do
    c = Struct.new(:m1, :m2)
-   c.superclass == Struct and
-     c.members == [:m1,:m2]
+   assert_equal Struct, c.superclass
+   assert_equal [:m1, :m2], c.members
  end
  
  # Check crash bug with Struc.new and no params.
  assert('Struct.new', '15.2.18.3.1') do
    c = Struct.new()
-   c.superclass == Struct and c.members == []
+   assert_equal Struct, c.superclass
+   assert_equal [], c.members
  end
  
  assert('Struct#==', '15.2.18.4.1') do
    c = Struct.new(:m1, :m2)
    cc1 = c.new(1,2)
    cc2 = c.new(1,2)
-   cc1 == cc2
+   assert_true cc1 == cc2
  end
  
  assert('Struct#[]', '15.2.18.4.2') do
    c = Struct.new(:m1, :m2)
    cc = c.new(1,2)
-   cc[:m1] == 1 and cc["m2"] == 2
+   assert_equal 1, cc[:m1]
+   assert_equal 2, cc["m2"]
+   assert_equal 1, cc[0]
+   assert_equal 2, cc[-1]
+   assert_raise(TypeError) { cc[[]] }
+   assert_raise(IndexError) { cc[2] }
+   assert_raise(NameError) { cc['tama'] }
  end
  
  assert('Struct#[]=', '15.2.18.4.3') do
    c = Struct.new(:m1, :m2)
    cc = c.new(1,2)
    cc[:m1] = 3
-   cc[:m1] == 3
+   assert_equal 3, cc[:m1]
    cc["m2"] = 3
    assert_equal 3, cc["m2"]
+   cc[0] = 4
+   assert_equal 4, cc[0]
+   cc[-1] = 5
+   assert_equal 5, cc[-1]
    assert_raise(TypeError) { cc[[]] = 3 }
+   assert_raise(IndexError) { cc[2] = 7 }
+   assert_raise(NameError) { cc['pochi'] = 8 }
  end
  
  assert('Struct#each', '15.2.18.4.4') do
@@@ -47,7 -60,7 +60,7 @@@
    cc.each{|x|
      a << x
    }
-   a[0] == 1 and a[1] == 2
+   assert_equal [1, 2], a
  end
  
  assert('Struct#each_pair', '15.2.18.4.5') do
    cc.each_pair{|k,v|
      a << [k,v]
    }
-   a[0] == [:m1, 1] and a[1] == [:m2, 2]
+   assert_equal [[:m1, 1], [:m2, 2]], a
  end
  
  assert('Struct#members', '15.2.18.4.6') do
    c = Struct.new(:m1, :m2)
-   cc = c.new(1,2)
-   cc.members == [:m1,:m2]
+   assert_equal [:m1, :m2], c.new(1,2).members
  end
  
  assert('Struct#select', '15.2.18.4.7') do
    c = Struct.new(:m1, :m2)
-   cc = c.new(1,2)
-   cc.select{|v| v % 2 == 0} == [2]
+   assert_equal([2]) { c.new(1,2).select{|v| v % 2 == 0} }
  end
  
  assert('large struct') do
@@@ -103,7 -114,7 +114,7 @@@ en
  assert('struct inspect') do
    c = Struct.new(:m1, :m2, :m3, :m4, :m5)
    cc = c.new(1,2,3,4,5)
 -  assert_equal "#<struct #{c.inspect} m1=1, m2=2, m3=3, m4=4, m5=5>", cc.inspect
 +  assert_equal "#<struct m1=1, m2=2, m3=3, m4=4, m5=5>", cc.inspect
  end
  
  assert('Struct#length, Struct#size') do