summaryrefslogtreecommitdiff
path: root/tests/unit/mongo/wire
diff options
context:
space:
mode:
Diffstat (limited to 'tests/unit/mongo/wire')
-rw-r--r--tests/unit/mongo/wire/cmd_custom.c67
-rw-r--r--tests/unit/mongo/wire/cmd_delete.c73
-rw-r--r--tests/unit/mongo/wire/cmd_get_more.c50
-rw-r--r--tests/unit/mongo/wire/cmd_insert.c83
-rw-r--r--tests/unit/mongo/wire/cmd_insert_n.c95
-rw-r--r--tests/unit/mongo/wire/cmd_kill_cursors.c58
-rw-r--r--tests/unit/mongo/wire/cmd_query.c117
-rw-r--r--tests/unit/mongo/wire/cmd_update.c97
-rw-r--r--tests/unit/mongo/wire/packet_get_set_data.c65
-rw-r--r--tests/unit/mongo/wire/packet_get_set_header.c58
-rw-r--r--tests/unit/mongo/wire/packet_get_set_header_raw.c56
-rw-r--r--tests/unit/mongo/wire/packet_new.c20
-rw-r--r--tests/unit/mongo/wire/reply_packet_get_data.c52
-rw-r--r--tests/unit/mongo/wire/reply_packet_get_header.c54
-rw-r--r--tests/unit/mongo/wire/reply_packet_get_nth_document.c68
15 files changed, 1013 insertions, 0 deletions
diff --git a/tests/unit/mongo/wire/cmd_custom.c b/tests/unit/mongo/wire/cmd_custom.c
new file mode 100644
index 0000000..7970aaa
--- /dev/null
+++ b/tests/unit/mongo/wire/cmd_custom.c
@@ -0,0 +1,67 @@
+#include "test.h"
+#include "tap.h"
+#include "mongo-wire.h"
+
+#include <string.h>
+
+void
+test_mongo_wire_cmd_custom (void)
+{
+ bson *cmd;
+ mongo_packet *p;
+
+ mongo_packet_header hdr;
+ const guint8 *data;
+ gint32 data_size;
+
+ bson_cursor *c;
+ gint32 pos;
+
+ cmd = bson_new ();
+ bson_append_int32 (cmd, "getnonce", 1);
+
+ ok (mongo_wire_cmd_custom (1, "test", 0, NULL) == NULL,
+ "mongo_wire_cmd_custom() fails with a NULL command");
+ ok (mongo_wire_cmd_custom (1, "test", 0, cmd) == NULL,
+ "mongo_wire_cmd_custom() fails with an unfinished command");
+ bson_finish (cmd);
+ ok (mongo_wire_cmd_custom (1, NULL, 0, cmd) == NULL,
+ "mongo_wire_cmd_custom() fails with a NULL db");
+
+ ok ((p = mongo_wire_cmd_custom (1, "test", 0, cmd)) != NULL,
+ "mongo_wire_cmd_custom() works");
+ bson_free (cmd);
+
+ /* Verify the header */
+ mongo_wire_packet_get_header (p, &hdr);
+ cmp_ok ((data_size = mongo_wire_packet_get_data (p, &data)), "!=", -1,
+ "Packet data size looks fine");
+ cmp_ok (hdr.length, "==", sizeof (mongo_packet_header) + data_size,
+ "Packet header length is OK");
+ cmp_ok (hdr.id, "==", 1, "Packet request ID is ok");
+ cmp_ok (hdr.resp_to, "==", 0, "Packet reply ID is ok");
+
+ /*
+ * Test the created request
+ */
+
+ /* pos = zero + collection_name + NULL + skip + ret */
+ pos = sizeof (gint32) + strlen ("test.$cmd") + 1 + sizeof (gint32) * 2;
+ ok ((cmd = bson_new_from_data (data + pos,
+ bson_stream_doc_size (data, pos) - 1)) != NULL,
+ "Packet contains a BSON document");
+ bson_finish (cmd);
+
+ ok ((c = bson_find (cmd, "getnonce")) != NULL,
+ "BSON object contains a 'getnonce' key");
+ cmp_ok (bson_cursor_type (c), "==", BSON_TYPE_INT32,
+ "'getnonce' key has the correct type");
+ ok (bson_cursor_next (c) == FALSE,
+ "'getnonce' key is the last in the object");
+
+ bson_cursor_free (c);
+ bson_free (cmd);
+ mongo_wire_packet_free (p);
+}
+
+RUN_TEST (12, mongo_wire_cmd_custom);
diff --git a/tests/unit/mongo/wire/cmd_delete.c b/tests/unit/mongo/wire/cmd_delete.c
new file mode 100644
index 0000000..9399046
--- /dev/null
+++ b/tests/unit/mongo/wire/cmd_delete.c
@@ -0,0 +1,73 @@
+#include "test.h"
+#include "tap.h"
+#include "mongo-wire.h"
+
+#include <string.h>
+
+void
+test_mongo_wire_cmd_delete (void)
+{
+ mongo_packet *p;
+ bson *s, *tmp;
+
+ mongo_packet_header hdr;
+ const guint8 *data;
+ gint32 data_size;
+
+ gint32 pos;
+ bson_cursor *c;
+
+ s = test_bson_generate_full ();
+ tmp = bson_new ();
+
+ ok (mongo_wire_cmd_delete (1, NULL, 0, s) == NULL,
+ "mongo_wire_cmd_delete() fails with a NULL namespace");
+ ok (mongo_wire_cmd_delete (1, "test.ns", 0, NULL) == NULL,
+ "mongo_wire_cmd_delete() fails with a NULL selector");
+ ok (mongo_wire_cmd_delete (1, "test.ns", 0, tmp) == NULL,
+ "mongo_wire_cmd_delete() fails with an unfinished selector");
+ bson_free (tmp);
+
+ ok ((p = mongo_wire_cmd_delete (1, "test.ns", 0, s)) != NULL,
+ "mongo_wire_cmd_delete() works");
+ bson_free (s);
+
+ /* Test basic header data */
+ mongo_wire_packet_get_header (p, &hdr);
+ cmp_ok ((data_size = mongo_wire_packet_get_data (p, &data)), "!=", -1,
+ "Packet data size appears fine");
+
+ cmp_ok (hdr.length, "==", sizeof (mongo_packet_header) + data_size,
+ "Packet header length is correct");
+ cmp_ok (hdr.id, "==", 1, "Header ID is ok");
+ cmp_ok (hdr.resp_to, "==", 0, "Response ID is ok");
+
+ /*
+ * Test the constructed request
+ */
+
+ /* pos = zero + ns + NULL + flags */
+ pos = sizeof (gint32) + strlen ("test.ns") + 1 + sizeof (gint32);
+
+ ok ((s = bson_new_from_data (data + pos,
+ bson_stream_doc_size (data, pos) - 1)) != NULL,
+ "Packet contains a valid BSON update document");
+ bson_finish (s);
+
+ ok ((c = bson_find (s, "int32")) != NULL,
+ "BSON contains 'int32'");
+ cmp_ok (bson_cursor_type (c), "==", BSON_TYPE_INT32,
+ "int32 has correct type");
+ bson_cursor_next (c);
+ cmp_ok (bson_cursor_type (c), "==", BSON_TYPE_INT64,
+ "next element has correct type too");
+ ok (bson_cursor_next (c) == FALSE,
+ "No more data after the update BSON object");
+
+ bson_cursor_free (c);
+ bson_free (s);
+
+ mongo_wire_packet_free (p);
+}
+
+RUN_TEST (13, mongo_wire_cmd_delete);
diff --git a/tests/unit/mongo/wire/cmd_get_more.c b/tests/unit/mongo/wire/cmd_get_more.c
new file mode 100644
index 0000000..5f56821
--- /dev/null
+++ b/tests/unit/mongo/wire/cmd_get_more.c
@@ -0,0 +1,50 @@
+#include "test.h"
+#include "tap.h"
+#include "mongo-wire.h"
+
+#include <string.h>
+
+void
+test_mongo_wire_cmd_get_more (void)
+{
+ mongo_packet *p;
+
+ mongo_packet_header hdr;
+ const guint8 *data;
+ gint32 data_size;
+
+ gint32 pos;
+ gint64 cid = 9876543210;
+
+ ok (mongo_wire_cmd_get_more (1, NULL, 1, cid) == NULL,
+ "mongo_wire_cmd_get_more() fails with a NULL namespace");
+ ok ((p = mongo_wire_cmd_get_more (1, "test.ns", 1, cid)) != NULL,
+ "mongo_wire_cmd_get_more() works");
+
+ /* Test basic header data */
+ mongo_wire_packet_get_header (p, &hdr);
+ cmp_ok ((data_size = mongo_wire_packet_get_data (p, &data)), "!=", -1,
+ "Packet data size appears fine");
+
+ cmp_ok (hdr.length, "==", sizeof (mongo_packet_header) + data_size,
+ "Packet header length is correct");
+ cmp_ok (hdr.id, "==", 1, "Header ID is ok");
+ cmp_ok (hdr.resp_to, "==", 0, "Response ID is ok");
+
+ /*
+ * Test the request itself.
+ */
+
+ /* pos = zero + ns + NULL + ret */
+ pos = sizeof (gint32) + strlen ("test.ns") + 1 + sizeof (gint32);
+ cid = 0;
+ memcpy (&cid, data + pos, sizeof (cid));
+ cid = GINT64_FROM_LE (cid);
+
+ ok (cid == 9876543210,
+ "Included CID is correct");
+
+ mongo_wire_packet_free (p);
+}
+
+RUN_TEST (7, mongo_wire_cmd_get_more);
diff --git a/tests/unit/mongo/wire/cmd_insert.c b/tests/unit/mongo/wire/cmd_insert.c
new file mode 100644
index 0000000..3e84847
--- /dev/null
+++ b/tests/unit/mongo/wire/cmd_insert.c
@@ -0,0 +1,83 @@
+#include "test.h"
+#include "tap.h"
+#include "mongo-wire.h"
+
+#include <string.h>
+
+void
+test_mongo_wire_cmd_insert (void)
+{
+ bson *ins, *tmp;
+ mongo_packet *p;
+
+ mongo_packet_header hdr;
+ const guint8 *data;
+ gint32 data_size;
+
+ bson_cursor *c;
+ gint32 pos;
+
+ ins = test_bson_generate_full ();
+ tmp = bson_new ();
+
+ ok (mongo_wire_cmd_insert (1, NULL, ins, NULL) == NULL,
+ "mongo_wire_cmd_insert() fails with a NULL namespace");
+ ok (mongo_wire_cmd_insert (1, "test.ns", NULL) == NULL,
+ "mongo_wire_cmd_insert() fails with no documents");
+ ok (mongo_wire_cmd_insert (1, "test.ns", tmp, NULL) == NULL,
+ "mongo_wire_cmd_insert() with an unfinished document");
+ bson_finish (tmp);
+ ok ((p = mongo_wire_cmd_insert (1, "test.ns", ins, tmp, NULL)) != NULL,
+ "mongo_wire_cmd_insert() works");
+ bson_free (ins);
+ bson_free (tmp);
+
+ /* Test basic header data */
+ mongo_wire_packet_get_header (p, &hdr);
+ cmp_ok ((data_size = mongo_wire_packet_get_data (p, &data)), "!=", -1,
+ "Packet data size appears fine");
+
+ cmp_ok (hdr.length, "==", sizeof (mongo_packet_header) + data_size,
+ "Packet header length is correct");
+ cmp_ok (hdr.id, "==", 1, "Header ID is ok");
+ cmp_ok (hdr.resp_to, "==", 0, "Response ID is ok");
+
+ /*
+ * Test the first document
+ */
+
+ /* pos = zero + collection_name + NULL */
+ pos = sizeof (gint32) + strlen ("test.ns") + 1;
+ ok ((ins = bson_new_from_data (data + pos,
+ bson_stream_doc_size (data, pos) - 1)) != NULL,
+ "First document is included");
+ bson_finish (ins);
+
+ ok ((c = bson_find (ins, "int32")) != NULL,
+ "BSON contains 'int32'");
+ cmp_ok (bson_cursor_type (c), "==", BSON_TYPE_INT32,
+ "int32 has correct type");
+ bson_cursor_next (c);
+ cmp_ok (bson_cursor_type (c), "==", BSON_TYPE_INT64,
+ "next element has correct type too");
+ ok (bson_cursor_next (c) == FALSE,
+ "No more data after the update BSON object");
+ bson_cursor_free (c);
+
+ /*
+ * Test the second document
+ */
+ pos += bson_size (ins);
+ ok ((tmp = bson_new_from_data (data + pos,
+ bson_stream_doc_size (data, pos) - 1)) != NULL,
+ "Second document is included");
+ bson_finish (tmp);
+ cmp_ok (bson_size (tmp), "==", 5,
+ "Second document is empty");
+
+ bson_free (ins);
+ bson_free (tmp);
+ mongo_wire_packet_free (p);
+}
+
+RUN_TEST (15, mongo_wire_cmd_insert);
diff --git a/tests/unit/mongo/wire/cmd_insert_n.c b/tests/unit/mongo/wire/cmd_insert_n.c
new file mode 100644
index 0000000..1c00193
--- /dev/null
+++ b/tests/unit/mongo/wire/cmd_insert_n.c
@@ -0,0 +1,95 @@
+#include "test.h"
+#include "tap.h"
+#include "mongo-wire.h"
+
+#include <string.h>
+
+void
+test_mongo_wire_cmd_insert_n (void)
+{
+ bson *ins, *tmp;
+ const bson *docs[10];
+ mongo_packet *p;
+
+ mongo_packet_header hdr;
+ const guint8 *data;
+ gint32 data_size;
+
+ bson_cursor *c;
+ gint32 pos;
+
+ ins = test_bson_generate_full ();
+ tmp = bson_new ();
+
+ docs[0] = ins;
+ docs[1] = tmp;
+ docs[2] = ins;
+ docs[3] = ins;
+ docs[4] = NULL;
+ docs[5] = ins;
+
+ ok (mongo_wire_cmd_insert_n (1, NULL, 1, docs) == NULL,
+ "mongo_wire_cmd_insert_n() fails with a NULL namespace");
+ ok (mongo_wire_cmd_insert_n (1, "test.ns", 1, NULL) == NULL,
+ "mongo_wire_cmd_insert_n() fails with no documents");
+ ok (mongo_wire_cmd_insert_n (1, "test.ns", 0, docs) == NULL,
+ "mongo_wire_cmd_insert_n() fails with no documents");
+ ok (mongo_wire_cmd_insert_n (1, "test.ns", 2, docs) == NULL,
+ "mongo_wire_cmd_insert_n() fails with an unfinished document");
+ bson_finish (tmp);
+ ok (mongo_wire_cmd_insert_n (1, "test.ns", 5, docs) == NULL,
+ "mongo_wire_cmd_insert_n() fails with a NULL document in the array");
+ ok ((p = mongo_wire_cmd_insert_n (1, "test.ns", 3, docs)) != NULL,
+ "mongo_wire_cmd_insert() works");
+ bson_free (ins);
+ bson_free (tmp);
+
+ /* Test basic header data */
+ mongo_wire_packet_get_header (p, &hdr);
+ cmp_ok ((data_size = mongo_wire_packet_get_data (p, &data)), "!=", -1,
+ "Packet data size appears fine");
+
+ cmp_ok (hdr.length, "==", sizeof (mongo_packet_header) + data_size,
+ "Packet header length is correct");
+ cmp_ok (hdr.id, "==", 1, "Header ID is ok");
+ cmp_ok (hdr.resp_to, "==", 0, "Response ID is ok");
+
+ /*
+ * Test the first document
+ */
+
+ /* pos = zero + collection_name + NULL */
+ pos = sizeof (gint32) + strlen ("test.ns") + 1;
+ ok ((ins = bson_new_from_data (data + pos,
+ bson_stream_doc_size (data, pos) - 1)) != NULL,
+ "First document is included");
+ bson_finish (ins);
+
+ ok ((c = bson_find (ins, "int32")) != NULL,
+ "BSON contains 'int32'");
+ cmp_ok (bson_cursor_type (c), "==", BSON_TYPE_INT32,
+ "int32 has correct type");
+ bson_cursor_next (c);
+ cmp_ok (bson_cursor_type (c), "==", BSON_TYPE_INT64,
+ "next element has correct type too");
+ ok (bson_cursor_next (c) == FALSE,
+ "No more data after the update BSON object");
+ bson_cursor_free (c);
+
+ /*
+ * Test the second document
+ */
+ pos += bson_size (ins);
+ ok ((tmp = bson_new_from_data (data + pos,
+ bson_stream_doc_size (data, pos) - 1)) != NULL,
+ "Second document is included");
+ bson_finish (tmp);
+ cmp_ok (bson_size (tmp), "==", 5,
+ "Second document is empty");
+
+ bson_free (ins);
+ bson_free (tmp);
+ mongo_wire_packet_free (p);
+}
+
+RUN_TEST (17, mongo_wire_cmd_insert_n);
diff --git a/tests/unit/mongo/wire/cmd_kill_cursors.c b/tests/unit/mongo/wire/cmd_kill_cursors.c
new file mode 100644
index 0000000..a8a8fd9
--- /dev/null
+++ b/tests/unit/mongo/wire/cmd_kill_cursors.c
@@ -0,0 +1,58 @@
+#include "test.h"
+#include "tap.h"
+#include "mongo-wire.h"
+
+#include <string.h>
+
+void
+test_mongo_wire_cmd_kill_cursors (void)
+{
+ mongo_packet *p;
+
+ mongo_packet_header hdr;
+ const guint8 *data;
+ gint32 data_size;
+
+ gint32 pos, n = 0;
+ gint64 c1 = 9876543210, c2 = 1234567890;
+
+ ok (mongo_wire_cmd_kill_cursors (1, 0) == NULL,
+ "mongo_wire_cmd_kill_cursors() should fail with zero cursors");
+ ok (mongo_wire_cmd_kill_cursors (1, -1) == NULL,
+ "mongo_wire_cmd_kill_cursors() should fail with negative amount of "
+ "cursors");
+ ok ((p = mongo_wire_cmd_kill_cursors (1, 2, c1, c2)) != NULL,
+ "mongo_wire_cmd_kill_cursors() works");
+
+ /* Verify the header */
+ mongo_wire_packet_get_header (p, &hdr);
+ cmp_ok ((data_size = mongo_wire_packet_get_data (p, &data)), "!=", -1,
+ "Packet data size looks fine");
+ cmp_ok (hdr.length, "==", sizeof (mongo_packet_header) + data_size,
+ "Packet header length is OK");
+ cmp_ok (hdr.id, "==", 1, "Packet request ID is ok");
+ cmp_ok (hdr.resp_to, "==", 0, "Packet reply ID is ok");
+
+ /*
+ * Test the request contents
+ */
+ c1 = c2 = 0;
+ /* pos = zero + n */
+ pos = sizeof (gint32) + sizeof (n);
+
+ memcpy (&n, data + sizeof (gint32), sizeof (gint32));
+ memcpy (&c1, data + pos, sizeof (c1));
+ memcpy (&c2, data + pos + sizeof (c1), sizeof (c2));
+
+ n = GINT32_FROM_LE (n);
+ c1 = GINT64_FROM_LE (c1);
+ c2 = GINT64_FROM_LE (c2);
+
+ ok (n == 2, "Number of cursors are OK");
+ ok (c1 == 9876543210, "First cursor is OK");
+ ok (c2 == 1234567890, "Second cursor is OK");
+
+ mongo_wire_packet_free (p);
+}
+
+RUN_TEST (10, mongo_wire_cmd_kill_cursors);
diff --git a/tests/unit/mongo/wire/cmd_query.c b/tests/unit/mongo/wire/cmd_query.c
new file mode 100644
index 0000000..58eb960
--- /dev/null
+++ b/tests/unit/mongo/wire/cmd_query.c
@@ -0,0 +1,117 @@
+#include "test.h"
+#include "tap.h"
+#include "mongo-wire.h"
+
+#include <string.h>
+
+void
+test_mongo_wire_cmd_query (void)
+{
+ bson *q, *s, *tmp;
+ mongo_packet *p;
+
+ mongo_packet_header hdr;
+ const guint8 *data;
+ gint32 data_size;
+
+ bson_cursor *c;
+ gint32 pos;
+
+ q = test_bson_generate_full ();
+ s = bson_new ();
+ bson_append_boolean (s, "_id", TRUE);
+ bson_append_boolean (s, "double", TRUE);
+ bson_finish (s);
+
+ tmp = bson_new ();
+
+ ok (mongo_wire_cmd_query (1, NULL, 0, 0, 0, q, s) == NULL,
+ "mongo_wire_cmd_query() fails whith a NULL namespace");
+ ok (mongo_wire_cmd_query (1, "test.ns", 0, 0, 0, NULL, s) == NULL,
+ "mongo_wire_cmd_query() fails with a NULL query");
+ ok (mongo_wire_cmd_query (1, "test.ns", 0, 0, 0, tmp, s) == NULL,
+ "mongo_wire_cmd_query() fails with an unfinished query");
+ ok (mongo_wire_cmd_query (1, "test.ns", 0, 0, 0, q, tmp) == NULL,
+ "mongo_wire_cmd_query() fails with an unfinished selector");
+ bson_free (tmp);
+
+ ok ((p = mongo_wire_cmd_query (1, "test.ns", 0, 0, 10, q, NULL)) != NULL,
+ "mongo_wire_cmd_query() works with a NULL selector");
+
+ mongo_wire_packet_get_header (p, &hdr);
+ cmp_ok ((data_size = mongo_wire_packet_get_data (p, &data)), "!=", -1,
+ "Packet data size looks fine");
+ cmp_ok (hdr.length, "==", sizeof (mongo_packet_header) + data_size,
+ "Packet header length is OK");
+ cmp_ok (hdr.id, "==", 1, "Packet request ID is ok");
+ cmp_ok (hdr.resp_to, "==", 0, "Packet reply ID is ok");
+
+ /* pos = zero + collection_name + NULL + skip + ret */
+ pos = sizeof (gint32) + strlen ("test.ns") + 1 + sizeof (gint32) * 2;
+ ok ((tmp = bson_new_from_data (data + pos,
+ bson_stream_doc_size (data, pos) - 1)) != NULL,
+ "Packet contains a valid BSON query document");
+ bson_finish (tmp);
+
+ ok ((c = bson_find (tmp, "int32")) != NULL,
+ "BSON contains 'int32'");
+ cmp_ok (bson_cursor_type (c), "==", BSON_TYPE_INT32,
+ "int32 has correct type");
+ bson_cursor_next (c);
+ cmp_ok (bson_cursor_type (c), "==", BSON_TYPE_INT64,
+ "next element has correct type too");
+ ok (bson_cursor_next (c) == FALSE,
+ "No more data after the update BSON object");
+ bson_cursor_free (c);
+
+ cmp_ok (hdr.length, "==", sizeof (mongo_packet_header) + pos +
+ bson_size (q),
+ "Packet header lenght is correct");
+ bson_free (tmp);
+ mongo_wire_packet_free (p);
+
+ /*
+ * Test again with a selector document
+ */
+
+ ok ((p = mongo_wire_cmd_query (1, "test.ns", 0, 0, 10, q, s)) != NULL,
+ "mongo_wire_cmd_query() works with a NULL selector");
+
+ mongo_wire_packet_get_header (p, &hdr);
+ cmp_ok ((data_size = mongo_wire_packet_get_data (p, &data)), "!=", -1,
+ "Packet data size looks fine");
+ cmp_ok (hdr.length, "==", sizeof (mongo_packet_header) + data_size,
+ "Packet header length is OK");
+ cmp_ok (hdr.id, "==", 1, "Packet request ID is ok");
+ cmp_ok (hdr.resp_to, "==", 0, "Packet reply ID is ok");
+
+ /* pos = zero + collection_name + NULL + skip + ret */
+ pos = sizeof (gint32) + strlen ("test.ns") + 1 + sizeof (gint32) * 2;
+ ok ((tmp = bson_new_from_data (data + pos,
+ bson_stream_doc_size (data, pos) - 1)) != NULL,
+ "Packet contains a valid BSON query document");
+ bson_finish (tmp);
+ pos += bson_size (tmp);
+ bson_free (tmp);
+ bson_free (q);
+ bson_free (s);
+
+ ok ((s = bson_new_from_data (data + pos,
+ bson_stream_doc_size (data, pos) - 1)) != NULL,
+ "Packet contains a valid BSON selector document");
+ bson_finish (s);
+
+ ok ((c = bson_find (s, "_id")) != NULL,
+ "BSON contains '_id'");
+ cmp_ok (bson_cursor_type (c), "==", BSON_TYPE_BOOLEAN,
+ "_id has correct type");
+ bson_cursor_next (c);
+ cmp_ok (bson_cursor_type (c), "==", BSON_TYPE_BOOLEAN,
+ "next element has correct type too");
+
+ bson_cursor_free (c);
+ bson_free (s);
+ mongo_wire_packet_free (p);
+}
+
+RUN_TEST (25, mongo_wire_cmd_query);
diff --git a/tests/unit/mongo/wire/cmd_update.c b/tests/unit/mongo/wire/cmd_update.c
new file mode 100644
index 0000000..95a2a50
--- /dev/null
+++ b/tests/unit/mongo/wire/cmd_update.c
@@ -0,0 +1,97 @@
+#include "test.h"
+#include "tap.h"
+#include "mongo-wire.h"
+
+#include <string.h>
+
+void
+test_mongo_wire_cmd_update (void)
+{
+ bson *sel, *upd, *tmp;
+ mongo_packet *p;
+
+ mongo_packet_header hdr;
+ const guint8 *data;
+ gint32 data_size;
+
+ bson_cursor *c;
+ gint32 pos;
+
+ sel = bson_new ();
+ bson_append_null (sel, "_id");
+ bson_finish (sel);
+
+ upd = test_bson_generate_full ();
+
+ ok (mongo_wire_cmd_update (1, NULL, 0, sel, upd) == NULL,
+ "mongo_wire_cmd_update() with a NULL namespace should fail");
+ ok (mongo_wire_cmd_update (1, "test.ns", 0, NULL, upd) == NULL,
+ "mongo_wire_cmd_update() with a NULL selector should fail");
+ ok (mongo_wire_cmd_update (1, "test.ns", 0, sel, NULL) == NULL,
+ "mongo_wire_cmd_update() with a NULL update should fail");
+
+ tmp = bson_new ();
+ ok (mongo_wire_cmd_update (1, "test.ns", 0, tmp, upd) == NULL,
+ "mongo_wire_cmd_update() fails with an unfinished selector");
+ ok (mongo_wire_cmd_update (1, "test.ns", 0, sel, tmp) == NULL,
+ "mongo_wire_cmd_update() fails with an unfinished update");
+ bson_free (tmp);
+
+ ok ((p = mongo_wire_cmd_update (1, "test.ns", 0, sel, upd)) != NULL,
+ "mongo_wire_cmd_update() works");
+
+ bson_free (sel);
+
+ mongo_wire_packet_get_header (p, &hdr);
+ cmp_ok ((data_size = mongo_wire_packet_get_data (p, &data)), "!=", -1,
+ "Packet data size looks fine");
+ cmp_ok (hdr.length, "==", sizeof (mongo_packet_header) + data_size,
+ "Packet header length is OK");
+ cmp_ok (hdr.id, "==", 1, "Packet request ID is ok");
+ cmp_ok (hdr.resp_to, "==", 0, "Packet reply ID is ok");
+
+ /*
+ * Verify the selector object.
+ */
+
+ /* pos = zero + collection_name + NULL + flags */
+ pos = sizeof (gint32) + strlen ("test.ns") + 1 + sizeof (gint32);
+ ok ((sel = bson_new_from_data (data + pos, (gint32)data[pos] - 1)) != NULL,
+ "Packet contains a valid BSON selector document");
+ bson_finish (sel);
+
+ ok ((c = bson_find (sel, "_id")) != NULL,
+ "BSON contains an _id");
+ cmp_ok (bson_cursor_type (c), "==", BSON_TYPE_NULL,
+ "_id has correct type");
+ bson_cursor_free (c);
+ bson_free (sel);
+
+ /*
+ * Verify the update object
+ */
+ pos += (gint32)data[pos];
+ ok ((tmp = bson_new_from_data (data + pos,
+ bson_stream_doc_size (data, pos) - 1)) != NULL,
+ "Packet contains a valid BSON update document");
+ bson_finish (tmp);
+ cmp_ok (bson_size (upd), "==", bson_size (tmp),
+ "Packet's update document has the correct size");
+
+ ok ((c = bson_find (tmp, "int32")) != NULL,
+ "BSON contains 'int32'");
+ cmp_ok (bson_cursor_type (c), "==", BSON_TYPE_INT32,
+ "int32 has correct type");
+ bson_cursor_next (c);
+ cmp_ok (bson_cursor_type (c), "==", BSON_TYPE_INT64,
+ "next element has correct type too");
+ ok (bson_cursor_next (c) == FALSE,
+ "No more data after the update BSON object");
+
+ bson_cursor_free (c);
+ bson_free (tmp);
+ bson_free (upd);
+ mongo_wire_packet_free (p);
+}
+
+RUN_TEST (19, mongo_wire_cmd_update);
diff --git a/tests/unit/mongo/wire/packet_get_set_data.c b/tests/unit/mongo/wire/packet_get_set_data.c
new file mode 100644
index 0000000..2f06b8f
--- /dev/null
+++ b/tests/unit/mongo/wire/packet_get_set_data.c
@@ -0,0 +1,65 @@
+#include "tap.h"
+#include "test.h"
+#include "mongo-wire.h"
+
+#include <string.h>
+
+void
+test_mongo_wire_packet_get_set_data (void)
+{
+ mongo_packet *p;
+ mongo_packet_header h;
+ guint8 data[32768];
+ const guint8 *idata;
+
+ p = mongo_wire_packet_new ();
+ memset (data, 'x', sizeof (data));
+
+ ok (mongo_wire_packet_get_data (NULL, &idata) == -1,
+ "mongo_wire_packet_get_data() with a NULL packet should fail");
+ ok (mongo_wire_packet_get_data (p, NULL) == -1,
+ "mongo_wire_packet_get_data() with NULL destination should fail");
+ ok (mongo_wire_packet_get_data (p, &idata) == -1,
+ "mongo_wire_packet_get_data() with an empty packet should fail");
+ ok (mongo_wire_packet_set_data (NULL, (const guint8 *)&data,
+ sizeof (data)) == FALSE,
+ "mongo_wire_packet_set_data() with a NULL packet should fail");
+ ok (mongo_wire_packet_set_data (p, NULL, sizeof (data)) == FALSE,
+ "mongo_wire_packet_set_data() with NULL data should fail");
+ ok (mongo_wire_packet_set_data (p, (const guint8 *)&data, 0) == FALSE,
+ "mongo_wire_packet_set_data() with zero size should fail");
+ ok (mongo_wire_packet_set_data (p, (const guint8 *)&data, -1) == FALSE,
+ "mongo_wire_packet_set_data() with negative size should fail");
+
+ ok (mongo_wire_packet_set_data (p, (const guint8 *)&data,
+ sizeof (data)),
+ "mongo_wire_packet_set_data() works");
+ cmp_ok (mongo_wire_packet_get_data (p, &idata), "==", sizeof (data),
+ "mongo_wire_packet_get_data() works");
+
+ mongo_wire_packet_get_header (p, &h);
+
+ cmp_ok (h.length, "==", sizeof (data) + sizeof (mongo_packet_header),
+ "Packet length is updated properly");
+ ok (memcmp (data, idata, sizeof (data)) == 0,
+ "Setting & retrieving data works");
+
+ memset (data, 'a', sizeof (data));
+
+ ok (mongo_wire_packet_set_data (p, (const guint8 *)&data,
+ sizeof (data) / 2),
+ "Re-setting the data works");
+ cmp_ok (mongo_wire_packet_get_data (p, &idata), "==", sizeof (data) / 2,
+ "Retrieving the data works still");
+
+ mongo_wire_packet_get_header (p, &h);
+
+ cmp_ok (h.length, "==", sizeof (data) / 2 + sizeof (mongo_packet_header),
+ "Packet length is updated properly");
+ ok (memcmp (data, idata, sizeof (data) / 2) == 0,
+ "Setting & retrieving data works");
+
+ mongo_wire_packet_free (p);
+}
+
+RUN_TEST (15, mongo_wire_packet_get_set_data);
diff --git a/tests/unit/mongo/wire/packet_get_set_header.c b/tests/unit/mongo/wire/packet_get_set_header.c
new file mode 100644
index 0000000..38e0ea7
--- /dev/null
+++ b/tests/unit/mongo/wire/packet_get_set_header.c
@@ -0,0 +1,58 @@
+#include "tap.h"
+#include "test.h"
+#include "mongo-wire.h"
+
+#include <string.h>
+
+void
+test_mongo_wire_packet_get_set_header (void)
+{
+ mongo_packet *p;
+ mongo_packet_header ph1, ph2;
+
+ p = mongo_wire_packet_new ();
+
+ ok (mongo_wire_packet_get_header (NULL, &ph2) == FALSE,
+ "mongo_wire_packet_get_header() should fail with a NULL packet");
+ ok (mongo_wire_packet_get_header (p, NULL) == FALSE,
+ "mongo_wire_packet_get_header() should fail with a NULL header");
+ ok (mongo_wire_packet_set_header (NULL, &ph1) == FALSE,
+ "mongo_wire_packet_set_header() should fail with a NULL packet");
+ ok (mongo_wire_packet_set_header (p, NULL) == FALSE,
+ "mongo_wire_packet_set_header() should fail with a NULL header");
+
+ ok (mongo_wire_packet_get_header (p, &ph2),
+ "mongo_wire_packet_get_header() works on a fresh packet");
+ cmp_ok (ph2.length, "==", sizeof (mongo_packet_header),
+ "Initial packet length is the length of the header");
+
+ ph1.length = sizeof (mongo_packet_header);
+ ph1.id = 1;
+ ph1.resp_to = 0;
+ ph1.opcode = 1000;
+
+ memset (&ph2, 0, sizeof (mongo_packet_header));
+
+ ok (mongo_wire_packet_set_header (p, &ph1),
+ "mongo_wire_packet_set_header() works");
+ ok (mongo_wire_packet_get_header (p, &ph2),
+ "mongo_wire_packet_get_header() works");
+
+ cmp_ok (ph1.length, "==", ph2.length,
+ "Packet lengths match");
+ cmp_ok (ph1.id, "==", ph2.id,
+ "Sequence IDs match");
+ cmp_ok (ph1.resp_to, "==", ph2.resp_to,
+ "Response IDs match");
+ cmp_ok (ph1.opcode, "==", ph2.opcode,
+ "OPCodes match");
+
+ ph1.length = GINT32_TO_LE (1);
+ ok (mongo_wire_packet_set_header (p, &ph1) == FALSE,
+ "Setting a packet with length shorter than the header "
+ "returns an error");
+
+ mongo_wire_packet_free (p);
+}
+
+RUN_TEST (13, mongo_wire_packet_get_set_header);
diff --git a/tests/unit/mongo/wire/packet_get_set_header_raw.c b/tests/unit/mongo/wire/packet_get_set_header_raw.c
new file mode 100644
index 0000000..d97a8b3
--- /dev/null
+++ b/tests/unit/mongo/wire/packet_get_set_header_raw.c
@@ -0,0 +1,56 @@
+#include "tap.h"
+#include "test.h"
+#include "mongo-wire.h"
+
+#include "libmongo-private.h"
+
+#include <string.h>
+
+void
+test_mongo_wire_packet_get_set_header_raw (void)
+{
+ mongo_packet *p;
+ mongo_packet_header ph1, ph2;
+
+ p = mongo_wire_packet_new ();
+
+ ok (mongo_wire_packet_get_header_raw (NULL, &ph2) == FALSE,
+ "mongo_wire_packet_get_header_raw() should fail with a NULL packet");
+ ok (mongo_wire_packet_get_header_raw (p, NULL) == FALSE,
+ "mongo_wire_packet_get_header_raw() should fail with a NULL header");
+ ok (mongo_wire_packet_set_header_raw (NULL, &ph1) == FALSE,
+ "mongo_wire_packet_set_header_raw() should fail with a NULL packet");
+ ok (mongo_wire_packet_set_header_raw (p, NULL) == FALSE,
+ "mongo_wire_packet_set_header_raw() should fail with a NULL header");
+
+ ok (mongo_wire_packet_get_header_raw (p, &ph2),
+ "mongo_wire_packet_get_header_raw() works on a fresh packet");
+ /* Need to convert from LE, because _new() sets the length to LE. */
+ cmp_ok (GINT32_FROM_LE (ph2.length), "==", sizeof (mongo_packet_header),
+ "Initial packet length is the length of the header");
+
+ ph1.length = sizeof (mongo_packet_header);
+ ph1.id = 1;
+ ph1.resp_to = 0;
+ ph1.opcode = 1000;
+
+ memset (&ph2, 0, sizeof (mongo_packet_header));
+
+ ok (mongo_wire_packet_set_header_raw (p, &ph1),
+ "mongo_wire_packet_set_header_raw() works");
+ ok (mongo_wire_packet_get_header_raw (p, &ph2),
+ "mongo_wire_packet_get_header_raw() works");
+
+ cmp_ok (ph1.length, "==", ph2.length,
+ "Packet lengths match");
+ cmp_ok (ph1.id, "==", ph2.id,
+ "Sequence IDs match");
+ cmp_ok (ph1.resp_to, "==", ph2.resp_to,
+ "Response IDs match");
+ cmp_ok (ph1.opcode, "==", ph2.opcode,
+ "OPCodes match");
+
+ mongo_wire_packet_free (p);
+}
+
+RUN_TEST (12, mongo_wire_packet_get_set_header_raw);
diff --git a/tests/unit/mongo/wire/packet_new.c b/tests/unit/mongo/wire/packet_new.c
new file mode 100644
index 0000000..4940542
--- /dev/null
+++ b/tests/unit/mongo/wire/packet_new.c
@@ -0,0 +1,20 @@
+#include "tap.h"
+#include "test.h"
+#include "mongo-wire.h"
+
+#include <string.h>
+
+void
+test_mongo_wire_packet_new (void)
+{
+ mongo_packet *p;
+
+ ok ((p = mongo_wire_packet_new ()) != NULL,
+ "mongo_wire_packet_new() works");
+ mongo_wire_packet_free (NULL);
+ pass ("mongo_wire_packet_free(NULL) works");
+ mongo_wire_packet_free (p);
+ pass ("mongo_wire_packet_free() works");
+}
+
+RUN_TEST (3, mongo_wire_packet_new);
diff --git a/tests/unit/mongo/wire/reply_packet_get_data.c b/tests/unit/mongo/wire/reply_packet_get_data.c
new file mode 100644
index 0000000..e22f142
--- /dev/null
+++ b/tests/unit/mongo/wire/reply_packet_get_data.c
@@ -0,0 +1,52 @@
+#include "test.h"
+#include "tap.h"
+#include "bson.h"
+#include "mongo-wire.h"
+
+#include <string.h>
+
+void
+test_mongo_wire_reply_packet_get_data (void)
+{
+ mongo_packet *p;
+ mongo_packet_header h;
+ const guint8 *data;
+ bson *b;
+
+ p = mongo_wire_packet_new ();
+ memset (&h, 0, sizeof (mongo_packet_header));
+ h.opcode = 0;
+ h.length = sizeof (mongo_packet_header);
+ mongo_wire_packet_set_header (p, &h);
+
+ ok (mongo_wire_reply_packet_get_data (NULL, &data) == FALSE,
+ "mongo_wire_reply_packet_get_data() fails with a NULL packet");
+ ok (mongo_wire_reply_packet_get_data (p, NULL) == FALSE,
+ "mongo_wire_reply_packet_get_data() fails with a NULL destination");
+ ok (mongo_wire_reply_packet_get_data (p, &data) == FALSE,
+ "mongo_wire_reply_packet_get_data() fails with a non-reply packet");
+
+ h.opcode = 1;
+ mongo_wire_packet_set_header (p, &h);
+
+ ok (mongo_wire_reply_packet_get_data (p, &data) == FALSE,
+ "mongo_wire_reply_packet_get_data() fails if the packet has "
+ "no data");
+
+ mongo_wire_packet_free (p);
+
+ p = test_mongo_wire_generate_reply (TRUE, 2, TRUE);
+
+ ok (mongo_wire_reply_packet_get_data (p, &data),
+ "mongo_wire_reply_packet_get_data() works");
+
+ b = test_bson_generate_full ();
+
+ ok (memcmp (data, bson_data (b), bson_size (b)) == 0,
+ "The returned data is correct");
+
+ bson_free (b);
+ mongo_wire_packet_free (p);
+}
+
+RUN_TEST (6, mongo_wire_reply_packet_get_data);
diff --git a/tests/unit/mongo/wire/reply_packet_get_header.c b/tests/unit/mongo/wire/reply_packet_get_header.c
new file mode 100644
index 0000000..36b548c
--- /dev/null
+++ b/tests/unit/mongo/wire/reply_packet_get_header.c
@@ -0,0 +1,54 @@
+#include "test.h"
+#include "tap.h"
+#include "mongo-wire.h"
+
+#include <string.h>
+
+void
+test_mongo_wire_reply_packet_get_header (void)
+{
+ mongo_packet *p;
+ mongo_packet_header h;
+ mongo_reply_packet_header rh;
+
+ p = mongo_wire_packet_new ();
+ memset (&h, 0, sizeof (mongo_packet_header));
+ h.opcode = 1;
+ h.length = sizeof (mongo_packet_header);
+
+ mongo_wire_packet_set_header (p, &h);
+
+ ok (mongo_wire_reply_packet_get_header (NULL, &rh) == FALSE,
+ "mongo_wire_reply_packet_get_header() fails with a NULL packet");
+ ok (mongo_wire_reply_packet_get_header (p, NULL) == FALSE,
+ "mongo_wire_reply_packet_get_header() fails with a NULL header");
+
+ ok (mongo_wire_reply_packet_get_header (p, &rh) == FALSE,
+ "mongo_wire_reply_packet_get_header() fails if the packet has "
+ "no reply header");
+
+ h.opcode = 2;
+ mongo_wire_packet_set_header (p, &h);
+ ok (mongo_wire_reply_packet_get_header (p, &rh) == FALSE,
+ "mongo_wire_reply_packet_get_header() fails if the packet is "
+ "not a reply packet");
+
+ mongo_wire_packet_free (p);
+
+ p = test_mongo_wire_generate_reply (TRUE, 0, FALSE);
+
+ ok (mongo_wire_reply_packet_get_header (p, &rh),
+ "mongo_wire_reply_packet_get_header() works");
+ cmp_ok (rh.flags, "==", 0,
+ "Reply flags are correct");
+ ok (rh.cursor_id == (gint64)12345,
+ "Cursor ID is correct");
+ cmp_ok (rh.start, "==", 0,
+ "Reply start document is OK");
+ cmp_ok (rh.returned, "==", 0,
+ "Number of documents returned is OK");
+
+ mongo_wire_packet_free (p);
+}
+
+RUN_TEST (9, mongo_wire_reply_packet_get_header);
diff --git a/tests/unit/mongo/wire/reply_packet_get_nth_document.c b/tests/unit/mongo/wire/reply_packet_get_nth_document.c
new file mode 100644
index 0000000..68d9fed
--- /dev/null
+++ b/tests/unit/mongo/wire/reply_packet_get_nth_document.c
@@ -0,0 +1,68 @@
+#include "test.h"
+#include "tap.h"
+#include "mongo-wire.h"
+#include "bson.h"
+
+#include <string.h>
+
+void
+test_mongo_wire_reply_packet_get_nth_document (void)
+{
+ mongo_packet *p;
+ bson *b, *doc;
+ mongo_packet_header h;
+
+ p = mongo_wire_packet_new ();
+ memset (&h, 0, sizeof (mongo_packet_header));
+ h.opcode = 2;
+ h.length = sizeof (mongo_packet_header);
+ mongo_wire_packet_set_header (p, &h);
+
+ ok (mongo_wire_reply_packet_get_nth_document (NULL, 1, &doc) == FALSE,
+ "mongo_wire_reply_packet_get_nth_document() fails with a NULL packet");
+ ok (mongo_wire_reply_packet_get_nth_document (p, 0, &doc) == FALSE,
+ "mongo_wire_reply_packet_get_nth_document() fails with n = 0");
+ ok (mongo_wire_reply_packet_get_nth_document (p, -42, &doc) == FALSE,
+ "mongo_wire_reply_packet_get_nth_document() fails with n < 0");
+ ok (mongo_wire_reply_packet_get_nth_document (p, 1, NULL) == FALSE,
+ "mongo_wire_reply_packet_get_nth_document() fails with a NULL "
+ "destination");
+
+ ok (mongo_wire_reply_packet_get_nth_document (p, 1, &doc) == FALSE,
+ "mongo_wire_reply_packet_get_nth_document() fails with a "
+ "non-reply packet");
+
+ h.opcode = 1;
+ mongo_wire_packet_set_header (p, &h);
+
+ ok (mongo_wire_reply_packet_get_nth_document (p, 1, &doc) == FALSE,
+ "mongo_wire_reply_packet_get_nth_document() fails with an "
+ "incomplete reply packet");
+
+ mongo_wire_packet_free (p);
+
+ p = test_mongo_wire_generate_reply (TRUE, 0, FALSE);
+ ok (mongo_wire_reply_packet_get_nth_document (p, 1, &doc) == FALSE,
+ "mongo_wire_reply_packet_get_nth_document() fails if there are "
+ "no documents to return");
+ mongo_wire_packet_free (p);
+
+ p = test_mongo_wire_generate_reply (TRUE, 2, TRUE);
+ ok (mongo_wire_reply_packet_get_nth_document (p, 2, &doc),
+ "mongo_wire_reply_packet_get_nth_document() works");
+ b = test_bson_generate_full ();
+ bson_finish (doc);
+
+ ok (memcmp (bson_data (b), bson_data (doc), bson_size (doc)) == 0,
+ "Returned document is correct");
+ bson_free (doc);
+ bson_free (b);
+
+ ok (mongo_wire_reply_packet_get_nth_document (p, 3, &doc) == FALSE,
+ "mongo_wire_reply_packet_get_nth_document() fails if the requested "
+ "document does not exist");
+
+ mongo_wire_packet_free (p);
+}
+
+RUN_TEST (10, mongo_wire_reply_packet_get_nth_document);