#50 - advanced tests (delayed test 5)
authorFedor Yudanov <fedwiz@academ.org>
Mon, 8 Apr 2013 06:33:06 +0000 (13:33 +0700)
committerFedor Yudanov <fedwiz@academ.org>
Mon, 8 Apr 2013 06:33:06 +0000 (13:33 +0700)
rbejdb/src/rbbson.c
rbejdb/test/t2.rb

index e0af287..6fba9c3 100644 (file)
@@ -13,6 +13,8 @@ typedef struct {
     VALUE obj;
     int arrayIndex;
     int flags;
+
+    VALUE traverse_hash;
 } RBBSON;
 
 
@@ -22,6 +24,8 @@ VALUE bson_array_to_ruby(bson_iterator* it);
 
 bson_date_t ruby_time_to_bson_internal(VALUE time);
 
+void ruby_to_bson_internal(VALUE rbobj, bson** bsonresp, VALUE traverse, int flags);
+
 VALUE bson_date_to_ruby(bson_date_t date);
 
 
@@ -33,7 +37,7 @@ void init_ruby_to_bson() {
 }
 
 
-VALUE createBsonWrap(bson* bsonval, VALUE rbobj, int flags) {
+VALUE createBsonWrap(bson* bsonval, VALUE rbobj, VALUE traverse, int flags) {
     if (NIL_P(bsonWrapClass)) {
         rb_raise(rb_eRuntimeError, "Ruby to BSON library must be initialized");
     }
@@ -44,10 +48,21 @@ VALUE createBsonWrap(bson* bsonval, VALUE rbobj, int flags) {
     rbbson->bsonval = bsonval;
     rbbson->obj = rbobj;
     rbbson->arrayIndex = 0;
+    rbbson->traverse_hash = !NIL_P(traverse) ? traverse : rb_hash_new();
 
     return bsonWrap;
 }
 
+void add_ruby_to_traverse(VALUE rbobj, VALUE traverse) {
+    Check_Type(traverse, T_HASH);
+
+    if (!NIL_P(rb_hash_aref(traverse, rbobj))) {
+        rb_raise(rb_eRuntimeError, "Converting circular structure to BSON");
+    }
+    rb_hash_aset(traverse, rbobj, Qtrue);
+}
+
+
 int iterate_key_values_callback(VALUE key, VALUE val, VALUE bsonWrap) {
     key = rb_funcall(key, rb_intern("to_s"), 0);
     char* attrName = StringValuePtr(key);
@@ -82,12 +97,13 @@ int iterate_key_values_callback(VALUE key, VALUE val, VALUE bsonWrap) {
             }
             //else same as hash :)
         case T_HASH:
-            ruby_to_bson(val, &subbson, rbbson->flags);
+            ruby_to_bson_internal(val, &subbson, rbbson->traverse_hash, rbbson->flags);
             bson_append_bson(b, attrName, subbson);
             break;
         case T_ARRAY:
+            add_ruby_to_traverse(val, rbbson->traverse_hash);
             bson_append_start_array(b, attrName);
-            rb_iterate(rb_each, val, iterate_array_callback, createBsonWrap(b, rbbson->obj, rbbson->flags));
+            rb_iterate(rb_each, val, iterate_array_callback, createBsonWrap(b, rbbson->obj, rbbson->traverse_hash, rbbson->flags));
             bson_append_finish_array(b);
             break;
         case T_STRING:
@@ -168,11 +184,13 @@ void ruby_hash_to_bson_internal(VALUE rbhash, VALUE bsonWrap) {
 }
 
 
-void ruby_to_bson(VALUE rbobj, bson** bsonresp, int flags) {
-    VALUE bsonWrap = createBsonWrap(bson_create(), rbobj, flags);
+void ruby_to_bson_internal(VALUE rbobj, bson** bsonresp, VALUE traverse, int flags) {
+    VALUE bsonWrap = createBsonWrap(bson_create(), rbobj, traverse, flags);
     RBBSON* rbbson;
     Data_Get_Struct(bsonWrap, RBBSON, rbbson);
 
+    add_ruby_to_traverse(rbobj, rbbson->traverse_hash);
+
     if (flags & RUBY_TO_BSON_AS_QUERY) {
         bson_init_as_query(rbbson->bsonval);
     } else {
@@ -196,6 +214,11 @@ void ruby_to_bson(VALUE rbobj, bson** bsonresp, int flags) {
     *bsonresp = rbbson->bsonval;
 }
 
+void ruby_to_bson(VALUE rbobj, bson** bsonresp, int flags) {
+    ruby_to_bson_internal(rbobj, bsonresp, Qnil, flags);
+}
+
+
 
 VALUE bson_iterator_to_ruby(bson_iterator* it, bson_type t) {
     VALUE val;
index 50be66c..6c66838 100644 (file)
@@ -150,9 +150,6 @@ class EJDBTestUnit < Test::Unit::TestCase
   end
 
 
-=begin
-  test is written but this functionality is rather special an has low priority...
-
   def test_ejdb5_circular
     assert_not_nil $jb
     assert $jb.is_open?
@@ -169,21 +166,34 @@ class EJDBTestUnit < Test::Unit::TestCase
     end
 
     assert_not_nil err
-    assert_equal(err.message, "Converting circular structure to JSON")
+    assert_equal(err.message, "Converting circular structure to BSON")
 
     err = nil
     begin
-      $jb.find("parrots", [cir_query])
+      $jb.find("parrots", {:q => [cir_query]})
     rescue Exception => e
       err = e
     end
 
     assert_not_nil err
-    assert_equal(err.message, "Converting circular structure to JSON")
+    assert_equal(err.message, "Converting circular structure to BSON")
+
+
+    cir_array = []
+    cir_array[0] = cir_array
+
+    err = nil
+    begin
+      $jb.find("parrots", {:q => cir_array})
+    rescue Exception => e
+      err = e
+    end
+
+    assert_not_nil err
+    assert_equal(err.message, "Converting circular structure to BSON")
 
     puts "test_ejdb5_circular has passed successfull"
   end
-=end
 
 
   def test_ejdb6_save_load_buffer
@@ -293,6 +303,7 @@ class EJDBTestUnit < Test::Unit::TestCase
     puts "test_ejdb9_test_update1 has passed successfull"
   end
 
+
   def test_ejdba_id_nin
     assert_not_nil $jb
     assert $jb.is_open?
@@ -316,6 +327,7 @@ class EJDBTestUnit < Test::Unit::TestCase
     puts "test_ejdba_id_nin has passed successfull"
   end
 
+
   def test_ejdbb_test_remove
     assert_not_nil $jb
     assert $jb.is_open?
@@ -334,6 +346,7 @@ class EJDBTestUnit < Test::Unit::TestCase
     puts "test_ejdbb_test_remove has passed successfull"
   end
 
+
   def test_ejdbc_sync
     assert_not_nil $jb
     assert $jb.is_open?
@@ -341,6 +354,7 @@ class EJDBTestUnit < Test::Unit::TestCase
     puts "test_ejdbc_sync has passed successfull"
   end
 
+
   def test_ejdbd_remove_colls
     assert_not_nil $jb
     assert $jb.is_open?
@@ -354,6 +368,7 @@ class EJDBTestUnit < Test::Unit::TestCase
     puts "test_ejdbd_remove_colls has passed successfull"
   end
 
+
   def test_ejdbd_tx1
     assert_not_nil $jb
     assert $jb.is_open?
@@ -399,6 +414,7 @@ class EJDBTestUnit < Test::Unit::TestCase
     puts "test_ejdbd_tx1 has passed successfull"
   end
 
+
   def test_ejdbe_create_collection_on_upsert
     assert_not_nil $jb
     assert $jb.is_open?