TEST sort_set_sortby_alpha_test(int _commit) { int retval; rlite *db = NULL; RL_CALL_VERBOSE(setup_db, RL_OK, &db, _commit, 1); unsigned char *key = (unsigned char *)"key"; long keylen = 3; char *values[] = {"a", "s", "d"}; long valueslen[] = {1, 1, 1}; RL_CALL_VERBOSE(rl_sadd, RL_OK, db, key, keylen, 3, (unsigned char **)values, valueslen, NULL); RL_CALL_VERBOSE(rl_set, RL_OK, db, (unsigned char *)"wa", 2, (unsigned char *)"1", 1, 1, 0); RL_CALL_VERBOSE(rl_set, RL_OK, db, (unsigned char *)"ws", 2, (unsigned char *)"0", 1, 1, 0); RL_CALL_VERBOSE(rl_set, RL_OK, db, (unsigned char *)"wd", 2, (unsigned char *)"2", 1, 1, 0); long objc; unsigned char **objv; long *objvlen; RL_CALL_VERBOSE(rl_sort, RL_OK, db, key, keylen, (unsigned char *)"w*", 2, 0, 0, 1, 0, 0, -1, 0, NULL, NULL, NULL, 0, &objc, &objv, &objvlen); EXPECT_LONG(objc, 3); EXPECT_BYTES(objv[0], objvlen[0], "s", 1); EXPECT_BYTES(objv[1], objvlen[1], "a", 1); EXPECT_BYTES(objv[2], objvlen[2], "d", 1); rl_free(objv[0]); rl_free(objv[1]); rl_free(objv[2]); rl_free(objv); rl_free(objvlen); rl_close(db); PASS(); }
TEST sort_nosort_list_test(int _commit) { int retval; rlite *db = NULL; RL_CALL_VERBOSE(setup_db, RL_OK, &db, _commit, 1); unsigned char *key = (unsigned char *)"key"; long keylen = 3; char *values[] = {"1", "0", "2"}; long valueslen[] = {1, 1, 1}; RL_CALL_VERBOSE(rl_push, RL_OK, db, key, keylen, 1, 0, 3, (unsigned char **)values, valueslen, NULL); long objc; unsigned char **objv; long *objvlen; RL_CALL_VERBOSE(rl_sort, RL_OK, db, key, keylen, NULL, 0, 1, 0, 0, 0, 0, -1, 0, NULL, NULL, NULL, 0, &objc, &objv, &objvlen); EXPECT_LONG(objc, 3); EXPECT_BYTES(objv[0], objvlen[0], "1", 1); EXPECT_BYTES(objv[1], objvlen[1], "0", 1); EXPECT_BYTES(objv[2], objvlen[2], "2", 1); rl_free(objv[0]); rl_free(objv[1]); rl_free(objv[2]); rl_free(objv); rl_free(objvlen); rl_close(db); PASS(); }
TEST test_rlite_page_cache() { rlite *db = malloc(sizeof(rlite)); db->driver_type = RL_MEMORY_DRIVER; int retval; void *obj; int size = 15; db->write_pages_len = 0; db->read_pages = malloc(sizeof(rl_page *) * size); db->read_pages_len = size; db->read_pages_alloc = size; long i; for (i = 0; i < size; i++) { db->read_pages[i] = malloc(sizeof(rl_page)); db->read_pages[i]->page_number = i; db->read_pages[i]->type = &rl_data_type_header; // not a real life scenario, we just need any pointer db->read_pages[i]->obj = db->read_pages[i]; } for (i = 0; i < size; i++) { RL_CALL_VERBOSE(rl_read, RL_FOUND, db, &rl_data_type_header, i, NULL, &obj, 1); EXPECT_PTR(obj, db->read_pages[i]) } for (i = 0; i < size; i++) { rl_free(db->read_pages[i]); } rl_free(db->read_pages); rl_free(db); PASS(); }
TEST basic_test_ltrim(int _commit) { int retval; unsigned char *key = UNSIGN("my key"); long keylen = strlen((char *)key); long i, size; unsigned char **values; long *valueslen; rlite *db = NULL; RL_CALL_VERBOSE(setup_db, RL_OK, &db, _commit, 1); RL_CALL_VERBOSE(create, RL_OK, db, key, keylen, 200, _commit, 1); RL_CALL_VERBOSE(rl_ltrim, RL_OK, db, key, keylen, 50, -50); RL_BALANCED(); RL_CALL_VERBOSE(rl_lrange, RL_OK, db, key, keylen, 0, -1, &size, &values, &valueslen); EXPECT_LONG(size, 101); for (i = 0; i < size; i++) { EXPECT_LONG(valueslen[i], 2); EXPECT_INT(values[i][0], ((50 + i) % CHAR_MAX)); EXPECT_INT(values[i][1], 0); rl_free(values[i]); } rl_free(values); rl_free(valueslen); RL_CALL_VERBOSE(rl_ltrim, RL_DELETED, db, key, keylen, 1, 0); RL_BALANCED(); rl_close(db); PASS(); }
int rl_close(rlite *db) { if (!db) { return RL_OK; } if (db->driver_type == RL_FILE_DRIVER) { rl_unsubscribe_all(db); } // discard before removing the driver, since we need to release locks rl_discard(db); if (db->driver_type == RL_FILE_DRIVER) { rl_file_driver *driver = db->driver; rl_free(driver->filename); } else if (db->driver_type == RL_MEMORY_DRIVER) { rl_memory_driver* driver = db->driver; rl_free(driver->data); } if (db->subscriber_lock_filename) { remove(db->subscriber_lock_filename); rl_free(db->subscriber_lock_filename); } rl_free(db->driver); rl_free(db->subscriber_id); rl_free(db->read_pages); rl_free(db->write_pages); rl_free(db->databases); rl_free(db->initial_databases); rl_free(db); return RL_OK; }
int rl_dirty_hash(struct rlite *db, unsigned char **hash) { long i; int retval = RL_OK; rl_page *page; SHA1_CTX sha; unsigned char *data = NULL; if (db->write_pages_len == 0) { *hash = NULL; goto cleanup; } RL_MALLOC(data, db->page_size * sizeof(unsigned char)); RL_MALLOC(*hash, sizeof(unsigned char) * 20); SHA1Init(&sha); for (i = 0; i < db->write_pages_len; i++) { page = db->write_pages[i]; memset(data, 0, db->page_size); if (page->type) { retval = page->type->serialize(db, page->obj, data); } SHA1Update(&sha, data, db->page_size); } SHA1Final(*hash, &sha); cleanup: rl_free(data); if (retval != RL_OK) { rl_free(*hash); *hash = NULL; } return retval; }
int rl_key_set(rlite *db, const unsigned char *key, long keylen, unsigned char type, long value_page, unsigned long long expires, long version) { int retval; rl_key *key_obj = NULL; unsigned char *digest = NULL; RL_CALL2(rl_key_delete, RL_OK, RL_NOT_FOUND, db, key, keylen); RL_MALLOC(digest, sizeof(unsigned char) * 20); RL_CALL(sha1, RL_OK, key, keylen, digest); rl_btree *btree; RL_CALL(rl_get_key_btree, RL_OK, db, &btree, 1); RL_MALLOC(key_obj, sizeof(*key_obj)) RL_CALL(rl_multi_string_set, RL_OK, db, &key_obj->string_page, key, keylen); key_obj->type = type; key_obj->value_page = value_page; key_obj->expires = expires; // reserving version=0 for non existent keys if (version == 0) { version = 1; } key_obj->version = version; RL_CALL(rl_btree_add_element, RL_OK, db, btree, db->databases[rl_get_selected_db(db)], digest, key_obj); retval = RL_OK; cleanup: if (retval != RL_OK) { rl_free(digest); rl_free(key_obj); } return retval; }
int rl_header_deserialize(struct rlite *db, void **UNUSED(obj), void *UNUSED(context), unsigned char *data) { int retval = RL_OK; int identifier_len = strlen((char *)identifier); if (memcmp(data, identifier, identifier_len) != 0) { fprintf(stderr, "Unexpected header, expecting %s\n", identifier); return RL_INVALID_STATE; } db->page_size = get_4bytes(&data[identifier_len]); db->initial_next_empty_page = db->next_empty_page = get_4bytes(&data[identifier_len + 4]); db->initial_number_of_pages = db->number_of_pages = get_4bytes(&data[identifier_len + 8]); db->initial_number_of_databases = db->number_of_databases = get_4bytes(&data[identifier_len + 12]); rl_free(db->databases); rl_free(db->initial_databases); RL_MALLOC(db->databases, sizeof(long) * (db->number_of_databases + RLITE_INTERNAL_DB_COUNT)); RL_MALLOC(db->initial_databases, sizeof(long) * (db->number_of_databases + RLITE_INTERNAL_DB_COUNT)); long i, pos = identifier_len + 16; for (i = 0; i < db->number_of_databases + RLITE_INTERNAL_DB_COUNT; i++) { db->initial_databases[i] = db->databases[i] = get_4bytes(&data[pos]); pos += 4; } cleanup: return retval; }
TEST test_append(long size, long append_size) { int retval; unsigned char *data = malloc(sizeof(unsigned char) * size); unsigned char *append_data = malloc(sizeof(unsigned char) * append_size); unsigned char *testdata; long testdatalen; rlite *db = NULL; RL_CALL_VERBOSE(rl_open, RL_OK, ":memory:", &db, RLITE_OPEN_READWRITE | RLITE_OPEN_CREATE); long page, i; for (i = 0; i < size; i++) { data[i] = i % 123; } for (i = 0; i < append_size; i++) { append_data[i] = i % 123; } RL_CALL_VERBOSE(rl_multi_string_set, RL_OK, db, &page, data, size); RL_CALL_VERBOSE(rl_multi_string_append, RL_OK, db, page, append_data, append_size, &testdatalen); EXPECT_LONG(testdatalen, size + append_size); RL_CALL_VERBOSE(rl_multi_string_get, RL_OK, db, page, &testdata, &testdatalen); EXPECT_LONG(testdatalen, size + append_size); EXPECT_BYTES(testdata, size, data, size); EXPECT_BYTES(&testdata[size], append_size, append_data, append_size); rl_free(testdata); rl_free(data); rl_free(append_data); rl_close(db); PASS(); }
TEST basic_set_get() { int retval, i, j; long size, size2, number; unsigned char *data, *data2; rlite *db = NULL; RL_CALL_VERBOSE(rl_open, RL_OK, ":memory:", &db, RLITE_OPEN_READWRITE | RLITE_OPEN_CREATE); for (i = 0; i < 2; i++) { srand(1); size = i == 0 ? 20 : 1020; data = malloc(sizeof(unsigned char) * size); for (j = 0; j < size; j++) { data[j] = (unsigned char)(rand() / CHAR_MAX); } RL_CALL_VERBOSE(rl_multi_string_set, RL_OK, db, &number, data, size); RL_CALL_VERBOSE(rl_multi_string_get, RL_OK, db, number, &data2, &size2); EXPECT_BYTES(data, size, data2, size2); rl_free(data); rl_free(data2); } rl_close(db); PASS(); }
static int add_member(rlite *db, rl_btree *scores, long scores_page, rl_skiplist *skiplist, long skiplist_page, double score, unsigned char *member, long memberlen) { int retval; unsigned char *digest = NULL; void *value_ptr; RL_MALLOC(value_ptr, sizeof(double)); digest = rl_malloc(sizeof(unsigned char) * 20); if (!digest) { rl_free(value_ptr); retval = RL_OUT_OF_MEMORY; goto cleanup; } *(double *)value_ptr = score; retval = sha1(member, memberlen, digest); if (retval != RL_OK) { rl_free(value_ptr); rl_free(digest); goto cleanup; } RL_CALL(rl_btree_add_element, RL_OK, db, scores, scores_page, digest, value_ptr); retval = rl_skiplist_add(db, skiplist, skiplist_page, score, member, memberlen); if (retval != RL_OK) { // This failure is critical. The btree already has the element, but // the skiplist failed to add it. If left as is, it would be in an // inconsistent state. Dropping all the transaction in progress. rl_discard(db); goto cleanup; } cleanup: return retval; }
TEST test_lrange(rlite *db, unsigned char *key, long keylen, long start, long stop, long cstart, long cstop) { unsigned char testvalue[2]; long testvaluelen = 2; testvalue[1] = 0; long i, size = 0, *valueslen = NULL; unsigned char **values = NULL; long pos; int retval; RL_CALL_VERBOSE(rl_lrange, RL_OK, db, key, keylen, start, stop, &size, &values, &valueslen); EXPECT_LONG(size, cstop - cstart); for (i = cstart; i < cstop; i++) { testvalue[0] = i; pos = i - cstart; EXPECT_BYTES(values[pos], valueslen[pos], testvalue, testvaluelen); } for (i = 0; i < size; i++) { rl_free(values[i]); } rl_free(values); rl_free(valueslen); PASS(); }
TEST basic_test_sadd_sunionstore(int _commit) { int retval; rlite *db = NULL; RL_CALL_VERBOSE(setup_db, RL_OK, &db, _commit, 1); unsigned char *key = UNSIGN("my key"); long keylen = strlen((char *)key); unsigned char *key2 = UNSIGN("my key2"); long key2len = strlen((char *)key2); unsigned char *target = UNSIGN("my target"); long targetlen = strlen((char *)target); unsigned char *datas[2] = {UNSIGN("my data"), UNSIGN("my data2")}; long dataslen[2] = {strlen((char *)datas[0]), strlen((char *)datas[1]) }; unsigned char *datas2[3] = {UNSIGN("other data2"), UNSIGN("yet another data"), UNSIGN("my data")}; long datas2len[3] = {strlen((char *)datas2[0]), strlen((char *)datas2[1]), strlen((char *)datas2[2])}; unsigned char *keys[2] = {key, key2}; long keyslen[2] = {keylen, key2len}; unsigned char **datasunion; long *datasunionlen, datasc, i; long added; RL_CALL_VERBOSE(rl_sadd, RL_OK, db, key, keylen, 2, datas, dataslen, NULL); RL_BALANCED(); RL_CALL_VERBOSE(rl_sadd, RL_OK, db, key2, key2len, 3, datas2, datas2len, NULL); RL_BALANCED(); RL_CALL_VERBOSE(rl_sunionstore, RL_OK, db, target, targetlen, 2, keys, keyslen, &added); EXPECT_LONG(added, 4); datasc = added; RL_CALL_VERBOSE(rl_srandmembers, RL_OK, db, target, targetlen, 0, &datasc, &datasunion, &datasunionlen); #define ASSERT_IN_4(s, l)\ if (!IS_EQUAL(s, l, datasunion[0], datasunionlen[0]) &&\ !IS_EQUAL(s, l, datasunion[1], datasunionlen[1]) &&\ !IS_EQUAL(s, l, datasunion[2], datasunionlen[2]) &&\ !IS_EQUAL(s, l, datasunion[3], datasunionlen[3])\ ) {\ fprintf(stderr, "Expected union to contains \"%s\" (%ld) on line %d\n", datas[0], dataslen[0], __LINE__);\ FAIL();\ } ASSERT_IN_4(datas[0], dataslen[0]); ASSERT_IN_4(datas[1], dataslen[1]); ASSERT_IN_4(datas2[0], datas2len[0]); ASSERT_IN_4(datas2[1], datas2len[1]); for (i = 0; i < datasc; i++) { rl_free(datasunion[i]); } rl_free(datasunion); rl_free(datasunionlen); rl_close(db); PASS(); }
int rl_list_node_destroy(rlite *UNUSED(db), void *_node) { rl_list_node *node = _node; long i; if (node->elements) { for (i = 0; i < node->size; i++) { rl_free(node->elements[i]); } rl_free(node->elements); } rl_free(node); return 0; }
TEST basic_test_rpush_lpop(int maxsize, int _commit) { int retval; rlite *db = NULL; unsigned char *value = malloc(sizeof(unsigned char) * 2); RL_CALL_VERBOSE(setup_db, RL_OK, &db, _commit, 1); unsigned char *key = UNSIGN("my key"); long keylen = strlen((char *)key); unsigned char *testvalue; long testvaluelen; value[1] = 0; int i; RL_CALL_VERBOSE(create, RL_OK, db, key, keylen, maxsize, _commit, 0); for (i = maxsize - 1; i >= 0; i--) { value[0] = i % CHAR_MAX; RL_CALL_VERBOSE(rl_pop, RL_OK, db, key, keylen, &testvalue, &testvaluelen, 1); EXPECT_BYTES(value, 2, testvalue, testvaluelen); rl_free(testvalue); RL_BALANCED(); } free(value); rl_close(db); PASS(); }
TEST test_setrange(long initialsize, long index, long updatesize) { int retval; long finalsize = index + updatesize > initialsize ? index + updatesize : initialsize; long newlength, testdatalen; unsigned char *testdata; unsigned char *finaldata = calloc(finalsize, sizeof(unsigned char)); unsigned char *initialdata = malloc(sizeof(unsigned char) * initialsize); unsigned char *updatedata = malloc(sizeof(unsigned char) * updatesize); rlite *db = NULL; RL_CALL_VERBOSE(rl_open, RL_OK, ":memory:", &db, RLITE_OPEN_READWRITE | RLITE_OPEN_CREATE); long page, i; for (i = 0; i < initialsize; i++) { finaldata[i] = initialdata[i] = i % 123; } for (i = 0; i < updatesize; i++) { finaldata[index + i] = updatedata[i] = i % 151; } RL_CALL_VERBOSE(rl_multi_string_set, RL_OK, db, &page, initialdata, initialsize); RL_CALL_VERBOSE(rl_multi_string_setrange, RL_OK, db, page, updatedata, updatesize, index, &newlength); EXPECT_LONG(finalsize, newlength); RL_CALL_VERBOSE(rl_multi_string_get, RL_OK, db, page, &testdata, &testdatalen); EXPECT_BYTES(finaldata, finalsize, testdata, testdatalen); rl_free(testdata); free(finaldata); free(initialdata); free(updatedata); rl_close(db); PASS(); }
static int _zremiterator(rlite *db, const unsigned char *key, long keylen, long levels_page_number, rl_zset_iterator *iterator, rl_btree *scores, long scores_page, rl_skiplist *skiplist, long skiplist_page, long *changed) { long _changed = 0; double score; unsigned char *member; long memberlen; int retval; while ((retval = rl_zset_iterator_next(iterator, &score, &member, &memberlen)) == RL_OK) { retval = remove_member_score(db, key, keylen, levels_page_number, scores, scores_page, skiplist, skiplist_page, member, memberlen, score); rl_free(member); if (retval != RL_OK && retval != RL_DELETED) { rl_zset_iterator_destroy(iterator); goto cleanup; } _changed++; } if (retval != RL_END) { goto cleanup; } *changed = _changed; retval = RL_OK; cleanup: return retval; }
int rl_flushdb(struct rlite *db) { int retval; rl_btree *btree; rl_btree_iterator *iterator = NULL; rl_key *key; void *tmp; RL_CALL2(rl_get_key_btree, RL_OK, RL_NOT_FOUND, db, &btree, 0); if (retval == RL_NOT_FOUND) { retval = RL_OK; goto cleanup; } RL_CALL(rl_btree_iterator_create, RL_OK, db, btree, &iterator); while ((retval = rl_btree_iterator_next(iterator, NULL, &tmp)) == RL_OK) { key = tmp; RL_CALL(rl_key_delete_value, RL_OK, db, key->type, key->value_page); RL_CALL(rl_multi_string_delete, RL_OK, db, key->string_page); rl_free(key); } if (retval != RL_END) { goto cleanup; } RL_CALL(rl_btree_delete, RL_OK, db, btree); RL_CALL(rl_delete, RL_OK, db, db->databases[db->selected_database]); db->databases[db->selected_database] = 0; RL_CALL(rl_write, RL_OK, db, &rl_data_type_header, 0, NULL); retval = RL_OK; cleanup: return retval; }
TEST basic_read_timeout_write() { static const char *data = "hello world!"; size_t datalen = strlen(data); char *testdata = NULL; size_t testdatalen = 0; pthread_t thread; struct buf buffer; buffer.data = data; buffer.datalen = datalen; buffer.sleep = 1; struct timeval timeout; timeout.tv_sec = 10; timeout.tv_usec = 0; delete_file(); rl_create_signal(FILEPATH); pthread_create(&thread, NULL, write_signal, &buffer); rl_read_signal(FILEPATH, NULL, &testdata, &testdatalen); unlink(FILEPATH); ASSERT_EQ(datalen, testdatalen); ASSERT_EQ(memcmp(data, testdata, datalen), 0); rl_free(testdata); PASS(); }
int rl_key_delete(struct rlite *db, const unsigned char *key, long keylen) { int retval; void *tmp; unsigned char *digest; rl_btree *btree = NULL; rl_key *key_obj = NULL; RL_MALLOC(digest, sizeof(unsigned char) * 20); RL_CALL(sha1, RL_OK, key, keylen, digest); RL_CALL(rl_get_key_btree, RL_OK, db, &btree, 0); retval = rl_btree_find_score(db, btree, digest, &tmp, NULL, NULL); if (retval == RL_FOUND) { int selected_database = rl_get_selected_db(db); key_obj = tmp; RL_CALL(rl_multi_string_delete, RL_OK, db, key_obj->string_page); retval = rl_btree_remove_element(db, btree, db->databases[selected_database], digest); if (retval == RL_DELETED) { db->databases[selected_database] = 0; retval = RL_OK; } else if (retval != RL_OK) { goto cleanup; } } cleanup: rl_free(digest); return retval; }
int rl_print_list(rlite *db, rl_list *list) { if (!list->type->formatter) { fprintf(stderr, "Trying to print an element without formatter\n"); return RL_UNEXPECTED; } printf("-------\n"); rl_list_node *node; void *_node; char *element; int size; long i, number = list->left; int retval = RL_OK; while (number != 0) { RL_CALL(rl_read, RL_FOUND, db, list->type->list_node_type, number, list, &_node, 1); node = _node; for (i = 0; i < node->size; i++) { RL_CALL(list->type->formatter, RL_OK, node->elements[i], &element, &size); fwrite(element, sizeof(char), size, stdout); rl_free(element); printf("\n"); } number = node->right; } printf("-------\n"); cleanup: return retval; }
int rl_list_iterator_destroy(rlite *UNUSED(db), rl_list_iterator *iterator) { if (iterator->node) { rl_list_node_nocache_destroy(iterator->db, iterator->node); } rl_free(iterator); return RL_OK; }
int rl_multi_string_sha1(struct rlite *db, unsigned char digest[20], long number) { unsigned char *data; long datalen; SHA1_CTX sha; SHA1Init(&sha); void *tmp; rl_list *list; rl_list_iterator *iterator = NULL; int retval; RL_CALL(rl_read, RL_FOUND, db, &rl_data_type_list_long, number, &rl_list_type_long, &tmp, 0); list = tmp; RL_CALL(rl_list_iterator_create, RL_OK, db, &iterator, list, 1); long size = 0; while ((retval = rl_list_iterator_next(iterator, &tmp)) == RL_OK) { if (size == 0) { size = *(long *)tmp; rl_free(tmp); continue; } RL_CALL(rl_string_get, RL_OK, db, &data, *(long *)tmp); datalen = size > db->page_size ? db->page_size : size; SHA1Update(&sha, data, datalen); size -= datalen; rl_free(tmp); } iterator = NULL; if (retval != RL_END) { goto cleanup; } RL_CALL(rl_list_nocache_destroy, RL_OK, db, list); SHA1Final(digest, &sha); retval = RL_OK; cleanup: if (iterator) { rl_list_iterator_destroy(db, iterator); } return retval; }
void rl_imageset_destroy( const rl_imageset_t* imageset ) { for ( int i = imageset->num_images - 1; i >= 0; --i ) { rl_image_destroy( imageset->images[ i ] ); } rl_free( (void*)imageset ); }
TEST basic_test_sadd_sunion(int _commit) { int retval; rlite *db = NULL; RL_CALL_VERBOSE(setup_db, RL_OK, &db, _commit, 1); unsigned char *key = UNSIGN("my key"); long keylen = strlen((char *)key); unsigned char *key2 = UNSIGN("my key2"); long key2len = strlen((char *)key2); unsigned char *datas[2] = {UNSIGN("my data"), UNSIGN("my data2")}; long dataslen[2] = {strlen((char *)datas[0]), strlen((char *)datas[1]) }; unsigned char *datas2[3] = {UNSIGN("other data2"), UNSIGN("yet another data"), UNSIGN("my data")}; long datas2len[3] = {strlen((char *)datas2[0]), strlen((char *)datas2[1]), strlen((char *)datas2[2])}; unsigned char *keys[2] = {key, key2}; long keyslen[2] = {keylen, key2len}; unsigned char **datasunion; long *datasunionlen, datasc, i; RL_CALL_VERBOSE(rl_sadd, RL_OK, db, key, keylen, 2, datas, dataslen, NULL); RL_BALANCED(); RL_CALL_VERBOSE(rl_sadd, RL_OK, db, key2, key2len, 3, datas2, datas2len, NULL); RL_BALANCED(); RL_CALL_VERBOSE(rl_sunion, RL_OK, db, 2, keys, keyslen, &datasc, &datasunion, &datasunionlen); EXPECT_LONG(datasc, 4); EXPECT_BYTES(datas[1], dataslen[1], datasunion[0], datasunionlen[0]); EXPECT_BYTES(datas[0], dataslen[0], datasunion[1], datasunionlen[1]); EXPECT_BYTES(datas2[1], datas2len[1], datasunion[2], datasunionlen[2]); EXPECT_BYTES(datas2[0], datas2len[0], datasunion[3], datasunionlen[3]); for (i = 0; i < datasc; i++) { rl_free(datasunion[i]); } rl_free(datasunion); rl_free(datasunionlen); rl_close(db); PASS(); }
int rl_list_node_create(rlite *UNUSED(db), rl_list *list, rl_list_node **_node) { int retval; rl_list_node *node; RL_MALLOC(node, sizeof(rl_list_node)); RL_MALLOC(node->elements, sizeof(void *) * list->max_node_size); node->size = 0; node->left = 0; node->right = 0; *_node = node; retval = RL_OK; cleanup: if (retval != RL_OK) { if (node) { rl_free(node->elements); } rl_free(node); } return retval; }
TEST test_string() { INIT(); RL_CALL_VERBOSE(rl_set, RL_OK, db, key, keylen, UNSIGN("asd"), 3, 0, 0); RL_CALL_VERBOSE(rl_dump, RL_OK, db, key, keylen, &testvalue, &testvaluelen); EXPECT_BYTES(UNSIGN("\x00\x80\x00\x00\x00\x03\x61sd\x06\x00\xa4\xed\x80\xcb:7\x89\xd7"), 19, testvalue, testvaluelen); rl_free(testvalue); rl_close(db); PASS(); }
TEST test_hash() { INIT(); RL_CALL_VERBOSE(rl_hset, RL_OK, db, key, keylen, UNSIGN("field"), 5, UNSIGN("value"), 5, NULL, 0); RL_CALL_VERBOSE(rl_hset, RL_OK, db, key, keylen, UNSIGN("field2"), 6, UNSIGN("value2"), 6, NULL, 0); RL_CALL_VERBOSE(rl_dump, RL_OK, db, key, keylen, &testvalue, &testvaluelen); EXPECT_BYTES(UNSIGN("\x04\x80\x00\x00\x00\x02\x80\x00\x00\x00\x05\x66\x69\x65\x6c\x64\x80\x00\x00\x00\x05\x76\x61\x6c\x75\x65\x80\x00\x00\x00\x06\x66\x69\x65\x6c\x64\x32\x80\x00\x00\x00\x06\x76\x61\x6c\x75\x65\x32\x06\x00\x74\xaf\xd2\x25\x1d\x50\x0c\xee"), 58, testvalue, testvaluelen); rl_free(testvalue); rl_close(db); PASS(); }
TEST test_zset() { INIT(); RL_CALL_VERBOSE(rl_zadd, RL_OK, db, key, keylen, 1.23, UNSIGN("a"), 1); RL_CALL_VERBOSE(rl_zadd, RL_OK, db, key, keylen, 4.5, UNSIGN("b"), 1); RL_CALL_VERBOSE(rl_dump, RL_OK, db, key, keylen, &testvalue, &testvaluelen); EXPECT_BYTES(UNSIGN("\x03\x80\x00\x00\x00\x02\x80\x00\x00\x00\x01\x61\x08\x31\x2e\x32\x33\x30\x30\x30\x30\x80\x00\x00\x00\x01\x62\x08\x34\x2e\x35\x30\x30\x30\x30\x30\x06\x00\x62\xf2\xc1\x8b\x73\x18\x51\xe6"), 46, testvalue, testvaluelen); rl_free(testvalue); rl_close(db); PASS(); }
TEST basic_test_sadd_sinter(int _commit) { int retval; rlite *db = NULL; RL_CALL_VERBOSE(setup_db, RL_OK, &db, _commit, 1); unsigned char *key = UNSIGN("my key"); long keylen = strlen((char *)key); unsigned char *key2 = UNSIGN("my key2"); long key2len = strlen((char *)key2); unsigned char *data = UNSIGN("my data"); long datalen = strlen((char *)data); unsigned char *data2 = UNSIGN("other data2"); long data2len = strlen((char *)data2); unsigned char *keys[2] = {key, key2}; long keyslen[2] = {keylen, key2len}; unsigned char *datas[2] = {data, data2}; long dataslen[2] = {datalen, data2len}; unsigned char **datasdiff; long *datasdifflen, datasc, i; RL_CALL_VERBOSE(rl_sadd, RL_OK, db, key, keylen, 2, datas, dataslen, NULL); RL_BALANCED(); RL_CALL_VERBOSE(rl_sadd, RL_OK, db, key2, key2len, 1, datas, dataslen, NULL); RL_BALANCED(); RL_CALL_VERBOSE(rl_sinter, RL_OK, db, 2, keys, keyslen, &datasc, &datasdiff, &datasdifflen); EXPECT_LONG(datasc, 1); EXPECT_BYTES(data, datalen, datasdiff[0], datasdifflen[0]); for (i = 0; i < datasc; i++) { rl_free(datasdiff[i]); } rl_free(datasdiff); rl_free(datasdifflen); rl_close(db); PASS(); }