#50 - advanced tests
authorFedor Yudanov <fedwiz@academ.org>
Mon, 1 Apr 2013 08:16:36 +0000 (15:16 +0700)
committerFedor Yudanov <fedwiz@academ.org>
Mon, 1 Apr 2013 08:16:36 +0000 (15:16 +0700)
rbejdb/Makefile
rbejdb/src/rbbson.c
rbejdb/src/rbbson.h
rbejdb/src/rbejdb.c
rbejdb/test/Makefile
rbejdb/test/t1.rb
rbejdb/test/t2.rb

index ec6de8e..8ea0edd 100644 (file)
@@ -12,5 +12,6 @@ check:
 doc:
 
 clean:
+       rm -rf build
 
 .PHONY: all build check clean doc
index 7acf287..38d8c80 100644 (file)
@@ -20,6 +20,9 @@ VALUE iterate_array_callback(VALUE val, VALUE bsonWrap);
 
 VALUE bson_array_to_ruby(bson_iterator* it);
 
+bson_date_t ruby_time_to_bson_internal(VALUE time);
+
+
 VALUE bsonWrapClass = Qnil;
 
 
@@ -72,12 +75,21 @@ int iterate_key_values_callback(VALUE key, VALUE val, VALUE bsonWrap) {
         case T_FIXNUM:
             bson_append_int(b, attrName, FIX2INT(val));
             break;
+        case T_DATA:
+            if (0 == strcmp(rb_obj_classname(val), "Time")) {
+                bson_append_date(b, attrName, ruby_time_to_bson_internal(val));
+            } else {
+                rb_raise(rb_eRuntimeError, "Cannot convert ruby data object to bson");
+            }
         case T_TRUE:
             bson_append_bool(b, attrName, 1);
             break;
         case T_FALSE:
             bson_append_bool(b, attrName, 0);
             break;
+        case T_NIL:
+            bson_append_null(b, attrName);
+            break;
         default:
             rb_raise(rb_eRuntimeError, "Cannot convert value type to bson: %d", TYPE(val));
     }
@@ -101,6 +113,12 @@ VALUE iterate_object_attrs_callback(VALUE key, VALUE bsonWrap) {
     return val;
 }
 
