Author: prahal Date: Wed Feb 10 22:53:13 2010 New Revision: 6034 URL: http://www.opensync.org/changeset/6034 Log: Add testcase for #1207 Ie if a change is shared (members have "same" entries) , the conversion in prepare write will apply more than once to this change. As the conversion path is cached, conversion will happens with a forced conversion path on data already converted to another format. Which can segfault and is anyway of no use and harmfull( change is not meant to be written). Added: trunk/tests/data/multisync_multiformats/ trunk/tests/data/multisync_multiformats/configs/ trunk/tests/data/multisync_multiformats/configs/group/ trunk/tests/data/multisync_multiformats/configs/group/1/ trunk/tests/data/multisync_multiformats/configs/group/1/mock-sync.conf trunk/tests/data/multisync_multiformats/configs/group/1/syncmember.conf trunk/tests/data/multisync_multiformats/configs/group/2/ trunk/tests/data/multisync_multiformats/configs/group/2/mock-sync.conf trunk/tests/data/multisync_multiformats/configs/group/2/syncmember.conf trunk/tests/data/multisync_multiformats/configs/group/3/ trunk/tests/data/multisync_multiformats/configs/group/3/mock-sync.conf trunk/tests/data/multisync_multiformats/configs/group/3/syncmember.conf trunk/tests/data/multisync_multiformats/configs/group/4/ trunk/tests/data/multisync_multiformats/configs/group/4/mock-sync.conf trunk/tests/data/multisync_multiformats/configs/group/4/syncmember.conf trunk/tests/data/multisync_multiformats/configs/group/syncgroup.conf trunk/tests/data/multisync_multiformats/data1/ trunk/tests/data/multisync_multiformats/data1/testdata (contents, props changed) trunk/tests/data/multisync_multiformats/data1/testdata_to_sync (contents, props changed) trunk/tests/data/multisync_multiformats/data2/ trunk/tests/data/multisync_multiformats/data2/testdata (contents, props changed) trunk/tests/data/multisync_multiformats/data3/ trunk/tests/data/multisync_multiformats/data3/testdata (contents, props changed) trunk/tests/data/multisync_multiformats/data4/ Modified: trunk/opensync/engine/opensync_sink_engine.c trunk/tests/CMakeLists.txt trunk/tests/mock-plugin/mock_format.c trunk/tests/sync-tests/check_multisync.c Modified: trunk/opensync/engine/opensync_sink_engine.c ============================================================================== --- trunk/opensync/engine/opensync_sink_engine.c Sun Feb 7 22:41:32 2010 (r6033) +++ trunk/opensync/engine/opensync_sink_engine.c Wed Feb 10 22:53:13 2010 (r6034) @@ -190,6 +190,11 @@ if (entry_engine->change == NULL) continue; + /* If change not meant to get written (change shared among multiple "same" mapping + entry engines), prevents conversions see #1207 */ + if (!osync_entry_engine_is_dirty(entry_engine)) + continue; + if (osync_change_get_changetype(entry_engine->change) == OSYNC_CHANGE_TYPE_DELETED) continue; Modified: trunk/tests/CMakeLists.txt ============================================================================== --- trunk/tests/CMakeLists.txt Sun Feb 7 22:41:32 2010 (r6033) +++ trunk/tests/CMakeLists.txt Wed Feb 10 22:53:13 2010 (r6034) @@ -296,6 +296,7 @@ OSYNC_TESTCASE( multisync multisync_easy_new) OSYNC_TESTCASE( multisync multisync_dual_new) OSYNC_TESTCASE( multisync multisync_triple_new) +OSYNC_TESTCASE( multisync multisync_easy_same) OSYNC_TESTCASE( multisync multisync_easy_mod) OSYNC_TESTCASE( multisync multisync_dual_mod) OSYNC_TESTCASE( multisync multisync_triple_mod) Added: trunk/tests/data/multisync_multiformats/configs/group/1/mock-sync.conf ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ trunk/tests/data/multisync_multiformats/configs/group/1/mock-sync.conf Wed Feb 10 22:53:13 2010 (r6034) @@ -0,0 +1,15 @@ +<?xml version="1.0"?> +<config version="1.0"> + <Resources> + <Resource> + <Enabled>1</Enabled> + <Formats> + <Format> + <Name>mockformat1</Name> + </Format> + </Formats> + <ObjType>mockobjtype1</ObjType> + <Path>data1</Path> + </Resource> + </Resources> +</config> Added: trunk/tests/data/multisync_multiformats/configs/group/1/syncmember.conf ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ trunk/tests/data/multisync_multiformats/configs/group/1/syncmember.conf Wed Feb 10 22:53:13 2010 (r6034) @@ -0,0 +1,15 @@ +<?xml version="1.0"?> +<syncmember version="1.0"> + <pluginname>mock-sync</pluginname> + <objtype> + <name>mockobjtype1</name> + <enabled>1</enabled> + <read>1</read> + <getchanges>1</getchanges> + <write>1</write> + <objformat> + <name>mockformat1</name> + <config/> + </objformat> + </objtype> +</syncmember> Added: trunk/tests/data/multisync_multiformats/configs/group/2/mock-sync.conf ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ trunk/tests/data/multisync_multiformats/configs/group/2/mock-sync.conf Wed Feb 10 22:53:13 2010 (r6034) @@ -0,0 +1,15 @@ +<?xml version="1.0"?> +<config version="1.0"> + <Resources> + <Resource> + <Enabled>1</Enabled> + <Formats> + <Format> + <Name>mockformat1a</Name> + </Format> + </Formats> + <ObjType>mockobjtype1</ObjType> + <Path>data2</Path> + </Resource> + </Resources> +</config> Added: trunk/tests/data/multisync_multiformats/configs/group/2/syncmember.conf ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ trunk/tests/data/multisync_multiformats/configs/group/2/syncmember.conf Wed Feb 10 22:53:13 2010 (r6034) @@ -0,0 +1,15 @@ +<?xml version="1.0"?> +<syncmember version="1.0"> + <pluginname>mock-sync</pluginname> + <objtype> + <name>mockobjtype1</name> + <enabled>1</enabled> + <read>1</read> + <getchanges>1</getchanges> + <write>1</write> + <objformat> + <name>mockformat1a</name> + <config/> + </objformat> + </objtype> +</syncmember> Added: trunk/tests/data/multisync_multiformats/configs/group/3/mock-sync.conf ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ trunk/tests/data/multisync_multiformats/configs/group/3/mock-sync.conf Wed Feb 10 22:53:13 2010 (r6034) @@ -0,0 +1,15 @@ +<?xml version="1.0"?> +<config version="1.0"> + <Resources> + <Resource> + <Enabled>1</Enabled> + <Formats> + <Format> + <Name>mockformat1a</Name> + </Format> + </Formats> + <ObjType>mockobjtype1</ObjType> + <Path>data3</Path> + </Resource> + </Resources> +</config> Added: trunk/tests/data/multisync_multiformats/configs/group/3/syncmember.conf ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ trunk/tests/data/multisync_multiformats/configs/group/3/syncmember.conf Wed Feb 10 22:53:13 2010 (r6034) @@ -0,0 +1,15 @@ +<?xml version="1.0"?> +<syncmember version="1.0"> + <pluginname>mock-sync</pluginname> + <objtype> + <name>mockobjtype1</name> + <enabled>1</enabled> + <read>1</read> + <getchanges>1</getchanges> + <write>1</write> + <objformat> + <name>mockformat1a</name> + <config /> + </objformat> + </objtype> +</syncmember> Added: trunk/tests/data/multisync_multiformats/configs/group/4/mock-sync.conf ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ trunk/tests/data/multisync_multiformats/configs/group/4/mock-sync.conf Wed Feb 10 22:53:13 2010 (r6034) @@ -0,0 +1,15 @@ +<?xml version="1.0"?> +<config version="1.0"> + <Resources> + <Resource> + <Enabled>1</Enabled> + <Formats> + <Format> + <Name>mockformat1</Name> + </Format> + </Formats> + <ObjType>mockobjtype1</ObjType> + <Path>data4</Path> + </Resource> + </Resources> +</config> Added: trunk/tests/data/multisync_multiformats/configs/group/4/syncmember.conf ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ trunk/tests/data/multisync_multiformats/configs/group/4/syncmember.conf Wed Feb 10 22:53:13 2010 (r6034) @@ -0,0 +1,15 @@ +<?xml version="1.0"?> +<syncmember version="1.0"> + <pluginname>mock-sync</pluginname> + <objtype> + <name>mockobjtype1</name> + <enabled>1</enabled> + <read>1</read> + <getchanges>1</getchanges> + <write>1</write> + <objformat> + <name>mockformat1</name> + <config/> + </objformat> + </objtype> +</syncmember> Added: trunk/tests/data/multisync_multiformats/configs/group/syncgroup.conf ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ trunk/tests/data/multisync_multiformats/configs/group/syncgroup.conf Wed Feb 10 22:53:13 2010 (r6034) @@ -0,0 +1,2 @@ +<?xml version="1.0"?> +<syncgroup><groupname>test</groupname></syncgroup> Added: trunk/tests/data/multisync_multiformats/data1/testdata ============================================================================== Binary file. No diff available. Added: trunk/tests/data/multisync_multiformats/data1/testdata_to_sync ============================================================================== Binary file. No diff available. Added: trunk/tests/data/multisync_multiformats/data2/testdata ============================================================================== Binary file. No diff available. Added: trunk/tests/data/multisync_multiformats/data3/testdata ============================================================================== Binary file. No diff available. Modified: trunk/tests/mock-plugin/mock_format.c ============================================================================== --- trunk/tests/mock-plugin/mock_format.c Sun Feb 7 22:41:32 2010 (r6033) +++ trunk/tests/mock-plugin/mock_format.c Wed Feb 10 22:53:13 2010 (r6034) @@ -102,7 +102,7 @@ osync_assert(file); file->path = osync_rand_str(g_random_int_range(1, 100), error); - osync_assert(error == NULL); + osync_assert(*error == NULL); file->data = input; file->size = inpsize - 1; @@ -112,6 +112,56 @@ return TRUE; } +static osync_bool conv_mockformat1a_to_mockformat1(char *input, unsigned int inpsize, char **output, unsigned int *outpsize, osync_bool *free_input, const char *config, void *userdata, OSyncError **error) +{ + osync_trace(TRACE_INTERNAL, "Converting fileA to file"); + + *free_input = FALSE; + OSyncFileFormat *fileA = (OSyncFileFormat *)input; + OSyncFileFormat *file = osync_try_malloc0(sizeof(OSyncFileFormat), error); + osync_assert(file); + + char *filedata = osync_try_malloc0(fileA->size - 2, error); + memcpy(filedata, fileA->data, fileA->size - 2); + + file->path = fileA->path; + osync_assert(*error == NULL); + + file->data = filedata; + file->size = fileA->size - 2; + + *output = (char *)file; + *outpsize = sizeof(OSyncFileFormat); + return TRUE; +} + +static osync_bool conv_mockformat1_to_mockformat1a(char *input, unsigned int inpsize, char **output, unsigned int *outpsize, osync_bool *free_input, const char *config, void *userdata, OSyncError **error) +{ + osync_trace(TRACE_INTERNAL, "Converting file to fileA"); + + *free_input = FALSE; + char *identifier = " "; + + OSyncFileFormat *file = (OSyncFileFormat *)input; + OSyncFileFormat *fileA = osync_try_malloc0(sizeof(OSyncFileFormat), error); + osync_assert(fileA); + + char *filedata = osync_try_malloc0(file->size + 2, error); + memcpy(filedata, file->data, file->size); + memcpy(filedata + file->size, identifier , 2); + + fileA->path = file->path; + osync_assert(*error == NULL); + + fileA->data = filedata; + fileA->size = file->size + 2; + + *output = (char *)fileA; + *outpsize = sizeof(OSyncFileFormat); + + return TRUE; +} + static osync_bool destroy_file(char *input, unsigned int inpsize, void *user_data, OSyncError **error) { OSyncFileFormat *file = (OSyncFileFormat *)input; @@ -211,7 +261,7 @@ osync_trace(TRACE_ENTRY, "%s(%p, %i, %p, %p)", __func__, input, inpsize, marshal, error); OSyncFileFormat *file = (OSyncFileFormat *)input; - + if (!osync_marshal_write_string(marshal, file->path, error)) goto error; if (!osync_marshal_write_buffer(marshal, file->data, file->size, error)) @@ -296,6 +346,15 @@ osync_assert(osync_format_env_register_objformat(env, format, error)); osync_objformat_unref(format); + /* mockformat1a */ + format = osync_objformat_new("mockformat1a", "mockobjtype1", error); + osync_assert(format); + + _format_set_functions(format); + + osync_assert(osync_format_env_register_objformat(env, format, error)); + osync_objformat_unref(format); + return TRUE; } @@ -310,6 +369,9 @@ OSyncObjFormat *mockformat2 = osync_format_env_find_objformat(env, "mockformat2"); osync_assert(mockformat2); + OSyncObjFormat *mockformat1a = osync_format_env_find_objformat(env, "mockformat1a"); + osync_assert(mockformat1a); + conv = osync_converter_new(OSYNC_CONVERTER_ENCAP, mockformat1, mockformat2, conv_mockformat1_to_mockformat2, error); osync_assert(conv); @@ -322,6 +384,17 @@ osync_format_env_register_converter(env, conv, error); osync_converter_unref(conv); + conv = osync_converter_new(OSYNC_CONVERTER_ENCAP, mockformat1, mockformat1a, conv_mockformat1_to_mockformat1a, error); + osync_assert(conv); + + osync_format_env_register_converter(env, conv, error); + osync_converter_unref(conv); + + conv = osync_converter_new(OSYNC_CONVERTER_DECAP, mockformat1a, mockformat1, conv_mockformat1a_to_mockformat1, error); + osync_assert(conv); + + osync_format_env_register_converter(env, conv, error); + osync_converter_unref(conv); return TRUE; } Modified: trunk/tests/sync-tests/check_multisync.c ============================================================================== --- trunk/tests/sync-tests/check_multisync.c Sun Feb 7 22:41:32 2010 (r6033) +++ trunk/tests/sync-tests/check_multisync.c Wed Feb 10 22:53:13 2010 (r6034) @@ -471,6 +471,47 @@ osync_engine_unref(engine); } +/* Synchronize slow sync with two same data . +It ends up with two entry_engines pointing to the same change. +Which could lead to double conversion of the change pointed to. +This also lead to wrong conversion path cached if this shared change +appears first. This is the latter that I use to detect the bug. +*/ +START_TEST (multisync_easy_same) +{ + char *testbed = setup_testbed("multisync_multiformats"); + OSyncError *error = NULL; + OSyncEngine *engine = setup_engine(testbed); + fail_unless(osync_engine_initialize(engine, &error), NULL); + fail_unless(error == NULL, NULL); + + osync_testing_system_abort("cp data1/testdata data4/"); + + mark_point(); + + synchronize_once(engine, NULL); + + fail_unless(num_change_read == 5, NULL); + fail_unless(num_change_written == 3, NULL); + fail_unless(num_change_error == 0, NULL); + + fail_unless(num_mapping_conflicts == 0, NULL); + + fail_unless(num_engine_connected == 1, NULL); + fail_unless(num_engine_read == 1, NULL); + fail_unless(num_engine_written == 1, NULL); + fail_unless(num_engine_disconnected == 1, NULL); + fail_unless(num_engine_end_conflicts = 1, NULL); + + fail_unless(osync_testing_diff("data1", "data4")); + fail_unless(osync_testing_diff("data2", "data3")); + + destroy_engine(engine); + + destroy_testbed(testbed); +} +END_TEST + /* Sync the single item testdata from data 1 to data2 and data3 * then change testdata in data3 */ START_TEST (multisync_easy_mod) @@ -1968,6 +2009,8 @@ OSYNC_TESTCASE_ADD(multisync_dual_new) OSYNC_TESTCASE_ADD(multisync_triple_new) +OSYNC_TESTCASE_ADD(multisync_easy_same) + OSYNC_TESTCASE_ADD(multisync_easy_mod) OSYNC_TESTCASE_ADD(multisync_dual_mod) OSYNC_TESTCASE_ADD(multisync_triple_mod) |