summaryrefslogtreecommitdiff
path: root/tests/func/mongo/sync
diff options
context:
space:
mode:
Diffstat (limited to 'tests/func/mongo/sync')
-rw-r--r--tests/func/mongo/sync/f_sync_auto_reauth.c58
-rw-r--r--tests/func/mongo/sync/f_sync_auto_reconnect.c61
-rw-r--r--tests/func/mongo/sync/f_sync_auto_reconnect_cache.c107
-rw-r--r--tests/func/mongo/sync/f_sync_conn_seed_add.c58
-rw-r--r--tests/func/mongo/sync/f_sync_invalid_getlasterror.c27
-rw-r--r--tests/func/mongo/sync/f_sync_max_insert_size.c69
-rw-r--r--tests/func/mongo/sync/f_sync_oidtest.c44
-rw-r--r--tests/func/mongo/sync/f_sync_safe_mode.c112
-rw-r--r--tests/func/mongo/sync/f_sync_safe_mode_cache.c131
-rw-r--r--tests/func/mongo/sync/f_sync_write_error.c52
10 files changed, 719 insertions, 0 deletions
diff --git a/tests/func/mongo/sync/f_sync_auto_reauth.c b/tests/func/mongo/sync/f_sync_auto_reauth.c
new file mode 100644
index 0000000..477dd25
--- /dev/null
+++ b/tests/func/mongo/sync/f_sync_auto_reauth.c
@@ -0,0 +1,58 @@
+#include "test.h"
+#include <mongo.h>
+
+#include <errno.h>
+#include <sys/socket.h>
+
+#include "libmongo-private.h"
+
+
+/*
+ * This test requires that the "lmcUser" user (password "lmcPass") has
+ * RW access to the test db. It must be set up prior to running this
+ * test.
+ */
+void
+test_func_mongo_sync_auto_reauth (void)
+{
+ mongo_sync_connection *conn;
+ bson *b;
+
+ b = bson_new ();
+ bson_append_int32 (b, "f_sync_auto_reauth", 1);
+ bson_finish (b);
+
+ conn = mongo_sync_connect (config.primary_host, config.primary_port,
+ TRUE);
+
+ mongo_sync_conn_set_safe_mode (conn, TRUE);
+
+ skip (mongo_sync_cmd_insert (conn, config.ns, b, NULL) == TRUE, 3,
+ "Authentication not configured.");
+
+ skip (mongo_sync_cmd_authenticate (conn, config.db, "lmcUser", "lmcPass")== FALSE, 3,
+ "Authentication environment not set up for testing.");
+
+ ok (mongo_sync_cmd_insert (conn, config.ns, b, NULL) == TRUE,
+ "Inserting works after authentication.");
+
+ shutdown (conn->super.fd, SHUT_RDWR);
+ sleep (1);
+
+ ok (mongo_sync_cmd_insert (conn, config.ns, b, NULL) == FALSE,
+ "Inserting fails with auto-reconnect turned off, and a broken "
+ "connection");
+
+ mongo_sync_conn_set_auto_reconnect (conn, TRUE);
+
+ ok (mongo_sync_cmd_insert (conn, config.ns, b, NULL) == TRUE,
+ "Inserting works with auto-reconnect turned on, and auto-auth, "
+ "and a broken connection.");
+
+ endskip;
+ endskip;
+
+ mongo_sync_disconnect (conn);
+}
+
+RUN_NET_TEST (3, func_mongo_sync_auto_reauth);
diff --git a/tests/func/mongo/sync/f_sync_auto_reconnect.c b/tests/func/mongo/sync/f_sync_auto_reconnect.c
new file mode 100644
index 0000000..45ec28d
--- /dev/null
+++ b/tests/func/mongo/sync/f_sync_auto_reconnect.c
@@ -0,0 +1,61 @@
+#include "test.h"
+#include <mongo.h>
+
+#include <errno.h>
+#include <sys/socket.h>
+
+#include "libmongo-private.h"
+
+void
+test_func_mongo_sync_auto_reconnect (void)
+{
+ mongo_sync_connection *conn;
+ bson *b;
+ mongo_packet *p;
+
+ b = bson_new ();
+ bson_append_int32 (b, "f_sync_auto_reconnect", 1);
+ bson_finish (b);
+
+ conn = mongo_sync_connect (config.primary_host, config.primary_port,
+ TRUE);
+ ok (mongo_sync_cmd_insert (conn, config.ns, b, NULL) == TRUE);
+
+ shutdown (conn->super.fd, SHUT_RDWR);
+ sleep (1);
+
+ ok (mongo_sync_cmd_insert (conn, config.ns, b, NULL) == FALSE,
+ "Inserting fails with auto-reconnect turned off, and a broken "
+ "connection");
+
+ mongo_sync_conn_set_auto_reconnect (conn, TRUE);
+
+ ok (mongo_sync_cmd_insert (conn, config.ns, b, NULL) == TRUE,
+ "Inserting works with auto-reconnect turned on, and a broken "
+ "connection");
+
+ mongo_sync_conn_set_auto_reconnect (conn, FALSE);
+
+ shutdown (conn->super.fd, SHUT_RDWR);
+ sleep (1);
+
+ ok (mongo_sync_cmd_insert (conn, config.ns, b, NULL) == FALSE,
+ "Turning off auto-reconnect works");
+
+ shutdown (conn->super.fd, SHUT_RDWR);
+ sleep (1);
+
+ p = mongo_sync_cmd_query (conn, config.ns, 0, 0, 1, b, NULL);
+ ok (p == NULL,
+ "Query fails with auto-reconnect turned off");
+
+ mongo_sync_conn_set_auto_reconnect (conn, TRUE);
+ p = mongo_sync_cmd_query (conn, config.ns, 0, 0, 1, b, NULL);
+ ok (p != NULL,
+ "Query does reconnect with auto-reconnect turned on");
+ mongo_wire_packet_free (p);
+
+ mongo_sync_disconnect (conn);
+}
+
+RUN_NET_TEST (6, func_mongo_sync_auto_reconnect);
diff --git a/tests/func/mongo/sync/f_sync_auto_reconnect_cache.c b/tests/func/mongo/sync/f_sync_auto_reconnect_cache.c
new file mode 100644
index 0000000..d69ea5d
--- /dev/null
+++ b/tests/func/mongo/sync/f_sync_auto_reconnect_cache.c
@@ -0,0 +1,107 @@
+#include "test.h"
+#include <mongo.h>
+
+#include <errno.h>
+#include <sys/socket.h>
+
+#include "libmongo-private.h"
+
+void
+test_func_mongo_sync_auto_reconnect_cache (void)
+{
+ mongo_sync_conn_recovery_cache *cache;
+ mongo_sync_connection *conn;
+ bson *b;
+ mongo_packet *p;
+ gchar *primary_addr;
+ const gchar *error_msg;
+
+ primary_addr = g_strdup_printf ("%s:%d", config.primary_host, config.primary_port);
+
+ b = bson_new ();
+ bson_append_int32 (b, "f_sync_auto_reconnect", 1);
+ bson_finish (b);
+
+ cache = mongo_sync_conn_recovery_cache_new ();
+
+ mongo_sync_conn_recovery_cache_seed_add (cache,
+ config.primary_host,
+ config.primary_port);
+
+ conn = mongo_sync_connect_recovery_cache (cache,
+ TRUE);
+
+ ok (mongo_sync_cmd_insert (conn, config.ns, b, NULL) == TRUE);
+
+ shutdown (conn->super.fd, SHUT_RDWR);
+ sleep (1);
+
+ ok (mongo_sync_cmd_insert (conn, config.ns, b, NULL) == FALSE,
+ "Inserting fails with auto-reconnect turned off, and a broken "
+ "connection");
+
+ error_msg = mongo_sync_conn_get_last_error (conn);
+
+ ok (error_msg != NULL, "We have an error msg when insert fails.");
+
+ mongo_sync_conn_set_auto_reconnect (conn, TRUE);
+
+ ok (mongo_sync_cmd_insert (conn, config.ns, b, NULL) == TRUE,
+ "Inserting works with auto-reconnect turned on, and a broken "
+ "connection");
+
+ error_msg = mongo_sync_conn_get_last_error (conn);
+
+ ok (error_msg == NULL,
+ "After a succesful insert we shouldn't have an error msg.");
+
+ mongo_sync_conn_set_auto_reconnect (conn, FALSE);
+
+ shutdown (conn->super.fd, SHUT_RDWR);
+ sleep (1);
+
+ ok (mongo_sync_cmd_insert (conn, config.ns, b, NULL) == FALSE,
+ "Turning off auto-reconnect works");
+
+ skip (!config.secondary_host, 7,
+ "Secondary host not set up");
+
+ shutdown (conn->super.fd, SHUT_RDWR);
+ sleep (1);
+
+ p = mongo_sync_cmd_query (conn, config.ns, 0, 0, 1, b, NULL);
+ ok (p == NULL,
+ "Query fails with auto-reconnect turned off");
+
+ error_msg = mongo_sync_conn_get_last_error(conn);
+ ok (error_msg != NULL, "We have an error msg after a failure query.");
+
+ mongo_sync_conn_set_auto_reconnect (conn, TRUE);
+ p = mongo_sync_cmd_query (conn, config.ns, 0, 0, 1, b, NULL);
+ ok (p != NULL,
+ "Query does reconnect with auto-reconnect turned on");
+
+ ok (mongo_sync_conn_get_last_error(conn) == NULL,
+ "We shouldn't have any error messages after a successful operation.");
+
+ mongo_wire_packet_free (p);
+
+ mongo_sync_cmd_is_master (conn);
+
+ ok (conn->rs.hosts != NULL,
+ "We have hosts in the connection's replica set.");
+
+ ok (cache->rs.hosts == NULL, "Cache is empty.");
+
+ mongo_sync_disconnect (conn);
+
+ ok (cache->rs.hosts != NULL, "Cache is filled by disconnect()");
+
+ mongo_sync_conn_recovery_cache_free (cache);
+
+ endskip;
+
+ g_free (primary_addr);
+}
+
+RUN_NET_TEST (13, func_mongo_sync_auto_reconnect_cache);
diff --git a/tests/func/mongo/sync/f_sync_conn_seed_add.c b/tests/func/mongo/sync/f_sync_conn_seed_add.c
new file mode 100644
index 0000000..03bcdd2
--- /dev/null
+++ b/tests/func/mongo/sync/f_sync_conn_seed_add.c
@@ -0,0 +1,58 @@
+#include "test.h"
+#include <mongo.h>
+
+#include "libmongo-private.h"
+
+void
+test_func_mongo_sync_conn_seed_add (void)
+{
+ mongo_sync_connection *conn;
+ GList *l;
+
+ conn = mongo_sync_connect (config.primary_host, config.primary_port,
+ FALSE);
+ close (conn->super.fd);
+
+ l = conn->rs.hosts;
+ while (l)
+ {
+ g_free (l->data);
+ l = g_list_delete_link (l, l);
+ }
+ conn->rs.hosts = NULL;
+
+ l = conn->rs.seeds;
+ while (l)
+ {
+ g_free (l->data);
+ l = g_list_delete_link (l, l);
+ }
+ conn->rs.seeds = NULL;
+
+ conn = mongo_sync_reconnect (conn, TRUE);
+ ok (conn == NULL,
+ "mongo_sync_reconnect() fails without seeds or discovery");
+
+ conn = mongo_sync_connect (config.primary_host, config.primary_port,
+ FALSE);
+ close (conn->super.fd);
+ l = conn->rs.hosts;
+ while (l)
+ {
+ g_free (l->data);
+ l = g_list_delete_link (l, l);
+ }
+ conn->rs.hosts = NULL;
+
+ ok (mongo_sync_conn_seed_add (conn, config.primary_host,
+ config.primary_port),
+ "mongo_sync_conn_seed_add() works");
+
+ conn = mongo_sync_reconnect (conn, TRUE);
+ ok (conn != NULL,
+ "mongo_sync_reconnect() works when properly seeded");
+
+ mongo_sync_disconnect (conn);
+}
+
+RUN_NET_TEST (3, func_mongo_sync_conn_seed_add);
diff --git a/tests/func/mongo/sync/f_sync_invalid_getlasterror.c b/tests/func/mongo/sync/f_sync_invalid_getlasterror.c
new file mode 100644
index 0000000..6af227b
--- /dev/null
+++ b/tests/func/mongo/sync/f_sync_invalid_getlasterror.c
@@ -0,0 +1,27 @@
+#include "test.h"
+#include <mongo.h>
+#include <errno.h>
+
+void
+test_func_mongo_sync_invalid_getlasterror (void)
+{
+ mongo_sync_connection *conn;
+ gchar *error = NULL;
+ gboolean res;
+
+ conn = mongo_sync_connect (config.primary_host, config.primary_port,
+ TRUE);
+
+ res = mongo_sync_cmd_get_last_error
+ (conn, "1234567890123456789012345678901234567890123456789012345678901234567890",
+ &error);
+
+ ok (res == FALSE,
+ "Trying to get the last error from an invalid DB results in an error.");
+ ok (error == NULL,
+ "When getLastError() fails, error remains NULL");
+
+ mongo_sync_disconnect (conn);
+}
+
+RUN_NET_TEST (2, func_mongo_sync_invalid_getlasterror);
diff --git a/tests/func/mongo/sync/f_sync_max_insert_size.c b/tests/func/mongo/sync/f_sync_max_insert_size.c
new file mode 100644
index 0000000..9ea5854
--- /dev/null
+++ b/tests/func/mongo/sync/f_sync_max_insert_size.c
@@ -0,0 +1,69 @@
+#include "test.h"
+#include <mongo.h>
+
+#include <errno.h>
+
+#include "libmongo-private.h"
+
+void
+test_func_mongo_sync_max_insert_size (void)
+{
+ mongo_sync_connection *conn;
+ const bson *docs[10];
+ bson *b1, *b2, *b3;
+
+ b1 = bson_new ();
+ bson_append_string (b1, "func_mongo_sync_max_insert_size", "works", -1);
+
+ bson_finish (b1);
+ b2 = bson_new ();
+ bson_append_int32 (b2, "int32", 1984);
+ bson_finish (b2);
+ b3 = bson_new ();
+ bson_finish (b3);
+
+ conn = mongo_sync_connect (config.primary_host, config.primary_port,
+ FALSE);
+
+ /*
+ * cmd_insert_n()
+ */
+ mongo_sync_conn_set_max_insert_size (conn, bson_size (b1) +
+ bson_size (b3) + 1);
+
+ docs[0] = b1;
+ docs[1] = b2;
+ docs[2] = b3;
+
+ ok (mongo_sync_cmd_insert_n (conn, config.ns, 3, docs) == TRUE,
+ "mongo_sync_cmd_insert_n() works with a small max_insert_size");
+
+ mongo_sync_conn_set_max_insert_size (conn, 1);
+ errno = 0;
+ ok (mongo_sync_cmd_insert_n (conn, config.ns, 3, docs) == FALSE,
+ "mongo_sync_cmd_insert_n() should fail if any one document is too big");
+ cmp_ok (errno, "==", EMSGSIZE,
+ "errno is set to EMSGSIZE");
+
+ /*
+ * cmd_insert()
+ */
+ mongo_sync_conn_set_max_insert_size (conn, bson_size (b1) +
+ bson_size (b3) + 1);
+ ok (mongo_sync_cmd_insert (conn, config.ns, b1, b2, b3, NULL) == TRUE,
+ "mongo_sync_cmd_insert() works with a small max_insert_size");
+
+ mongo_sync_conn_set_max_insert_size (conn, 1);
+ errno = 0;
+ ok (mongo_sync_cmd_insert (conn, config.ns, b1, b2, b3, NULL) == FALSE,
+ "mongo_sync_cmd_insert() should fail if any one document is too big");
+ cmp_ok (errno, "==", EMSGSIZE,
+ "errno is set to EMSGSIZE");
+
+ mongo_sync_disconnect (conn);
+ bson_free (b1);
+ bson_free (b2);
+ bson_free (b3);
+}
+
+RUN_NET_TEST (6, func_mongo_sync_max_insert_size);
diff --git a/tests/func/mongo/sync/f_sync_oidtest.c b/tests/func/mongo/sync/f_sync_oidtest.c
new file mode 100644
index 0000000..2a64692
--- /dev/null
+++ b/tests/func/mongo/sync/f_sync_oidtest.c
@@ -0,0 +1,44 @@
+#include "test.h"
+#include <mongo.h>
+
+#include <string.h>
+
+void
+test_func_mongo_sync_oidtest (void)
+{
+ mongo_sync_connection *conn;
+ bson *boid, *reply = NULL;
+ bson_cursor *c;
+ mongo_packet *p;
+ guint8 *oid;
+ const guint8 *noid;
+
+ mongo_util_oid_init (0);
+
+ oid = mongo_util_oid_new (1);
+ boid = bson_new ();
+ bson_append_oid (boid, "driverOIDTest", oid);
+ bson_finish (boid);
+
+ conn = mongo_sync_connect (config.primary_host, config.primary_port,
+ FALSE);
+
+ p = mongo_sync_cmd_custom (conn, config.db, boid);
+ ok (p != NULL,
+ "driverOIDTest(OID) custom command works");
+ mongo_wire_reply_packet_get_nth_document (p, 1, &reply);
+ bson_finish (reply);
+
+ c = bson_find (reply, "oid");
+ bson_cursor_get_oid (c, &noid);
+ ok (memcmp (oid, noid, 12) == 0,
+ "driverOIDTest(OID) returns the same OID");
+ bson_cursor_free (c);
+
+ mongo_sync_disconnect (conn);
+ mongo_wire_packet_free (p);
+ bson_free (boid);
+ bson_free (reply);
+}
+
+RUN_NET_TEST (2, func_mongo_sync_oidtest);
diff --git a/tests/func/mongo/sync/f_sync_safe_mode.c b/tests/func/mongo/sync/f_sync_safe_mode.c
new file mode 100644
index 0000000..e312c2f
--- /dev/null
+++ b/tests/func/mongo/sync/f_sync_safe_mode.c
@@ -0,0 +1,112 @@
+#include "test.h"
+#include <mongo.h>
+
+#include <errno.h>
+#include <string.h>
+
+#include "libmongo-private.h"
+
+void
+test_func_mongo_sync_safe_mode_basics (void)
+{
+ mongo_sync_connection *conn;
+ const bson *docs[10];
+ bson *b1, *b2, *b3, *b4, *cmd;
+ mongo_packet *p;
+ gchar *error;
+
+ mongo_util_oid_init (0);
+
+ b1 = bson_new ();
+ bson_append_string (b1, "func_mongo_sync_safe_mode", "works", -1);
+ bson_finish (b1);
+
+ b2 = bson_new ();
+ bson_append_int32 (b2, "int32", 1984);
+ bson_finish (b2);
+
+ b3 = test_bson_generate_full ();
+ b4 = test_bson_generate_full ();
+
+ docs[0] = b1;
+ docs[1] = b2;
+ docs[2] = b3;
+ docs[3] = b4;
+
+ conn = mongo_sync_connect (config.primary_host, config.primary_port,
+ FALSE);
+
+ /* Test inserts */
+ mongo_sync_conn_set_safe_mode (conn, FALSE);
+ ok (mongo_sync_cmd_insert_n (conn, config.ns, 4, docs) == TRUE,
+ "mongo_sync_cmd_insert_n() should not fail with safe mode off");
+
+ mongo_sync_conn_set_safe_mode (conn, TRUE);
+ ok (mongo_sync_cmd_insert_n (conn, config.ns, 4, docs) == FALSE,
+ "mongo_sync_cmd_insert_n() should fail with safe mode on");
+
+ /* Test a custom command */
+ cmd = bson_new ();
+ bson_append_int32 (cmd, "bogusCommand", 1);
+ bson_finish (cmd);
+
+ mongo_sync_cmd_reset_error (conn, config.db);
+ mongo_sync_conn_set_safe_mode (conn, FALSE);
+ p = mongo_sync_cmd_custom (conn, config.db, cmd);
+ mongo_sync_cmd_get_last_error (conn, config.db, &error);
+ ok (p == NULL && strcmp (error, "no such cmd: bogusCommand") == 0,
+ "mongo_sync_cmd_custom() with a bogus command fails with safe-mode off");
+ bson_free (cmd);
+
+ cmd = bson_new ();
+ bson_append_int32 (cmd, "bogusCommand2", 1);
+ bson_finish (cmd);
+ mongo_sync_cmd_reset_error (conn, config.db);
+ mongo_sync_conn_set_safe_mode (conn, TRUE);
+ p = mongo_sync_cmd_custom (conn, config.db, cmd);
+ mongo_sync_cmd_get_last_error (conn, config.db, &error);
+ ok (p == NULL && strcmp (error, "no such cmd: bogusCommand2") == 0,
+ "mongo_sync_cmd_custom() with a bogus command fails with safe-mode on");
+ bson_free (cmd);
+
+ mongo_sync_disconnect (conn);
+ bson_free (b1);
+ bson_free (b2);
+ bson_free (b3);
+ bson_free (b4);
+}
+
+#define INVALID_NS "1234567890123456789012345678901234567890123456789012345678901234567890.test"
+
+void
+test_func_mongo_sync_safe_mode_invalid_db (void)
+{
+ mongo_sync_connection *conn;
+ bson *b;
+ const bson *docs[1];
+
+ b = bson_new ();
+ bson_append_int32 (b, "int32", 1984);
+ bson_finish (b);
+
+ docs[0] = b;
+
+ conn = mongo_sync_connect (config.primary_host, config.primary_port,
+ TRUE);
+ mongo_sync_conn_set_safe_mode (conn, TRUE);
+
+ ok (mongo_sync_cmd_insert_n (conn, INVALID_NS, 1, docs) == FALSE,
+ "mongo_sync_cmd_insert_n() should fail with safe mode on and an invalid NS");
+
+ mongo_sync_disconnect (conn);
+ bson_free (b);
+}
+
+void
+test_func_mongo_sync_safe_mode (void)
+{
+ test_func_mongo_sync_safe_mode_basics ();
+ test_func_mongo_sync_safe_mode_invalid_db ();
+}
+
+RUN_NET_TEST (5, func_mongo_sync_safe_mode);
diff --git a/tests/func/mongo/sync/f_sync_safe_mode_cache.c b/tests/func/mongo/sync/f_sync_safe_mode_cache.c
new file mode 100644
index 0000000..082617f
--- /dev/null
+++ b/tests/func/mongo/sync/f_sync_safe_mode_cache.c
@@ -0,0 +1,131 @@
+#include "test.h"
+#include <mongo.h>
+
+#include <errno.h>
+#include <string.h>
+
+#include "libmongo-private.h"
+
+void
+test_func_mongo_sync_safe_mode_basics_cache (void)
+{
+ mongo_sync_connection *conn;
+ mongo_sync_conn_recovery_cache *cache;
+
+ const bson *docs[10];
+ bson *b1, *b2, *b3, *b4, *cmd;
+ mongo_packet *p;
+ gchar *error;
+
+ mongo_util_oid_init (0);
+
+ b1 = bson_new ();
+ bson_append_string (b1, "func_mongo_sync_safe_mode", "works", -1);
+ bson_finish (b1);
+
+ b2 = bson_new ();
+ bson_append_int32 (b2, "int32", 1984);
+ bson_finish (b2);
+
+ b3 = test_bson_generate_full ();
+ b4 = test_bson_generate_full ();
+
+ docs[0] = b1;
+ docs[1] = b2;
+ docs[2] = b3;
+ docs[3] = b4;
+
+ cache = mongo_sync_conn_recovery_cache_new ();
+
+ mongo_sync_conn_recovery_cache_seed_add (cache,
+ config.primary_host,
+ config.primary_port);
+
+ conn = mongo_sync_connect_recovery_cache (cache, FALSE);
+
+ /* Test inserts */
+ mongo_sync_conn_set_safe_mode (conn, FALSE);
+ ok (mongo_sync_cmd_insert_n (conn, config.ns, 4, docs) == TRUE,
+ "mongo_sync_cmd_insert_n() should not fail with safe mode off");
+
+ mongo_sync_conn_set_safe_mode (conn, TRUE);
+ ok (mongo_sync_cmd_insert_n (conn, config.ns, 4, docs) == FALSE,
+ "mongo_sync_cmd_insert_n() should fail with safe mode on");
+
+ /* Test a custom command */
+ cmd = bson_new ();
+ bson_append_int32 (cmd, "bogusCommand", 1);
+ bson_finish (cmd);
+
+ mongo_sync_cmd_reset_error (conn, config.db);
+ mongo_sync_conn_set_safe_mode (conn, FALSE);
+ p = mongo_sync_cmd_custom (conn, config.db, cmd);
+ mongo_sync_cmd_get_last_error (conn, config.db, &error);
+ ok (p == NULL && strcmp (error, "no such cmd: bogusCommand") == 0,
+ "mongo_sync_cmd_custom() with a bogus command fails with safe-mode off");
+ bson_free (cmd);
+ g_free (error);
+
+ cmd = bson_new ();
+ bson_append_int32 (cmd, "bogusCommand2", 1);
+ bson_finish (cmd);
+ mongo_sync_cmd_reset_error (conn, config.db);
+ mongo_sync_conn_set_safe_mode (conn, TRUE);
+ p = mongo_sync_cmd_custom (conn, config.db, cmd);
+ mongo_sync_cmd_get_last_error (conn, config.db, &error);
+ ok (p == NULL && strcmp (error, "no such cmd: bogusCommand2") == 0,
+ "mongo_sync_cmd_custom() with a bogus command fails with safe-mode on");
+ bson_free (cmd);
+ g_free (error);
+
+ mongo_sync_disconnect (conn);
+ mongo_sync_conn_recovery_cache_free (cache);
+
+ bson_free (b1);
+ bson_free (b2);
+ bson_free (b3);
+ bson_free (b4);
+}
+
+#define INVALID_NS "1234567890123456789012345678901234567890123456789012345678901234567890.test"
+
+void
+test_func_mongo_sync_safe_mode_invalid_db_cache (void)
+{
+ mongo_sync_connection *conn;
+ mongo_sync_conn_recovery_cache *cache;
+ bson *b;
+ const bson *docs[1];
+
+ b = bson_new ();
+ bson_append_int32 (b, "int32", 1984);
+ bson_finish (b);
+
+ docs[0] = b;
+
+ cache = mongo_sync_conn_recovery_cache_new ();
+
+ mongo_sync_conn_recovery_cache_seed_add (cache,
+ config.primary_host,
+ config.primary_port);
+
+ conn = mongo_sync_connect_recovery_cache (cache, TRUE);
+
+ mongo_sync_conn_set_safe_mode (conn, TRUE);
+
+ ok (mongo_sync_cmd_insert_n (conn, INVALID_NS, 1, docs) == FALSE,
+ "mongo_sync_cmd_insert_n() should fail with safe mode on and an invalid NS");
+
+ mongo_sync_disconnect (conn);
+ mongo_sync_conn_recovery_cache_free (cache);
+ bson_free (b);
+}
+
+void
+test_func_mongo_sync_safe_mode_cache (void)
+{
+ test_func_mongo_sync_safe_mode_basics_cache ();
+ test_func_mongo_sync_safe_mode_invalid_db_cache ();
+}
+
+RUN_NET_TEST (5, func_mongo_sync_safe_mode_cache);
diff --git a/tests/func/mongo/sync/f_sync_write_error.c b/tests/func/mongo/sync/f_sync_write_error.c
new file mode 100644
index 0000000..b6d4750
--- /dev/null
+++ b/tests/func/mongo/sync/f_sync_write_error.c
@@ -0,0 +1,52 @@
+#include "test.h"
+#include <mongo.h>
+
+#include <errno.h>
+#include <sys/socket.h>
+
+#include "libmongo-private.h"
+
+#define INVALID_NS "test.$Uncle$.Dagobert$"
+
+void
+test_func_mongo_sync_write_error (void)
+{
+ mongo_sync_connection *conn;
+ bson *b;
+ const gchar *error_msg;
+
+ b = bson_new ();
+ bson_append_int32 (b, "f_sync_write_error", 1);
+ bson_finish (b);
+
+ conn = mongo_sync_connect (config.primary_host, config.primary_port,
+ TRUE);
+
+ ok (mongo_sync_cmd_insert (conn, config.ns, b, NULL) == TRUE,
+ "Inserting works with correct namespace when safe mode is off");
+
+ ok (mongo_sync_cmd_insert (conn, INVALID_NS, b, NULL) == TRUE,
+ "Inserting works with invalid namespace when safe mode is off");
+
+ error_msg = mongo_sync_conn_get_last_error (conn);
+ ok (error_msg == NULL,
+ "When safe mode is off, there is no error msg, even if ns is invalid.");
+
+ ok (mongo_sync_conn_set_safe_mode (conn, TRUE) == TRUE,
+ "Setting safe mode works.");
+
+ ok (mongo_sync_cmd_insert (conn, config.ns, b, NULL) == TRUE,
+ "Inserting works with correct namespace when safe mode is on");
+
+ ok (mongo_sync_cmd_insert (conn, INVALID_NS, b, NULL) == FALSE,
+ "Inserting fails with invalid namespace when safe mode is on");
+
+ error_msg = mongo_sync_conn_get_last_error (conn);
+
+ ok (error_msg != NULL,
+ "Inserting failed in safe mode, so we should have an error msg");
+
+ mongo_sync_disconnect (conn);
+}
+
+RUN_NET_TEST (7, func_mongo_sync_write_error);