#include "test.h" #include "mongo.h" #include #include #include static const char *db = "test"; static const char *ns = "test.c.error"; int test_namespace_validation( void ) { mongo conn[1]; char longns[130] = "test.foo"; int i; mongo_init( conn ); /* Test a few legal namespaces. */ ASSERT( mongo_validate_ns( conn, "test.foo" ) == MONGO_OK ); ASSERT( conn->err == 0 ); ASSERT( mongo_validate_ns( conn, "test.f" ) == MONGO_OK ); ASSERT( conn->err == 0 ); ASSERT( mongo_validate_ns( conn, "test.foo.bar" ) == MONGO_OK ); ASSERT( conn->err == 0 ); /* Test illegal namespaces. */ ASSERT( mongo_validate_ns( conn, ".test.foo" ) == MONGO_ERROR ); ASSERT( conn->err == MONGO_NS_INVALID ); ASSERT( strncmp( conn->errstr, "ns cannot start with", 20 ) == 0 ); mongo_clear_errors( conn ); ASSERT( mongo_validate_ns( conn, "test..foo" ) == MONGO_ERROR ); ASSERT( conn->err == MONGO_NS_INVALID ); ASSERT( strncmp( conn->errstr, "ns cannot start with", 20 ) == 0 ); mongo_clear_errors( conn ); ASSERT( mongo_validate_ns( conn, "test" ) == MONGO_ERROR ); ASSERT( conn->err == MONGO_NS_INVALID ); ASSERT( strncmp( conn->errstr, "Collection name missing.", 24 ) == 0 ); mongo_clear_errors( conn ); ASSERT( mongo_validate_ns( conn, "test." ) == MONGO_ERROR ); ASSERT( conn->err == MONGO_NS_INVALID ); ASSERT( strncmp( conn->errstr, "Collection name missing.", 24 ) == 0 ); mongo_clear_errors( conn ); ASSERT( mongo_validate_ns( conn, "." ) == MONGO_ERROR ); ASSERT( conn->err == MONGO_NS_INVALID ); ASSERT( strncmp( conn->errstr, "ns cannot start with", 20 ) == 0 ); mongo_clear_errors( conn ); ASSERT( mongo_validate_ns( conn, "tes t.foo" ) == MONGO_ERROR ); ASSERT( conn->err == MONGO_NS_INVALID ); ASSERT( strncmp( conn->errstr, "Database name may not contain", 28 ) == 0 ); mongo_clear_errors( conn ); ASSERT( mongo_validate_ns( conn, "te$st.foo" ) == MONGO_ERROR ); ASSERT( conn->err == MONGO_NS_INVALID ); ASSERT( strncmp( conn->errstr, "Database name may not contain", 28 ) == 0 ); mongo_clear_errors( conn ); ASSERT( mongo_validate_ns( conn, "te/st.foo" ) == MONGO_ERROR ); ASSERT( conn->err == MONGO_NS_INVALID ); ASSERT( strncmp( conn->errstr, "Database name may not contain", 28 ) == 0 ); mongo_clear_errors( conn ); ASSERT( mongo_validate_ns( conn, "te\\st.foo" ) == MONGO_ERROR ); ASSERT( conn->err == MONGO_NS_INVALID ); ASSERT( strncmp( conn->errstr, "Database name may not contain", 28 ) == 0 ); mongo_clear_errors( conn ); ASSERT( mongo_validate_ns( conn, "test.fo$o" ) == MONGO_ERROR ); ASSERT( conn->err == MONGO_NS_INVALID ); ASSERT( strncmp( conn->errstr, "Collection may not contain '$'", 29 ) == 0 ); mongo_clear_errors( conn ); ASSERT( mongo_validate_ns( conn, "test.fo..o" ) == MONGO_ERROR ); ASSERT( conn->err == MONGO_NS_INVALID ); ASSERT( strncmp( conn->errstr, "Collection may not contain two consecutive '.'", 46 ) == 0 ); mongo_clear_errors( conn ); ASSERT( mongo_validate_ns( conn, "test.fo.o." ) == MONGO_ERROR ); ASSERT( conn->err == MONGO_NS_INVALID ); ASSERT( strncmp( conn->errstr, "Collection may not end with '.'", 30 ) == 0 ); mongo_clear_errors( conn ); for(i = 8; i < 129; i++ ) longns[i] = 'a'; longns[129] = '\0'; ASSERT( mongo_validate_ns( conn, longns ) == MONGO_ERROR ); ASSERT( conn->err == MONGO_NS_INVALID ); ASSERT( strncmp( conn->errstr, "Namespace too long; has 129 but must <= 128.", 32 ) == 0 ); mongo_clear_errors( conn ); return 0; } int test_namespace_validation_on_insert( void ) { mongo conn[1]; bson b[1], b2[1]; bson *objs[2]; INIT_SOCKETS_FOR_WINDOWS; CONN_CLIENT_TEST; bson_init( b ); bson_append_int( b, "foo", 1 ); bson_finish( b ); ASSERT( mongo_insert( conn, "tet.fo$o", b, NULL ) == MONGO_ERROR ); ASSERT( conn->err == MONGO_NS_INVALID ); ASSERT( strncmp( conn->errstr, "Collection may not contain '$'", 29 ) == 0 ); mongo_clear_errors( conn ); bson_init( b2 ); bson_append_int( b2, "foo", 1 ); bson_finish( b2 ); objs[0] = b; objs[1] = b2; ASSERT( mongo_insert_batch( conn, "tet.fo$o", (const bson **)objs, 2, NULL, 0 ) == MONGO_ERROR ); ASSERT( conn->err == MONGO_NS_INVALID ); ASSERT( strncmp( conn->errstr, "Collection may not contain '$'", 29 ) == 0 ); bson_destroy( b ); bson_destroy( b2 ); mongo_destroy( conn ); return 0; } int test_insert_limits( void ) { char version[10]; mongo conn[1]; int i; char key[10]; bson b[1], b2[1]; bson *objs[2]; /* Test the default max BSON size. */ mongo_init( conn ); ASSERT( conn->max_bson_size == MONGO_DEFAULT_MAX_BSON_SIZE ); /* We'll perform the full test if we're running v2.0 or later. */ if( mongo_get_server_version( version ) != -1 && version[0] <= '1' ) return 0; CONN_CLIENT_TEST; ASSERT( conn->max_bson_size > MONGO_DEFAULT_MAX_BSON_SIZE ); bson_init( b ); for(i=0; i<1200000; i++) { sprintf( key, "%d", i + 10000000 ); bson_append_int( b, key, i ); } bson_finish( b ); ASSERT( bson_size( b ) > conn->max_bson_size ); ASSERT( mongo_insert( conn, "test.foo", b, NULL ) == MONGO_ERROR ); ASSERT( conn->err == MONGO_BSON_TOO_LARGE ); mongo_clear_errors( conn ); ASSERT( conn->err == 0 ); bson_init( b2 ); bson_append_int( b2, "foo", 1 ); bson_finish( b2 ); objs[0] = b; objs[1] = b2; ASSERT( mongo_insert_batch( conn, "test.foo", (const bson **)objs, 2, NULL, 0 ) == MONGO_ERROR ); ASSERT( conn->err == MONGO_BSON_TOO_LARGE ); bson_destroy( b ); bson_destroy( b2 ); mongo_destroy( conn ); return 0; } int test_get_last_error_commands( void ) { mongo conn[1]; bson obj; INIT_SOCKETS_FOR_WINDOWS; CONN_CLIENT_TEST; /*********************/ ASSERT( mongo_cmd_get_prev_error( conn, db, NULL ) == MONGO_OK ); ASSERT( conn->lasterrcode == 0 ); ASSERT( conn->lasterrstr[0] == 0 ); ASSERT( mongo_cmd_get_last_error( conn, db, NULL ) == MONGO_OK ); ASSERT( conn->lasterrcode == 0 ); ASSERT( conn->lasterrstr[0] == 0 ); ASSERT( mongo_cmd_get_prev_error( conn, db, &obj ) == MONGO_OK ); bson_destroy( &obj ); ASSERT( mongo_cmd_get_last_error( conn, db, &obj ) == MONGO_OK ); ASSERT( bson_has_data( &obj) ); bson_destroy( &obj ); /*********************/ mongo_simple_int_command( conn, db, "forceerror", 1, NULL ); ASSERT( mongo_cmd_get_prev_error( conn, db, NULL ) == MONGO_ERROR ); ASSERT( conn->lasterrcode == 10038 ); ASSERT( strcmp( ( const char * )conn->lasterrstr, "forced error" ) == 0 ); ASSERT( mongo_cmd_get_last_error( conn, db, NULL ) == MONGO_ERROR ); ASSERT( mongo_cmd_get_prev_error( conn, db, &obj ) == MONGO_ERROR ); bson_destroy( &obj ); ASSERT( mongo_cmd_get_last_error( conn, db, &obj ) == MONGO_ERROR ); bson_destroy( &obj ); /* should clear lasterror but not preverror */ mongo_find_one( conn, ns, bson_shared_empty( ), bson_shared_empty( ), NULL ); ASSERT( mongo_cmd_get_prev_error( conn, db, NULL ) == MONGO_ERROR ); ASSERT( mongo_cmd_get_last_error( conn, db, NULL ) == MONGO_OK ); ASSERT( mongo_cmd_get_prev_error( conn, db, &obj ) == MONGO_ERROR ); bson_destroy( &obj ); ASSERT( mongo_cmd_get_last_error( conn, db, &obj ) == MONGO_OK ); bson_destroy( &obj ); /*********************/ mongo_cmd_reset_error( conn, db ); ASSERT( mongo_cmd_get_prev_error( conn, db, NULL ) == MONGO_OK ); ASSERT( mongo_cmd_get_last_error( conn, db, NULL ) == MONGO_OK ); ASSERT( mongo_cmd_get_prev_error( conn, db, &obj ) == MONGO_OK ); bson_destroy( &obj ); ASSERT( mongo_cmd_get_last_error( conn, db, &obj ) == MONGO_OK ); bson_destroy( &obj ); mongo_cmd_drop_db( conn, db ); mongo_destroy( conn ); /* for bson_has_data */ ASSERT( MONGO_ERROR == mongo_create_index( conn, "testbar", bson_shared_empty(), NULL, MONGO_INDEX_SPARSE | MONGO_INDEX_UNIQUE, -1, &obj )); ASSERT( !bson_has_data( &obj) ); return 0; } int main() { test_get_last_error_commands(); test_insert_limits(); test_namespace_validation(); test_namespace_validation_on_insert(); return 0; }