+bson_date_t ruby_time_to_bson_internal(VALUE time) {
+    VALUE microsecs = rb_funcall(time, rb_intern("to_f"), 0);
+    Check_Type(microsecs, T_FLOAT);
+    return (bson_date_t) NUM2DBL(microsecs) * 1000;
+}
+
 
 void ruby_object_to_bson_internal(VALUE rbobj, VALUE bsonWrap) {
     Check_Type(rbobj, T_OBJECT);
@@ -130,6 +148,7 @@ void ruby_to_bson(VALUE rbobj, bson** bsonresp, int flags) {
 
     switch (TYPE(rbobj)) {
         case T_OBJECT:
+        case T_DATA:
             ruby_object_to_bson_internal(rbobj, bsonWrap);
             break;
         case T_HASH:
@@ -148,11 +167,8 @@ void ruby_to_bson(VALUE rbobj, bson** bsonresp, int flags) {
 VALUE bson_iterator_to_ruby(bson_iterator* it, bson_type t) {
     VALUE val;
     switch (t) {
-        case BSON_OID: {
-                char oidhex[25];
-                bson_oid_to_string(bson_iterator_oid(it), oidhex);
-                val = rb_str_new2(oidhex);
-            }
+        case BSON_OID:
+            val = bson_oid_to_ruby(bson_iterator_oid(it));
             break;
         case BSON_STRING:
             val = rb_str_new2(bson_iterator_string(it));
@@ -205,3 +221,9 @@ VALUE bson_to_ruby(bson* bsonval) {
     }
     return res;
 }
+
+VALUE bson_oid_to_ruby(bson_oid_t* oid) {
+    char oidhex[25];
+    bson_oid_to_string(oid, oidhex);
+    return rb_str_new2(oidhex);
+}
index e04e84f..3b4bef5 100644 (file)
@@ -23,6 +23,8 @@ extern "C" {
 
     VALUE bson_to_ruby(bson* bsonval);
 
+    VALUE bson_oid_to_ruby(bson_oid_t* oid);
+
 #ifdef __cplusplus
 }
 #endif
index 3db2d1f..35cb3a5 100644 (file)
@@ -40,7 +40,7 @@ VALUE ejdbResultsClass;
 static int raise_ejdb_error(EJDB *ejdb) {
     int ecode = ejdbecode(ejdb);
     const char *emsg = ejdberrmsg(ecode);
-    rb_raise(rb_eRuntimeError, emsg);
+    rb_raise(rb_eRuntimeError, "%s", emsg);
 }
 
 
@@ -80,7 +80,7 @@ VALUE EJDB_open(VALUE clazz, VALUE path, VALUE mode) {
         rb_raise(rb_eRuntimeError, "Failed to init ejdb!");
     }
 
-    if (!ejdbopen(rejdb->ejdb, StringValuePtr(path), FIX2INT(mode))) {
+    if (!ejdbopen(rejdb->ejdb, StringValuePtr(path), NUM2INT(mode))) {
         raise_ejdb_error(rejdb->ejdb);
     }
     return ejdbWrap;
@@ -144,6 +144,9 @@ VALUE EJDB_save(int argc, VALUE *argv, VALUE self) {
 
     VALUE collName = argv[0];
     Check_Type(collName, T_STRING);
+
+    VALUE oids = rb_ary_new();
+
     EJCOLL *coll = ejdbcreatecoll(ejdb, StringValuePtr(collName), NULL);
     if (!coll) {
         raise_ejdb_error(ejdb);
@@ -151,8 +154,14 @@ VALUE EJDB_save(int argc, VALUE *argv, VALUE self) {
 
     int i;
     for (i = 1; i < argc; i++) {
+        VALUE rbobj = argv[i];
+        if (NIL_P(rbobj)) {
+            rb_ary_push(oids, Qnil);
+            continue;
+        }
+
         bson* bsonval;
-        ruby_to_bson(argv[i], &bsonval, 0);
+        ruby_to_bson(rbobj, &bsonval, 0);
 
         bson_oid_t oid;
         if (!ejdbsavebson2(coll, bsonval, &oid, true /*TODO read this param*/)) {
@@ -161,8 +170,24 @@ VALUE EJDB_save(int argc, VALUE *argv, VALUE self) {
         }
 
         bson_destroy(bsonval);
+
+        VALUE roid = bson_oid_to_ruby(&oid);
+        rb_ary_push(oids, roid);
+
+        switch(TYPE(rbobj)) {
+            case T_HASH:
+                rb_hash_aset(rbobj, rb_str_new2("_id"), roid);
+                break;
+            default:
+                rb_iv_set(rbobj, "@id", roid);
+        }
+    }
+
+    switch (RARRAY_LEN(oids)) {
+        case 0 : return Qnil;
+        case 1: return rb_ary_pop(oids);
+        default: return oids;
     }
-    return Qnil;
 }
 
 VALUE EJDB_find(int argc, VALUE* argv, VALUE self) {
@@ -236,6 +261,10 @@ Init_rbejdb() {
     rb_define_private_method(ejdbClass, "new", RUBY_METHOD_FUNC(EJDB_new), 0);
 
     rb_define_const(ejdbClass, "DEFAULT_OPEN_MODE", INT2FIX(DEFAULT_OPEN_MODE));
+    rb_define_const(ejdbClass, "JBOWRITER", INT2FIX(JBOWRITER));
+    rb_define_const(ejdbClass, "JBOCREAT", INT2FIX(JBOCREAT));
+    rb_define_const(ejdbClass, "JBOTSYNC", INT2FIX(JBOTSYNC));
+    rb_define_const(ejdbClass, "JBOTRUNC", INT2FIX(JBOTRUNC));
 
     rb_define_singleton_method(ejdbClass, "open", RUBY_METHOD_FUNC(EJDB_open), 2);
     rb_define_method(ejdbClass, "is_open?", RUBY_METHOD_FUNC(EJDB_is_open), 0);
index 32cbb5f..8c7527e 100644 (file)
@@ -3,5 +3,6 @@ all: check
 
 check:
        ruby t1.rb
+       ruby t2.rb
 
 .PHONY: all check
index c941e32..92f15be 100644 (file)
@@ -42,4 +42,4 @@ ejdb.close
 
 raise "Failed to close ejdb" unless !ejdb.is_open?
 
-puts "CONGRATULATIONS!!! EJDB tests have passed completely!"
+puts "CONGRATULATIONS!!! Test batch 1 has passed completely!"
index 73edd86..74bd350 100644 (file)
@@ -1,4 +1,43 @@
 require "rbejdb"
+require 'test/unit'
 
-db = EJDB.open("testdb", "rwct")
-raise "Failed to open ejdb" unless db.is_open?
+
+$now = Time.now
+$jb = EJDB.open("tdbt2", EJDB::JBOWRITER | EJDB::JBOCREAT | EJDB::JBOTRUNC)
+
+class EJDBTestUnit < Test::Unit::TestCase
+  def test_save_load
+      assert $jb.is_open?
+
+      parrot1 = {
+          "name" => "Grenny",
+          "type" => "African Grey",
+          "male" => true,
+          "age" => 1,
+          "birthdate" => $now,
+          "likes" => ["green color", "night", "toys"],
+          "extra1" => nil
+      }
+      parrot2 = {
+          "name" => "Bounty",
+          "type" => "Cockatoo",
+          "male" => false,
+          "age" => 15,
+          "birthdate" => $now,
+          "likes" => ["sugar cane"],
+          "extra1" => nil
+      }
+
+      oids = $jb.save("parrots", parrot1, nil, parrot2)
+      assert_not_nil oids
+      assert_equal(oids.length, 3)
+      assert_equal(parrot1["_id"], oids[0])
+      assert_nil oids[1]
+      assert_equal(parrot2["_id"], oids[2])
+
+      obj = $jb.load("parrots", parrot2["_id"])
+      assert_not_nil obj
+      assert_equal(obj["_id"], parrot2["_id"])
+      assert_equal(obj["name"], "Bounty")
+  end
+end