int test_main(int, char **) { { ion::metadata_t metadata_ = ion::empty_metadata(); TEST_ASSERT(ion::is_valid(metadata_), ""); TEST_VALUE(ion::get_metadata_string(metadata_), "{}\n"); } { ion::metadata_optional_t metadata_ = ion::parse_metadata("}{"); TEST_ASSERT(!metadata_, ""); } { ion::metadata_optional_t metadata_ = ion::parse_metadata("5"); TEST_ASSERT(!metadata_, ""); } { ion::metadata_optional_t metadata_ = ion::parse_metadata(""); TEST_ASSERT(metadata_, ""); TEST_ASSERT(ion::is_valid(*metadata_), ""); TEST_VALUE(ion::get_metadata_string(*metadata_), "{}\n"); } { ion::metadata_optional_t metadata_ = ion::parse_metadata("{\"a\" : 5}"); TEST_ASSERT(metadata_, ""); TEST_ASSERT(ion::is_valid(*metadata_), ""); TEST_VALUE(ion::get_metadata_value(*metadata_, "a", 0), 5); TEST_VALUE(ion::get_metadata_value(*metadata_, "b", 121), 121); } return 0; }
Commodity Database::parseCommodity(std::string str) { TEST_VALUE(PORK); TEST_VALUE(GOLD); TEST_VALUE(RICE); TEST_VALUE(SILV); TEST_VALUE(OIL); return UNKNOWN_COMMODITY; }
Dealer Database::parseDealer(std::string str) { TEST_VALUE(BARX); TEST_VALUE(BOFA); TEST_VALUE(CITI); TEST_VALUE(DB); TEST_VALUE(HSBC); TEST_VALUE(JPM); TEST_VALUE(MS); TEST_VALUE(RBC); TEST_VALUE(RBS); TEST_VALUE(UBS); return UNKNOWN_DEALER; }
TEST basic_test_lrem(int _commit) { int retval; unsigned char *key = UNSIGN("my key"); long keylen = strlen((char *)key); unsigned char *value1 = UNSIGN("AA"), *value2 = UNSIGN("BB"); long valuelen = 2, deleted; long size; unsigned char **values; long *valueslen; rlite *db = NULL; RL_CALL_VERBOSE(setup_db, RL_OK, &db, _commit, 1); long i, times = 100; for (i = 0; i < times; i++) { RL_CALL_VERBOSE(rl_push, RL_OK, db, key, keylen, 1, 1, 1, &value2, &valuelen, NULL); RL_CALL_VERBOSE(rl_push, RL_OK, db, key, keylen, 1, 1, 1, &value1, &valuelen, NULL); RL_BALANCED(); } RL_CALL_VERBOSE(rl_lrem, RL_OK, db, key, keylen, 1, 2, value2, valuelen, &deleted); RL_BALANCED(); EXPECT_LONG(deleted, 2); #define TEST_VALUE(index, value)\ {\ unsigned char *testvalue;\ long testvaluelen;\ RL_CALL_VERBOSE(rl_lindex, RL_OK, db, key, keylen, index, &testvalue, &testvaluelen);\ if (testvaluelen != (long)strlen((char *)value) || memcmp(testvalue, value, testvaluelen) != 0) {\ FAIL();\ }\ rl_free(testvalue);\ } TEST_VALUE(0, value1); TEST_VALUE(1, value1); TEST_VALUE(2, value1); TEST_VALUE(3, value2); TEST_VALUE(4, value1); RL_CALL_VERBOSE(rl_lrem, RL_OK, db, key, keylen, -1, 200, value1, valuelen, &deleted); RL_BALANCED(); EXPECT_LONG(deleted, 100); RL_CALL_VERBOSE(rl_lrange, RL_OK, db, key, keylen, 0, -1, &size, &values, &valueslen); for (i = 0; i < size; i++) { EXPECT_STR("BB", values[i], valueslen[i]); rl_free(values[i]); } rl_free(values); rl_free(valueslen); RL_CALL_VERBOSE(rl_lrem, RL_DELETED, db, key, keylen, 1, 0, value2, valuelen, &deleted); EXPECT_LONG(deleted, 98); RL_BALANCED(); RL_CALL_VERBOSE(rl_lrange, RL_NOT_FOUND, db, key, keylen, 0, -1, &size, &values, &valueslen); rl_close(db); PASS(); }
int test_main(int, char **) { typedef ion::playlists < ion::flat_playlist > playlists_t; typedef ion::filter_playlist < playlists_t > filter_playlist_t; ion::flat_playlist::unique_ids_t unique_ids_; ion::flat_playlist *playlist1 = new ion::flat_playlist(unique_ids_); playlist1->add_entry(ion::flat_playlist::entry_t(ion::uri("foo://bar11"), *ion::parse_metadata("{ \"title\" : \"hello 441\" }"), false), false); playlist1->add_entry(ion::flat_playlist::entry_t(ion::uri("foo://bar12"), *ion::parse_metadata("{ \"title\" : \"abc def\" }"), false), false); playlist1->add_entry(ion::flat_playlist::entry_t(ion::uri("foo://bar13"), *ion::parse_metadata("{ \"title\" : \"lorem ipsum\" }"), false), false); playlist1->add_entry(ion::flat_playlist::entry_t(ion::uri("foo://bar14"), *ion::parse_metadata("{ \"title\" : \"max mustermann\" }"), false), false); ion::flat_playlist *playlist2 = new ion::flat_playlist(unique_ids_); playlist2->add_entry(ion::flat_playlist::entry_t(ion::uri("foo://bar21"), *ion::parse_metadata("{ \"title\" : \"ugauga\" }"), false), false); playlist2->add_entry(ion::flat_playlist::entry_t(ion::uri("foo://bar22"), *ion::parse_metadata("{ \"title\" : \"john smith\" }"), false), false); playlist2->add_entry(ion::flat_playlist::entry_t(ion::uri("foo://bar23"), *ion::parse_metadata("{ \"title\" : \"test c55\" }"), false), false); playlist2->add_entry(ion::flat_playlist::entry_t(ion::uri("foo://bar24"), *ion::parse_metadata("{ \"title\" : \"xxycz\" }"), false), false); playlists_t playlists; playlists.add_playlist(playlists_t::playlist_ptr_t(playlist1)); playlists.add_playlist(playlists_t::playlist_ptr_t(playlist2)); filter_playlist_t filter_playlist(playlists, boost::phoenix::bind(&match, boost::phoenix::arg_names::arg1)); TEST_VALUE(ion::get_num_entries(filter_playlist), 3); TEST_VALUE(boost::fusion::at_c < 0 > (*ion::get_entry(filter_playlist, 0)).get_path(), "bar12"); TEST_VALUE(boost::fusion::at_c < 0 > (*ion::get_entry(filter_playlist, 1)).get_path(), "bar23"); TEST_VALUE(boost::fusion::at_c < 0 > (*ion::get_entry(filter_playlist, 2)).get_path(), "bar24"); { // testing uri-based retrieval and incompatibility marking // since the playlist adds an id option to the URI, it is retrieved from one of the entries instead of created manually ion::uri test_uri = boost::fusion::at_c < 0 > (*ion::get_entry(filter_playlist, 1)); TEST_ASSERT(ion::get_metadata_for(filter_playlist, test_uri), ""); ion::mark_backend_resource_incompatibility(filter_playlist, test_uri, "test_backend"); TEST_VALUE(boost::fusion::at_c < 2 > (*ion::get_entry(filter_playlist, 1)), true); } // The following code tests the signal relay in filter_playlist // Internally, if one of the playlists that have URIs in the filter playlist proxy entry list get altered, // the filter playlist is notified, and changes its proxy entry list accordingly. playlist1->add_entry(ion::flat_playlist::entry_t(ion::uri("foo://extra"), *ion::parse_metadata("{ \"title\" : \"ccccc\" }"), false), true); TEST_VALUE(ion::get_num_entries(filter_playlist), 4); TEST_VALUE(boost::fusion::at_c < 0 > (*ion::get_entry(filter_playlist, 0)).get_path(), "bar12"); TEST_VALUE(boost::fusion::at_c < 0 > (*ion::get_entry(filter_playlist, 1)).get_path(), "extra"); TEST_VALUE(boost::fusion::at_c < 0 > (*ion::get_entry(filter_playlist, 2)).get_path(), "bar23"); TEST_VALUE(boost::fusion::at_c < 0 > (*ion::get_entry(filter_playlist, 3)).get_path(), "bar24"); playlist2->remove_entry(*ion::get_entry(filter_playlist, 2), true); //print_playlist(filter_playlist); TEST_VALUE(ion::get_num_entries(filter_playlist), 3); TEST_VALUE(boost::fusion::at_c < 0 > (*ion::get_entry(filter_playlist, 0)).get_path(), "bar12"); TEST_VALUE(boost::fusion::at_c < 0 > (*ion::get_entry(filter_playlist, 1)).get_path(), "extra"); TEST_VALUE(boost::fusion::at_c < 0 > (*ion::get_entry(filter_playlist, 2)).get_path(), "bar24"); playlists.remove_playlist(*playlist1); TEST_VALUE(ion::get_num_entries(filter_playlist), 1); TEST_VALUE(boost::fusion::at_c < 0 > (*ion::get_entry(filter_playlist, 0)).get_path(), "bar24"); { // The following code tests correct signal disconnection playlists_t playlists_; ion::flat_playlist *playlist1 = new ion::flat_playlist(unique_ids_); filter_playlist_t *filter_playlist_ = new filter_playlist_t(playlists_, boost::phoenix::bind(&match, boost::phoenix::arg_names::arg1)); playlists_.add_playlist(playlists_t::playlist_ptr_t(playlist1)); delete filter_playlist_; playlist1->add_entry(ion::flat_playlist::entry_t(ion::uri("foo://abc"), *ion::parse_metadata("{ \"title\" : \"ccccc\" }"), false), true); } return 0; }
/* It's hard to explain "the rules" for bucket_merge, in large part because * any automatic conflict-resolution scheme is going to be incorrect for * some endcases of *some* app. The scheme here is pretty conservative, * and should be OK for most apps. It's easier to explain what the code * allows than what it forbids: * * Leaving things alone: it's OK if both s2 and s3 leave a piece of s1 * alone (don't delete the key, and don't change the value). * * Key deletion: a transaction (s2 or s3) can delete a key (from s1), but * only if the other transaction (of s2 and s3) doesn't delete the same key. * However, it's not OK for s2 and s3 to, between them, end up deleting all * the keys. This is a higher-level constraint, due to that the caller of * bucket_merge() doesn't have enough info to unlink the resulting empty * bucket from its BTree correctly. It's also not OK if s2 or s3 are empty, * because the transaction that emptied the bucket unlinked the bucket from * the tree, and nothing we do here can get it linked back in again. * * Key insertion: s2 or s3 can add a new key, provided the other transaction * doesn't insert the same key. It's not OK even if they insert the same * <key, value> pair. * * Mapping value modification: s2 or s3 can modify the value associated * with a key in s1, provided the other transaction doesn't make a * modification of the same key to a different value. It's OK if s2 and s3 * both give the same new value to the key while it's hard to be precise about * why, this doesn't seem consistent with that it's *not* OK for both to add * a new key mapping to the same value). */ static PyObject * bucket_merge(Bucket *s1, Bucket *s2, Bucket *s3) { Bucket *r=0; PyObject *s; SetIteration i1 = {0,0,0}, i2 = {0,0,0}, i3 = {0,0,0}; int cmp12, cmp13, cmp23, mapping, set; /* If either "after" bucket is empty, punt. */ if (s2->len == 0 || s3->len == 0) { merge_error(-1, -1, -1, 12); goto err; } if (initSetIteration(&i1, OBJECT(s1), 1) < 0) goto err; if (initSetIteration(&i2, OBJECT(s2), 1) < 0) goto err; if (initSetIteration(&i3, OBJECT(s3), 1) < 0) goto err; mapping = i1.usesValue | i2.usesValue | i3.usesValue; set = !mapping; if (mapping) r = (Bucket *)PyObject_CallObject((PyObject *)&BucketType, NULL); else r = (Bucket *)PyObject_CallObject((PyObject *)&SetType, NULL); if (r == NULL) goto err; if (i1.next(&i1) < 0) goto err; if (i2.next(&i2) < 0) goto err; if (i3.next(&i3) < 0) goto err; /* Consult zodb/btrees/interfaces.py for the meaning of the last * argument passed to merge_error(). */ /* TODO: This isn't passing on errors raised by value comparisons. */ while (i1.position >= 0 && i2.position >= 0 && i3.position >= 0) { TEST_KEY_SET_OR(cmp12, i1.key, i2.key) goto err; TEST_KEY_SET_OR(cmp13, i1.key, i3.key) goto err; if (cmp12==0) { if (cmp13==0) { if (set || (TEST_VALUE(i1.value, i2.value) == 0)) { /* change in i3 value or all same */ if (merge_output(r, &i3, mapping) < 0) goto err; } else if (set || (TEST_VALUE(i1.value, i3.value) == 0)) { /* change in i2 value */ if (merge_output(r, &i2, mapping) < 0) goto err; } else { /* conflicting value changes in i2 and i3 */ merge_error(i1.position, i2.position, i3.position, 1); goto err; } if (i1.next(&i1) < 0) goto err; if (i2.next(&i2) < 0) goto err; if (i3.next(&i3) < 0) goto err; } else if (cmp13 > 0) { /* insert i3 */ if (merge_output(r, &i3, mapping) < 0) goto err; if (i3.next(&i3) < 0) goto err; } else if (set || (TEST_VALUE(i1.value, i2.value) == 0)) { /* deleted in i3 */ if (i3.position == 1) { /* Deleted the first item. This will modify the parent node, so we don't know if merging will be safe */ merge_error(i1.position, i2.position, i3.position, 13); goto err; } if (i1.next(&i1) < 0) goto err; if (i2.next(&i2) < 0) goto err; } else { /* conflicting del in i3 and change in i2 */ merge_error(i1.position, i2.position, i3.position, 2); goto err; } } else if (cmp13 == 0) { if (cmp12 > 0) { /* insert i2 */ if (merge_output(r, &i2, mapping) < 0) goto err; if (i2.next(&i2) < 0) goto err; } else if (set || (TEST_VALUE(i1.value, i3.value) == 0)) { /* deleted in i2 */ if (i2.position == 1) { /* Deleted the first item. This will modify the parent node, so we don't know if merging will be safe */ merge_error(i1.position, i2.position, i3.position, 13); goto err; } if (i1.next(&i1) < 0) goto err; if (i3.next(&i3) < 0) goto err; } else { /* conflicting del in i2 and change in i3 */ merge_error(i1.position, i2.position, i3.position, 3); goto err; } } else { /* Both keys changed */ TEST_KEY_SET_OR(cmp23, i2.key, i3.key) goto err; if (cmp23==0) { /* dueling inserts or deletes */ merge_error(i1.position, i2.position, i3.position, 4); goto err; } if (cmp12 > 0) { /* insert i2 */ if (cmp23 > 0) { /* insert i3 first */ if (merge_output(r, &i3, mapping) < 0) goto err; if (i3.next(&i3) < 0) goto err; } else { /* insert i2 first */ if (merge_output(r, &i2, mapping) < 0) goto err; if (i2.next(&i2) < 0) goto err; } } else if (cmp13 > 0) { /* Insert i3 */ if (merge_output(r, &i3, mapping) < 0) goto err; if (i3.next(&i3) < 0) goto err; } else { /* 1<2 and 1<3: both deleted 1.key */ merge_error(i1.position, i2.position, i3.position, 5); goto err; } } } while (i2.position >= 0 && i3.position >= 0) { /* New inserts */ TEST_KEY_SET_OR(cmp23, i2.key, i3.key) goto err; if (cmp23==0) { /* dueling inserts */ merge_error(i1.position, i2.position, i3.position, 6); goto err; } if (cmp23 > 0) { /* insert i3 */ if (merge_output(r, &i3, mapping) < 0) goto err; if (i3.next(&i3) < 0) goto err; } else { /* insert i2 */ if (merge_output(r, &i2, mapping) < 0) goto err; if (i2.next(&i2) < 0) goto err; } } while (i1.position >= 0 && i2.position >= 0) { /* remainder of i1 deleted in i3 */ TEST_KEY_SET_OR(cmp12, i1.key, i2.key) goto err; if (cmp12 > 0) { /* insert i2 */ if (merge_output(r, &i2, mapping) < 0) goto err; if (i2.next(&i2) < 0) goto err; } else if (cmp12==0 && (set || (TEST_VALUE(i1.value, i2.value) == 0))) { /* delete i3 */ if (i1.next(&i1) < 0) goto err; if (i2.next(&i2) < 0) goto err; } else { /* Dueling deletes or delete and change */ merge_error(i1.position, i2.position, i3.position, 7); goto err; } } while (i1.position >= 0 && i3.position >= 0) { /* remainder of i1 deleted in i2 */ TEST_KEY_SET_OR(cmp13, i1.key, i3.key) goto err; if (cmp13 > 0) { /* insert i3 */ if (merge_output(r, &i3, mapping) < 0) goto err; if (i3.next(&i3) < 0) goto err; } else if (cmp13==0 && (set || (TEST_VALUE(i1.value, i3.value) == 0))) { /* delete i2 */ if (i1.next(&i1) < 0) goto err; if (i3.next(&i3) < 0) goto err; } else { /* Dueling deletes or delete and change */ merge_error(i1.position, i2.position, i3.position, 8); goto err; } } if (i1.position >= 0) { /* Dueling deletes */ merge_error(i1.position, i2.position, i3.position, 9); goto err; } while (i2.position >= 0) { /* Inserting i2 at end */ if (merge_output(r, &i2, mapping) < 0) goto err; if (i2.next(&i2) < 0) goto err; } while (i3.position >= 0) { /* Inserting i3 at end */ if (merge_output(r, &i3, mapping) < 0) goto err; if (i3.next(&i3) < 0) goto err; } /* If the output bucket is empty, conflict resolution doesn't have * enough info to unlink it from its containing BTree correctly. */ if (r->len == 0) { merge_error(-1, -1, -1, 10); goto err; } finiSetIteration(&i1); finiSetIteration(&i2); finiSetIteration(&i3); if (s1->next) { Py_INCREF(s1->next); r->next = s1->next; } s = bucket_getstate(r); Py_DECREF(r); return s; err: finiSetIteration(&i1); finiSetIteration(&i2); finiSetIteration(&i3); Py_XDECREF(r); return NULL; }