test_ds.cpp 77 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140
  1. // This file is part of OpenCV project.
  2. // It is subject to the license terms in the LICENSE file found in the top-level directory
  3. // of this distribution and at http://opencv.org/license.html.
  4. #include "test_precomp.hpp"
  5. namespace opencv_test { namespace {
  6. typedef struct CvTsSimpleSeq
  7. {
  8. schar* array;
  9. int count;
  10. int max_count;
  11. int elem_size;
  12. } CvTsSimpleSeq;
  13. static CvTsSimpleSeq* cvTsCreateSimpleSeq( int max_count, int elem_size )
  14. {
  15. CvTsSimpleSeq* seq = (CvTsSimpleSeq*)cvAlloc( sizeof(*seq) + max_count * elem_size );
  16. seq->elem_size = elem_size;
  17. seq->max_count = max_count;
  18. seq->count = 0;
  19. seq->array = (schar*)(seq + 1);
  20. return seq;
  21. }
  22. static void cvTsReleaseSimpleSeq( CvTsSimpleSeq** seq )
  23. {
  24. cvFree( seq );
  25. }
  26. static schar* cvTsSimpleSeqElem( CvTsSimpleSeq* seq, int index )
  27. {
  28. CV_Assert( 0 <= index && index < seq->count );
  29. return seq->array + index * seq->elem_size;
  30. }
  31. static void cvTsClearSimpleSeq( CvTsSimpleSeq* seq )
  32. {
  33. seq->count = 0;
  34. }
  35. static void cvTsSimpleSeqShiftAndCopy( CvTsSimpleSeq* seq, int from_idx, int to_idx, void* elem=0 )
  36. {
  37. int elem_size = seq->elem_size;
  38. if( from_idx == to_idx )
  39. return;
  40. if (elem)
  41. CV_Assert(from_idx < to_idx);
  42. else
  43. CV_Assert(from_idx > to_idx);
  44. if( from_idx < seq->count )
  45. {
  46. memmove( seq->array + to_idx*elem_size, seq->array + from_idx*elem_size,
  47. (seq->count - from_idx)*elem_size );
  48. }
  49. seq->count += to_idx - from_idx;
  50. if( elem )
  51. memcpy( seq->array + from_idx*elem_size, elem, (to_idx - from_idx)*elem_size );
  52. }
  53. static void cvTsSimpleSeqInvert( CvTsSimpleSeq* seq )
  54. {
  55. int i, k, len = seq->count, elem_size = seq->elem_size;
  56. schar *data = seq->array, t;
  57. for( i = 0; i < len/2; i++ )
  58. {
  59. schar* a = data + i*elem_size;
  60. schar* b = data + (len - i - 1)*elem_size;
  61. for( k = 0; k < elem_size; k++ )
  62. CV_SWAP( a[k], b[k], t );
  63. }
  64. }
  65. /****************************************************************************************\
  66. * simple cvset implementation *
  67. \****************************************************************************************/
  68. typedef struct CvTsSimpleSet
  69. {
  70. schar* array;
  71. int count, max_count;
  72. int elem_size;
  73. int* free_stack;
  74. int free_count;
  75. } CvTsSimpleSet;
  76. static void cvTsClearSimpleSet( CvTsSimpleSet* set_header )
  77. {
  78. int i;
  79. int elem_size = set_header->elem_size;
  80. for( i = 0; i < set_header->max_count; i++ )
  81. {
  82. set_header->array[i*elem_size] = 0;
  83. set_header->free_stack[i] = set_header->max_count - i - 1;
  84. }
  85. set_header->free_count = set_header->max_count;
  86. set_header->count = 0;
  87. }
  88. static CvTsSimpleSet* cvTsCreateSimpleSet( int max_count, int elem_size )
  89. {
  90. CvTsSimpleSet* set_header = (CvTsSimpleSet*)cvAlloc( sizeof(*set_header) + max_count *
  91. (elem_size + 1 + sizeof(int)));
  92. set_header->elem_size = elem_size + 1;
  93. set_header->max_count = max_count;
  94. set_header->free_stack = (int*)(set_header + 1);
  95. set_header->array = (schar*)(set_header->free_stack + max_count);
  96. cvTsClearSimpleSet( set_header );
  97. return set_header;
  98. }
  99. static void cvTsReleaseSimpleSet( CvTsSimpleSet** set_header )
  100. {
  101. cvFree( set_header );
  102. }
  103. static schar* cvTsSimpleSetFind( CvTsSimpleSet* set_header, int index )
  104. {
  105. int idx = index * set_header->elem_size;
  106. CV_Assert( 0 <= index && index < set_header->max_count );
  107. return set_header->array[idx] ? set_header->array + idx + 1 : 0;
  108. }
  109. static int cvTsSimpleSetAdd( CvTsSimpleSet* set_header, void* elem )
  110. {
  111. int idx, idx2;
  112. CV_Assert( set_header->free_count > 0 );
  113. idx = set_header->free_stack[--set_header->free_count];
  114. idx2 = idx * set_header->elem_size;
  115. CV_Assert( set_header->array[idx2] == 0 );
  116. set_header->array[idx2] = 1;
  117. if( set_header->elem_size > 1 )
  118. memcpy( set_header->array + idx2 + 1, elem, set_header->elem_size - 1 );
  119. set_header->count = MAX( set_header->count, idx + 1 );
  120. return idx;
  121. }
  122. static void cvTsSimpleSetRemove( CvTsSimpleSet* set_header, int index )
  123. {
  124. CV_Assert( set_header->free_count < set_header->max_count &&
  125. 0 <= index && index < set_header->max_count );
  126. CV_Assert( set_header->array[index * set_header->elem_size] == 1 );
  127. set_header->free_stack[set_header->free_count++] = index;
  128. set_header->array[index * set_header->elem_size] = 0;
  129. }
  130. /****************************************************************************************\
  131. * simple graph implementation *
  132. \****************************************************************************************/
  133. typedef struct CvTsSimpleGraph
  134. {
  135. char* matrix;
  136. int edge_size;
  137. int oriented;
  138. CvTsSimpleSet* vtx;
  139. } CvTsSimpleGraph;
  140. static void cvTsClearSimpleGraph( CvTsSimpleGraph* graph )
  141. {
  142. int max_vtx_count = graph->vtx->max_count;
  143. cvTsClearSimpleSet( graph->vtx );
  144. memset( graph->matrix, 0, max_vtx_count * max_vtx_count * graph->edge_size );
  145. }
  146. static CvTsSimpleGraph* cvTsCreateSimpleGraph( int max_vtx_count, int vtx_size,
  147. int edge_size, int oriented )
  148. {
  149. CvTsSimpleGraph* graph;
  150. CV_Assert( max_vtx_count > 1 && vtx_size >= 0 && edge_size >= 0 );
  151. graph = (CvTsSimpleGraph*)cvAlloc( sizeof(*graph) +
  152. max_vtx_count * max_vtx_count * (edge_size + 1));
  153. graph->vtx = cvTsCreateSimpleSet( max_vtx_count, vtx_size );
  154. graph->edge_size = edge_size + 1;
  155. graph->matrix = (char*)(graph + 1);
  156. graph->oriented = oriented;
  157. cvTsClearSimpleGraph( graph );
  158. return graph;
  159. }
  160. static void cvTsReleaseSimpleGraph( CvTsSimpleGraph** graph )
  161. {
  162. if( *graph )
  163. {
  164. cvTsReleaseSimpleSet( &(graph[0]->vtx) );
  165. cvFree( graph );
  166. }
  167. }
  168. static int cvTsSimpleGraphAddVertex( CvTsSimpleGraph* graph, void* vertex )
  169. {
  170. return cvTsSimpleSetAdd( graph->vtx, vertex );
  171. }
  172. static void cvTsSimpleGraphRemoveVertex( CvTsSimpleGraph* graph, int index )
  173. {
  174. int i, max_vtx_count = graph->vtx->max_count;
  175. int edge_size = graph->edge_size;
  176. cvTsSimpleSetRemove( graph->vtx, index );
  177. /* remove all the corresponding edges */
  178. for( i = 0; i < max_vtx_count; i++ )
  179. {
  180. graph->matrix[(i*max_vtx_count + index)*edge_size] =
  181. graph->matrix[(index*max_vtx_count + i)*edge_size] = 0;
  182. }
  183. }
  184. static void cvTsSimpleGraphAddEdge( CvTsSimpleGraph* graph, int idx1, int idx2, void* edge )
  185. {
  186. int i, t, n = graph->oriented ? 1 : 2;
  187. CV_Assert( cvTsSimpleSetFind( graph->vtx, idx1 ) &&
  188. cvTsSimpleSetFind( graph->vtx, idx2 ));
  189. for( i = 0; i < n; i++ )
  190. {
  191. int ofs = (idx1*graph->vtx->max_count + idx2)*graph->edge_size;
  192. CV_Assert( graph->matrix[ofs] == 0 );
  193. graph->matrix[ofs] = 1;
  194. if( graph->edge_size > 1 )
  195. memcpy( graph->matrix + ofs + 1, edge, graph->edge_size - 1 );
  196. CV_SWAP( idx1, idx2, t );
  197. }
  198. }
  199. static void cvTsSimpleGraphRemoveEdge( CvTsSimpleGraph* graph, int idx1, int idx2 )
  200. {
  201. int i, t, n = graph->oriented ? 1 : 2;
  202. CV_Assert( cvTsSimpleSetFind( graph->vtx, idx1 ) &&
  203. cvTsSimpleSetFind( graph->vtx, idx2 ));
  204. for( i = 0; i < n; i++ )
  205. {
  206. int ofs = (idx1*graph->vtx->max_count + idx2)*graph->edge_size;
  207. CV_Assert( graph->matrix[ofs] == 1 );
  208. graph->matrix[ofs] = 0;
  209. CV_SWAP( idx1, idx2, t );
  210. }
  211. }
  212. static schar* cvTsSimpleGraphFindVertex( CvTsSimpleGraph* graph, int index )
  213. {
  214. return cvTsSimpleSetFind( graph->vtx, index );
  215. }
  216. static char* cvTsSimpleGraphFindEdge( CvTsSimpleGraph* graph, int idx1, int idx2 )
  217. {
  218. if( cvTsSimpleGraphFindVertex( graph, idx1 ) &&
  219. cvTsSimpleGraphFindVertex( graph, idx2 ))
  220. {
  221. char* edge = graph->matrix + (idx1 * graph->vtx->max_count + idx2)*graph->edge_size;
  222. if( edge[0] ) return edge + 1;
  223. }
  224. return 0;
  225. }
  226. static int cvTsSimpleGraphVertexDegree( CvTsSimpleGraph* graph, int index )
  227. {
  228. int i, count = 0;
  229. int edge_size = graph->edge_size;
  230. int max_vtx_count = graph->vtx->max_count;
  231. CV_Assert( cvTsSimpleGraphFindVertex( graph, index ) != 0 );
  232. for( i = 0; i < max_vtx_count; i++ )
  233. {
  234. count += graph->matrix[(i*max_vtx_count + index)*edge_size] +
  235. graph->matrix[(index*max_vtx_count + i)*edge_size];
  236. }
  237. if( !graph->oriented )
  238. {
  239. CV_Assert( count % 2 == 0 );
  240. count /= 2;
  241. }
  242. return count;
  243. }
  244. ///////////////////////////////////// the tests //////////////////////////////////
  245. #define CV_TS_SEQ_CHECK_CONDITION( expr, err_msg ) \
  246. if( !(expr) ) \
  247. { \
  248. set_error_context( #expr, err_msg, __FILE__, __LINE__ ); \
  249. ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );\
  250. throw -1; \
  251. }
  252. class Core_DynStructBaseTest : public cvtest::BaseTest
  253. {
  254. public:
  255. Core_DynStructBaseTest();
  256. virtual ~Core_DynStructBaseTest();
  257. bool can_do_fast_forward();
  258. void clear();
  259. protected:
  260. int read_params( const cv::FileStorage& fs );
  261. void run_func(void);
  262. void set_error_context( const char* condition,
  263. const char* err_msg,
  264. const char* file, int line );
  265. int test_seq_block_consistence( int _struct_idx, CvSeq* seq, int total );
  266. void update_progressbar();
  267. int struct_count, max_struct_size, iterations, generations;
  268. int min_log_storage_block_size, max_log_storage_block_size;
  269. int min_log_elem_size, max_log_elem_size;
  270. int gen, struct_idx, iter;
  271. int test_progress;
  272. int64 start_time;
  273. double cpu_freq;
  274. vector<void*> cxcore_struct;
  275. vector<void*> simple_struct;
  276. Ptr<CvMemStorage> storage;
  277. };
  278. Core_DynStructBaseTest::Core_DynStructBaseTest()
  279. {
  280. struct_count = 2;
  281. max_struct_size = 2000;
  282. min_log_storage_block_size = 7;
  283. max_log_storage_block_size = 12;
  284. min_log_elem_size = 0;
  285. max_log_elem_size = 8;
  286. generations = 10;
  287. iterations = max_struct_size*2;
  288. gen = struct_idx = iter = -1;
  289. test_progress = -1;
  290. }
  291. Core_DynStructBaseTest::~Core_DynStructBaseTest()
  292. {
  293. clear();
  294. }
  295. void Core_DynStructBaseTest::run_func()
  296. {
  297. }
  298. bool Core_DynStructBaseTest::can_do_fast_forward()
  299. {
  300. return false;
  301. }
  302. void Core_DynStructBaseTest::clear()
  303. {
  304. cvtest::BaseTest::clear();
  305. }
  306. int Core_DynStructBaseTest::read_params( const cv::FileStorage& fs )
  307. {
  308. int code = cvtest::BaseTest::read_params( fs );
  309. double sqrt_scale = sqrt(ts->get_test_case_count_scale());
  310. if( code < 0 )
  311. return code;
  312. read( find_param( fs, "struct_count" ), struct_count, struct_count );
  313. read( find_param( fs, "max_struct_size" ), max_struct_size, max_struct_size );
  314. read( find_param( fs, "generations" ), generations, generations );
  315. read( find_param( fs, "iterations" ), iterations, iterations );
  316. generations = cvRound(generations*sqrt_scale);
  317. iterations = cvRound(iterations*sqrt_scale);
  318. read( find_param( fs, "min_log_storage_block_size" ),
  319. min_log_storage_block_size, min_log_storage_block_size );
  320. read( find_param( fs, "max_log_storage_block_size" ),
  321. max_log_storage_block_size, max_log_storage_block_size );
  322. read( find_param( fs, "min_log_elem_size" ), min_log_elem_size, min_log_elem_size );
  323. read( find_param( fs, "max_log_elem_size" ), max_log_elem_size, max_log_elem_size );
  324. struct_count = cvtest::clipInt( struct_count, 1, 100 );
  325. max_struct_size = cvtest::clipInt( max_struct_size, 1, 1<<20 );
  326. generations = cvtest::clipInt( generations, 1, 100 );
  327. iterations = cvtest::clipInt( iterations, 100, 1<<20 );
  328. min_log_storage_block_size = cvtest::clipInt( min_log_storage_block_size, 7, 20 );
  329. max_log_storage_block_size = cvtest::clipInt( max_log_storage_block_size,
  330. min_log_storage_block_size, 20 );
  331. min_log_elem_size = cvtest::clipInt( min_log_elem_size, 0, 8 );
  332. max_log_elem_size = cvtest::clipInt( max_log_elem_size, min_log_elem_size, 10 );
  333. return 0;
  334. }
  335. void Core_DynStructBaseTest::update_progressbar()
  336. {
  337. int64 t;
  338. if( test_progress < 0 )
  339. {
  340. test_progress = 0;
  341. cpu_freq = cv::getTickFrequency();
  342. start_time = cv::getTickCount();
  343. }
  344. t = cv::getTickCount();
  345. test_progress = update_progress( test_progress, 0, 0, (double)(t - start_time)/cpu_freq );
  346. }
  347. void Core_DynStructBaseTest::set_error_context( const char* condition,
  348. const char* err_msg,
  349. const char* filename, int lineno )
  350. {
  351. ts->printf( cvtest::TS::LOG, "file %s, line %d: %s\n(\"%s\" failed).\n"
  352. "generation = %d, struct_idx = %d, iter = %d\n",
  353. filename, lineno, err_msg, condition, gen, struct_idx, iter );
  354. ts->set_failed_test_info( cvtest::TS::FAIL_INVALID_OUTPUT );
  355. }
  356. int Core_DynStructBaseTest::test_seq_block_consistence( int _struct_idx, CvSeq* seq, int total )
  357. {
  358. int sum = 0;
  359. struct_idx = _struct_idx;
  360. CV_TS_SEQ_CHECK_CONDITION( seq != 0, "Null sequence pointer" );
  361. if( seq->first )
  362. {
  363. CvSeqBlock* block = seq->first;
  364. CvSeqBlock* prev_block = block->prev;
  365. int delta_idx = seq->first->start_index;
  366. for( ;; )
  367. {
  368. CV_TS_SEQ_CHECK_CONDITION( sum == block->start_index - delta_idx &&
  369. block->count > 0 && block->prev == prev_block &&
  370. prev_block->next == block,
  371. "sequence blocks are inconsistent" );
  372. sum += block->count;
  373. prev_block = block;
  374. block = block->next;
  375. if( block == seq->first ) break;
  376. }
  377. CV_TS_SEQ_CHECK_CONDITION( block->prev->count * seq->elem_size +
  378. block->prev->data <= seq->block_max,
  379. "block->data or block_max pointer are incorrect" );
  380. }
  381. CV_TS_SEQ_CHECK_CONDITION( seq->total == sum && sum == total,
  382. "total number of elements is incorrect" );
  383. return 0;
  384. }
  385. /////////////////////////////////// sequence tests ////////////////////////////////////
  386. class Core_SeqBaseTest : public Core_DynStructBaseTest
  387. {
  388. public:
  389. Core_SeqBaseTest();
  390. virtual ~Core_SeqBaseTest();
  391. void clear();
  392. void run( int );
  393. protected:
  394. int test_multi_create();
  395. int test_get_seq_elem( int _struct_idx, int iters );
  396. int test_get_seq_reading( int _struct_idx, int iters );
  397. int test_seq_ops( int iters );
  398. };
  399. Core_SeqBaseTest::Core_SeqBaseTest()
  400. {
  401. }
  402. Core_SeqBaseTest::~Core_SeqBaseTest()
  403. {
  404. clear();
  405. }
  406. void Core_SeqBaseTest::clear()
  407. {
  408. for( size_t i = 0; i < simple_struct.size(); i++ )
  409. cvTsReleaseSimpleSeq( (CvTsSimpleSeq**)&simple_struct[i] );
  410. Core_DynStructBaseTest::clear();
  411. }
  412. int Core_SeqBaseTest::test_multi_create()
  413. {
  414. vector<CvSeqWriter> writer(struct_count);
  415. vector<int> pos(struct_count);
  416. vector<int> index(struct_count);
  417. int cur_count, elem_size;
  418. RNG& rng = ts->get_rng();
  419. for( int i = 0; i < struct_count; i++ )
  420. {
  421. double t;
  422. CvTsSimpleSeq* sseq;
  423. pos[i] = -1;
  424. index[i] = i;
  425. t = cvtest::randReal(rng)*(max_log_elem_size - min_log_elem_size) + min_log_elem_size;
  426. elem_size = cvRound( exp(t * CV_LOG2) );
  427. elem_size = MIN( elem_size, (int)(storage->block_size - sizeof(void*) -
  428. sizeof(CvSeqBlock) - sizeof(CvMemBlock)) );
  429. cvTsReleaseSimpleSeq( (CvTsSimpleSeq**)&simple_struct[i] );
  430. simple_struct[i] = sseq = cvTsCreateSimpleSeq( max_struct_size, elem_size );
  431. cxcore_struct[i] = 0;
  432. sseq->count = cvtest::randInt( rng ) % max_struct_size;
  433. Mat m( 1, MAX(sseq->count,1)*elem_size, CV_8UC1, sseq->array );
  434. cvtest::randUni( rng, m, Scalar::all(0), Scalar::all(256) );
  435. }
  436. for( cur_count = struct_count; cur_count > 0; cur_count-- )
  437. {
  438. for(;;)
  439. {
  440. int k = cvtest::randInt( rng ) % cur_count;
  441. struct_idx = index[k];
  442. CvTsSimpleSeq* sseq = (CvTsSimpleSeq*)simple_struct[struct_idx];
  443. if( pos[struct_idx] < 0 )
  444. {
  445. int hdr_size = (cvtest::randInt(rng) % 10)*4 + sizeof(CvSeq);
  446. hdr_size = MIN( hdr_size, (int)(storage->block_size - sizeof(CvMemBlock)) );
  447. elem_size = sseq->elem_size;
  448. if( cvtest::randInt(rng) % 2 )
  449. {
  450. cvStartWriteSeq( 0, hdr_size, elem_size, storage, &writer[struct_idx] );
  451. }
  452. else
  453. {
  454. CvSeq* s;
  455. s = cvCreateSeq( 0, hdr_size, elem_size, storage );
  456. cvStartAppendToSeq( s, &writer[struct_idx] );
  457. }
  458. cvSetSeqBlockSize( writer[struct_idx].seq, cvtest::randInt( rng ) % 10000 );
  459. pos[struct_idx] = 0;
  460. }
  461. update_progressbar();
  462. if( pos[struct_idx] == sseq->count )
  463. {
  464. cxcore_struct[struct_idx] = cvEndWriteSeq( &writer[struct_idx] );
  465. /* del index */
  466. for( ; k < cur_count-1; k++ )
  467. index[k] = index[k+1];
  468. break;
  469. }
  470. {
  471. schar* el = cvTsSimpleSeqElem( sseq, pos[struct_idx] );
  472. CV_WRITE_SEQ_ELEM_VAR( el, writer[struct_idx] );
  473. }
  474. pos[struct_idx]++;
  475. }
  476. }
  477. return 0;
  478. }
  479. int Core_SeqBaseTest::test_get_seq_elem( int _struct_idx, int iters )
  480. {
  481. RNG& rng = ts->get_rng();
  482. CvSeq* seq = (CvSeq*)cxcore_struct[_struct_idx];
  483. CvTsSimpleSeq* sseq = (CvTsSimpleSeq*)simple_struct[_struct_idx];
  484. struct_idx = _struct_idx;
  485. CV_Assert( seq->total == sseq->count );
  486. if( sseq->count == 0 )
  487. return 0;
  488. for( int i = 0; i < iters; i++ )
  489. {
  490. int idx = cvtest::randInt(rng) % (sseq->count*3) - sseq->count*3/2;
  491. int idx0 = (unsigned)idx < (unsigned)(sseq->count) ? idx : idx < 0 ?
  492. idx + sseq->count : idx - sseq->count;
  493. int bad_range = (unsigned)idx0 >= (unsigned)(sseq->count);
  494. schar* elem;
  495. elem = cvGetSeqElem( seq, idx );
  496. if( bad_range )
  497. {
  498. CV_TS_SEQ_CHECK_CONDITION( elem == 0,
  499. "cvGetSeqElem doesn't "
  500. "handle \"out of range\" properly" );
  501. }
  502. else
  503. {
  504. CV_TS_SEQ_CHECK_CONDITION( elem != 0 &&
  505. !memcmp( elem, cvTsSimpleSeqElem(sseq, idx0), sseq->elem_size ),
  506. "cvGetSeqElem returns wrong element" );
  507. idx = cvSeqElemIdx(seq, elem );
  508. CV_TS_SEQ_CHECK_CONDITION( idx >= 0 && idx == idx0,
  509. "cvSeqElemIdx is incorrect" );
  510. }
  511. }
  512. return 0;
  513. }
  514. int Core_SeqBaseTest::test_get_seq_reading( int _struct_idx, int iters )
  515. {
  516. const int max_val = 3*5 + 2;
  517. CvSeq* seq = (CvSeq*)cxcore_struct[_struct_idx];
  518. CvTsSimpleSeq* sseq = (CvTsSimpleSeq*)simple_struct[_struct_idx];
  519. int total = seq->total;
  520. RNG& rng = ts->get_rng();
  521. CvSeqReader reader;
  522. vector<schar> _elem(sseq->elem_size);
  523. schar* elem = &_elem[0];
  524. CV_Assert( total == sseq->count );
  525. this->struct_idx = _struct_idx;
  526. int pos = cvtest::randInt(rng) % 2;
  527. cvStartReadSeq( seq, &reader, pos );
  528. if( total == 0 )
  529. {
  530. CV_TS_SEQ_CHECK_CONDITION( reader.ptr == 0, "Empty sequence reader pointer is not NULL" );
  531. return 0;
  532. }
  533. pos = pos ? seq->total - 1 : 0;
  534. CV_TS_SEQ_CHECK_CONDITION( pos == cvGetSeqReaderPos(&reader),
  535. "initial reader position is wrong" );
  536. for( iter = 0; iter < iters; iter++ )
  537. {
  538. int op = cvtest::randInt(rng) % max_val;
  539. if( op >= max_val - 2 )
  540. {
  541. int new_pos, new_pos0;
  542. int bad_range;
  543. int is_relative = op == max_val - 1;
  544. new_pos = cvtest::randInt(rng) % (total*2) - total;
  545. new_pos0 = new_pos + (is_relative ? pos : 0 );
  546. if( new_pos0 < 0 ) new_pos0 += total;
  547. if( new_pos0 >= total ) new_pos0 -= total;
  548. bad_range = (unsigned)new_pos0 >= (unsigned)total;
  549. cvSetSeqReaderPos( &reader, new_pos, is_relative );
  550. if( !bad_range )
  551. {
  552. CV_TS_SEQ_CHECK_CONDITION( new_pos0 == cvGetSeqReaderPos( &reader ),
  553. "cvset reader position doesn't work" );
  554. pos = new_pos0;
  555. }
  556. else
  557. {
  558. CV_TS_SEQ_CHECK_CONDITION( pos == cvGetSeqReaderPos( &reader ),
  559. "reader doesn't stay at the current position after wrong positioning" );
  560. }
  561. }
  562. else
  563. {
  564. int direction = (op % 3) - 1;
  565. memcpy( elem, reader.ptr, sseq->elem_size );
  566. if( direction > 0 )
  567. {
  568. CV_NEXT_SEQ_ELEM( sseq->elem_size, reader );
  569. }
  570. else if( direction < 0 )
  571. {
  572. CV_PREV_SEQ_ELEM( sseq->elem_size, reader );
  573. }
  574. CV_TS_SEQ_CHECK_CONDITION( memcmp(elem, cvTsSimpleSeqElem(sseq, pos),
  575. sseq->elem_size) == 0, "reading is incorrect" );
  576. pos += direction;
  577. if( -pos > 0 ) pos += total;
  578. if( pos >= total ) pos -= total;
  579. CV_TS_SEQ_CHECK_CONDITION( pos == cvGetSeqReaderPos( &reader ),
  580. "reader doesn't move correctly after reading" );
  581. }
  582. }
  583. return 0;
  584. }
  585. int Core_SeqBaseTest::test_seq_ops( int iters )
  586. {
  587. const int max_op = 14;
  588. int max_elem_size = 0;
  589. schar* elem2 = 0;
  590. RNG& rng = ts->get_rng();
  591. for( int i = 0; i < struct_count; i++ )
  592. max_elem_size = MAX( max_elem_size, ((CvSeq*)cxcore_struct[i])->elem_size );
  593. vector<schar> elem_buf(max_struct_size*max_elem_size);
  594. schar* elem = (schar*)&elem_buf[0];
  595. Mat elem_mat;
  596. for( iter = 0; iter < iters; iter++ )
  597. {
  598. struct_idx = cvtest::randInt(rng) % struct_count;
  599. int op = cvtest::randInt(rng) % max_op;
  600. CvSeq* seq = (CvSeq*)cxcore_struct[struct_idx];
  601. CvTsSimpleSeq* sseq = (CvTsSimpleSeq*)simple_struct[struct_idx];
  602. int elem_size = sseq->elem_size;
  603. int whence = 0, pos = 0, count = 0;
  604. switch( op )
  605. {
  606. case 0:
  607. case 1:
  608. case 2: // push/pushfront/insert
  609. if( sseq->count == sseq->max_count )
  610. break;
  611. elem_mat = Mat(1, elem_size, CV_8U, elem);
  612. cvtest::randUni( rng, elem_mat, cvScalarAll(0), cvScalarAll(255) );
  613. whence = op - 1;
  614. if( whence < 0 )
  615. {
  616. pos = 0;
  617. cvSeqPushFront( seq, elem );
  618. }
  619. else if( whence > 0 )
  620. {
  621. pos = sseq->count;
  622. cvSeqPush( seq, elem );
  623. }
  624. else
  625. {
  626. pos = cvtest::randInt(rng) % (sseq->count + 1);
  627. cvSeqInsert( seq, pos, elem );
  628. }
  629. cvTsSimpleSeqShiftAndCopy( sseq, pos, pos + 1, elem );
  630. elem2 = cvGetSeqElem( seq, pos );
  631. CV_TS_SEQ_CHECK_CONDITION( elem2 != 0, "The inserted element could not be retrieved" );
  632. CV_TS_SEQ_CHECK_CONDITION( seq->total == sseq->count &&
  633. memcmp(elem2, cvTsSimpleSeqElem(sseq,pos), elem_size) == 0,
  634. "The inserted sequence element is wrong" );
  635. break;
  636. case 3:
  637. case 4:
  638. case 5: // pop/popfront/remove
  639. if( sseq->count == 0 )
  640. break;
  641. whence = op - 4;
  642. if( whence < 0 )
  643. {
  644. pos = 0;
  645. cvSeqPopFront( seq, elem );
  646. }
  647. else if( whence > 0 )
  648. {
  649. pos = sseq->count-1;
  650. cvSeqPop( seq, elem );
  651. }
  652. else
  653. {
  654. pos = cvtest::randInt(rng) % sseq->count;
  655. cvSeqRemove( seq, pos );
  656. }
  657. if( whence != 0 )
  658. CV_TS_SEQ_CHECK_CONDITION( seq->total == sseq->count - 1 &&
  659. memcmp( elem, cvTsSimpleSeqElem(sseq,pos), elem_size) == 0,
  660. "The popped sequence element isn't correct" );
  661. cvTsSimpleSeqShiftAndCopy( sseq, pos + 1, pos );
  662. if( sseq->count > 0 )
  663. {
  664. elem2 = cvGetSeqElem( seq, pos < sseq->count ? pos : -1 );
  665. CV_TS_SEQ_CHECK_CONDITION( elem2 != 0, "GetSeqElem fails after removing the element" );
  666. CV_TS_SEQ_CHECK_CONDITION( memcmp( elem2,
  667. cvTsSimpleSeqElem(sseq, pos - (pos == sseq->count)), elem_size) == 0,
  668. "The first shifted element is not correct after removing another element" );
  669. }
  670. else
  671. {
  672. CV_TS_SEQ_CHECK_CONDITION( seq->first == 0,
  673. "The sequence doesn't become empty after the final remove" );
  674. }
  675. break;
  676. case 6:
  677. case 7:
  678. case 8: // push [front] multi/insert slice
  679. if( sseq->count == sseq->max_count )
  680. break;
  681. count = cvtest::randInt( rng ) % (sseq->max_count - sseq->count + 1);
  682. elem_mat = Mat(1, MAX(count,1) * elem_size, CV_8U, elem);
  683. cvtest::randUni( rng, elem_mat, cvScalarAll(0), cvScalarAll(255) );
  684. whence = op - 7;
  685. pos = whence < 0 ? 0 : whence > 0 ? sseq->count : (int)(cvtest::randInt(rng) % (sseq->count+1));
  686. if( whence != 0 )
  687. {
  688. cvSeqPushMulti( seq, elem, count, whence < 0 );
  689. }
  690. else
  691. {
  692. CvSeq header;
  693. CvSeqBlock block;
  694. cvMakeSeqHeaderForArray( CV_SEQ_KIND_GENERIC, sizeof(CvSeq),
  695. sseq->elem_size,
  696. elem, count,
  697. &header, &block );
  698. cvSeqInsertSlice( seq, pos, &header );
  699. }
  700. cvTsSimpleSeqShiftAndCopy( sseq, pos, pos + count, elem );
  701. if( sseq->count > 0 )
  702. {
  703. // choose the random element among the added
  704. pos = count > 0 ? (int)(cvtest::randInt(rng) % count + pos) : MAX(pos-1,0);
  705. elem2 = cvGetSeqElem( seq, pos );
  706. CV_TS_SEQ_CHECK_CONDITION( elem2 != 0, "multi push operation doesn't add elements" );
  707. CV_TS_SEQ_CHECK_CONDITION( seq->total == sseq->count &&
  708. memcmp( elem2, cvTsSimpleSeqElem(sseq,pos), elem_size) == 0,
  709. "One of the added elements is wrong" );
  710. }
  711. else
  712. {
  713. CV_TS_SEQ_CHECK_CONDITION( seq->total == 0 && seq->first == 0,
  714. "Adding no elements to empty sequence fails" );
  715. }
  716. break;
  717. case 9:
  718. case 10:
  719. case 11: // pop [front] multi
  720. if( sseq->count == 0 )
  721. break;
  722. count = cvtest::randInt(rng) % (sseq->count+1);
  723. whence = op - 10;
  724. pos = whence < 0 ? 0 : whence > 0 ? sseq->count - count :
  725. (int)(cvtest::randInt(rng) % (sseq->count - count + 1));
  726. if( whence != 0 )
  727. {
  728. cvSeqPopMulti( seq, elem, count, whence < 0 );
  729. if( count > 0 )
  730. {
  731. CV_TS_SEQ_CHECK_CONDITION( memcmp(elem,
  732. cvTsSimpleSeqElem(sseq,pos), elem_size) == 0,
  733. "The first (in the sequence order) removed element is wrong after popmulti" );
  734. }
  735. }
  736. else
  737. {
  738. cvSeqRemoveSlice( seq, cvSlice(pos, pos + count) );
  739. }
  740. CV_TS_SEQ_CHECK_CONDITION( seq->total == sseq->count - count,
  741. "The popmulti left a wrong number of elements in the sequence" );
  742. cvTsSimpleSeqShiftAndCopy( sseq, pos + count, pos, 0 );
  743. if( sseq->count > 0 )
  744. {
  745. pos = whence < 0 ? 0 : MIN( pos, sseq->count - 1 );
  746. elem2 = cvGetSeqElem( seq, pos );
  747. CV_TS_SEQ_CHECK_CONDITION( elem2 &&
  748. memcmp( elem2, cvTsSimpleSeqElem(sseq,pos), elem_size) == 0,
  749. "The last sequence element is wrong after POP" );
  750. }
  751. else
  752. {
  753. CV_TS_SEQ_CHECK_CONDITION( seq->total == 0 && seq->first == 0,
  754. "The sequence doesn't become empty after final POP" );
  755. }
  756. break;
  757. case 12: // seqslice
  758. {
  759. CvMemStoragePos storage_pos;
  760. cvSaveMemStoragePos( storage, &storage_pos );
  761. int copy_data = cvtest::randInt(rng) % 2;
  762. count = cvtest::randInt(rng) % (seq->total + 1);
  763. pos = cvtest::randInt(rng) % (seq->total - count + 1);
  764. CvSeq* seq_slice = cvSeqSlice( seq, cvSlice(pos, pos + count), storage, copy_data );
  765. CV_TS_SEQ_CHECK_CONDITION( seq_slice && seq_slice->total == count,
  766. "cvSeqSlice returned incorrect slice" );
  767. if( count > 0 )
  768. {
  769. int test_idx = cvtest::randInt(rng) % count;
  770. elem2 = cvGetSeqElem( seq_slice, test_idx );
  771. schar* elem3 = cvGetSeqElem( seq, pos + test_idx );
  772. CV_TS_SEQ_CHECK_CONDITION( elem2 &&
  773. memcmp( elem2, cvTsSimpleSeqElem(sseq,pos + test_idx), elem_size) == 0,
  774. "The extracted slice elements are not correct" );
  775. CV_TS_SEQ_CHECK_CONDITION( (elem2 == elem3) ^ copy_data,
  776. "copy_data flag is handled incorrectly" );
  777. }
  778. cvRestoreMemStoragePos( storage, &storage_pos );
  779. }
  780. break;
  781. case 13: // clear
  782. cvTsClearSimpleSeq( sseq );
  783. cvClearSeq( seq );
  784. CV_TS_SEQ_CHECK_CONDITION( seq->total == 0 && seq->first == 0,
  785. "The sequence doesn't become empty after clear" );
  786. break;
  787. default:
  788. CV_Assert(0);
  789. return -1;
  790. }
  791. if( test_seq_block_consistence(struct_idx, seq, sseq->count) < 0 )
  792. return -1;
  793. if( test_get_seq_elem(struct_idx, 7) < 0 )
  794. return -1;
  795. update_progressbar();
  796. }
  797. return 0;
  798. }
  799. void Core_SeqBaseTest::run( int )
  800. {
  801. try
  802. {
  803. RNG& rng = ts->get_rng();
  804. int i;
  805. double t;
  806. clear();
  807. test_progress = -1;
  808. simple_struct.resize(struct_count, 0);
  809. cxcore_struct.resize(struct_count, 0);
  810. for( gen = 0; gen < generations; gen++ )
  811. {
  812. struct_idx = iter = -1;
  813. if( !storage )
  814. {
  815. t = cvtest::randReal(rng)*(max_log_storage_block_size - min_log_storage_block_size)
  816. + min_log_storage_block_size;
  817. storage.reset(cvCreateMemStorage( cvRound( exp(t * CV_LOG2) ) ));
  818. }
  819. iter = struct_idx = -1;
  820. test_multi_create();
  821. for( i = 0; i < struct_count; i++ )
  822. {
  823. if( test_seq_block_consistence(i, (CvSeq*)cxcore_struct[i],
  824. ((CvTsSimpleSeq*)simple_struct[i])->count) < 0 )
  825. return;
  826. if( test_get_seq_elem( i, MAX(iterations/3,7) ) < 0 )
  827. return;
  828. if( test_get_seq_reading( i, MAX(iterations/3,7) ) < 0 )
  829. return;
  830. update_progressbar();
  831. }
  832. if( test_seq_ops( iterations ) < 0 )
  833. return;
  834. if( cvtest::randInt(rng) % 2 )
  835. storage.release();
  836. else
  837. cvClearMemStorage( storage );
  838. }
  839. }
  840. catch(const int &)
  841. {
  842. }
  843. }
  844. ////////////////////////////// more sequence tests //////////////////////////////////////
  845. class Core_SeqSortInvTest : public Core_SeqBaseTest
  846. {
  847. public:
  848. Core_SeqSortInvTest();
  849. void run( int );
  850. protected:
  851. };
  852. Core_SeqSortInvTest::Core_SeqSortInvTest()
  853. {
  854. }
  855. static int icvCmpSeqElems( const void* a, const void* b, void* userdata )
  856. {
  857. return memcmp( a, b, ((CvSeq*)userdata)->elem_size );
  858. }
  859. static int icvCmpSeqElems2_elem_size = 0;
  860. static int icvCmpSeqElems2( const void* a, const void* b )
  861. {
  862. return memcmp( a, b, icvCmpSeqElems2_elem_size );
  863. }
  864. void Core_SeqSortInvTest::run( int )
  865. {
  866. try
  867. {
  868. RNG& rng = ts->get_rng();
  869. int i, k;
  870. double t;
  871. schar *elem0, *elem, *elem2;
  872. vector<uchar> buffer;
  873. clear();
  874. test_progress = -1;
  875. simple_struct.resize(struct_count, 0);
  876. cxcore_struct.resize(struct_count, 0);
  877. for( gen = 0; gen < generations; gen++ )
  878. {
  879. struct_idx = iter = -1;
  880. if( !storage )
  881. {
  882. t = cvtest::randReal(rng)*(max_log_storage_block_size - min_log_storage_block_size)
  883. + min_log_storage_block_size;
  884. storage.reset(cvCreateMemStorage( cvRound( exp(t * CV_LOG2) ) ));
  885. }
  886. for( iter = 0; iter < iterations/10; iter++ )
  887. {
  888. int max_size = 0;
  889. test_multi_create();
  890. for( i = 0; i < struct_count; i++ )
  891. {
  892. CvTsSimpleSeq* sseq = (CvTsSimpleSeq*)simple_struct[i];
  893. max_size = MAX( max_size, sseq->count*sseq->elem_size );
  894. }
  895. buffer.resize(max_size);
  896. for( i = 0; i < struct_count; i++ )
  897. {
  898. CvSeq* seq = (CvSeq*)cxcore_struct[i];
  899. CvTsSimpleSeq* sseq = (CvTsSimpleSeq*)simple_struct[i];
  900. CvSlice slice = CV_WHOLE_SEQ;
  901. //printf("%d. %d. %d-th size = %d\n", gen, iter, i, sseq->count );
  902. cvSeqInvert( seq );
  903. cvTsSimpleSeqInvert( sseq );
  904. if( test_seq_block_consistence( i, seq, sseq->count ) < 0 )
  905. return;
  906. if( sseq->count > 0 && cvtest::randInt(rng) % 2 == 0 )
  907. {
  908. slice.end_index = cvtest::randInt(rng) % sseq->count + 1;
  909. slice.start_index = cvtest::randInt(rng) % (sseq->count - slice.end_index + 1);
  910. slice.end_index += slice.start_index;
  911. }
  912. cvCvtSeqToArray( seq, &buffer[0], slice );
  913. slice.end_index = MIN( slice.end_index, sseq->count );
  914. CV_TS_SEQ_CHECK_CONDITION( sseq->count == 0 || memcmp( &buffer[0],
  915. sseq->array + slice.start_index*sseq->elem_size,
  916. (slice.end_index - slice.start_index)*sseq->elem_size ) == 0,
  917. "cvSeqInvert returned wrong result" );
  918. for( k = 0; k < (sseq->count > 0 ? 10 : 0); k++ )
  919. {
  920. int idx0 = cvtest::randInt(rng) % sseq->count, idx = 0;
  921. elem0 = cvTsSimpleSeqElem( sseq, idx0 );
  922. elem = cvGetSeqElem( seq, idx0 );
  923. elem2 = cvSeqSearch( seq, elem0, k % 2 ? icvCmpSeqElems : 0, 0, &idx, seq );
  924. CV_TS_SEQ_CHECK_CONDITION( elem != 0 &&
  925. memcmp( elem0, elem, seq->elem_size ) == 0,
  926. "cvSeqInvert gives incorrect result" );
  927. CV_TS_SEQ_CHECK_CONDITION( elem2 != 0 &&
  928. memcmp( elem0, elem2, seq->elem_size ) == 0 &&
  929. elem2 == cvGetSeqElem( seq, idx ),
  930. "cvSeqSearch failed (linear search)" );
  931. }
  932. cvSeqSort( seq, icvCmpSeqElems, seq );
  933. if( test_seq_block_consistence( i, seq, sseq->count ) < 0 )
  934. return;
  935. if( sseq->count > 0 )
  936. {
  937. // !!! This is not thread-safe !!!
  938. icvCmpSeqElems2_elem_size = sseq->elem_size;
  939. qsort( sseq->array, sseq->count, sseq->elem_size, icvCmpSeqElems2 );
  940. if( cvtest::randInt(rng) % 2 == 0 )
  941. {
  942. slice.end_index = cvtest::randInt(rng) % sseq->count + 1;
  943. slice.start_index = cvtest::randInt(rng) % (sseq->count - slice.end_index + 1);
  944. slice.end_index += slice.start_index;
  945. }
  946. }
  947. cvCvtSeqToArray( seq, &buffer[0], slice );
  948. CV_TS_SEQ_CHECK_CONDITION( sseq->count == 0 || memcmp( &buffer[0],
  949. sseq->array + slice.start_index*sseq->elem_size,
  950. (slice.end_index - slice.start_index)*sseq->elem_size ) == 0,
  951. "cvSeqSort returned wrong result" );
  952. for( k = 0; k < (sseq->count > 0 ? 10 : 0); k++ )
  953. {
  954. int idx0 = cvtest::randInt(rng) % sseq->count, idx = 0;
  955. elem0 = cvTsSimpleSeqElem( sseq, idx0 );
  956. elem = cvGetSeqElem( seq, idx0 );
  957. elem2 = cvSeqSearch( seq, elem0, icvCmpSeqElems, 1, &idx, seq );
  958. CV_TS_SEQ_CHECK_CONDITION( elem != 0 &&
  959. memcmp( elem0, elem, seq->elem_size ) == 0,
  960. "cvSeqSort gives incorrect result" );
  961. CV_TS_SEQ_CHECK_CONDITION( elem2 != 0 &&
  962. memcmp( elem0, elem2, seq->elem_size ) == 0 &&
  963. elem2 == cvGetSeqElem( seq, idx ),
  964. "cvSeqSearch failed (binary search)" );
  965. }
  966. }
  967. cvClearMemStorage( storage );
  968. }
  969. storage.release();
  970. }
  971. }
  972. catch (const int &)
  973. {
  974. }
  975. }
  976. /////////////////////////////////////// set tests ///////////////////////////////////////
  977. class Core_SetTest : public Core_DynStructBaseTest
  978. {
  979. public:
  980. Core_SetTest();
  981. virtual ~Core_SetTest();
  982. void clear();
  983. void run( int );
  984. protected:
  985. //int test_seq_block_consistence( int struct_idx );
  986. int test_set_ops( int iters );
  987. };
  988. Core_SetTest::Core_SetTest()
  989. {
  990. }
  991. Core_SetTest::~Core_SetTest()
  992. {
  993. clear();
  994. }
  995. void Core_SetTest::clear()
  996. {
  997. for( size_t i = 0; i < simple_struct.size(); i++ )
  998. cvTsReleaseSimpleSet( (CvTsSimpleSet**)&simple_struct[i] );
  999. Core_DynStructBaseTest::clear();
  1000. }
  1001. int Core_SetTest::test_set_ops( int iters )
  1002. {
  1003. const int max_op = 4;
  1004. int max_elem_size = 0;
  1005. int idx, idx0;
  1006. CvSetElem *elem = 0, *elem2 = 0, *elem3 = 0;
  1007. schar* elem_data = 0;
  1008. RNG& rng = ts->get_rng();
  1009. //int max_active_count = 0, mean_active_count = 0;
  1010. for( int i = 0; i < struct_count; i++ )
  1011. max_elem_size = MAX( max_elem_size, ((CvSeq*)cxcore_struct[i])->elem_size );
  1012. vector<schar> elem_buf(max_elem_size);
  1013. Mat elem_mat;
  1014. for( iter = 0; iter < iters; iter++ )
  1015. {
  1016. struct_idx = cvtest::randInt(rng) % struct_count;
  1017. CvSet* cvset = (CvSet*)cxcore_struct[struct_idx];
  1018. CvTsSimpleSet* sset = (CvTsSimpleSet*)simple_struct[struct_idx];
  1019. int pure_elem_size = sset->elem_size - 1;
  1020. int prev_total = cvset->total, prev_count = cvset->active_count;
  1021. int op = cvtest::randInt(rng) % (iter <= iters/10 ? 2 : max_op);
  1022. int by_ptr = op % 2 == 0;
  1023. CvSetElem* first_free = cvset->free_elems;
  1024. CvSetElem* next_free = first_free ? first_free->next_free : 0;
  1025. int pass_data = 0;
  1026. if( iter > iters/10 && cvtest::randInt(rng)%200 == 0 ) // clear set
  1027. {
  1028. prev_count = cvset->total;
  1029. cvClearSet( cvset );
  1030. cvTsClearSimpleSet( sset );
  1031. CV_TS_SEQ_CHECK_CONDITION( cvset->active_count == 0 && cvset->total == 0 &&
  1032. cvset->first == 0 && cvset->free_elems == 0 &&
  1033. (cvset->free_blocks != 0 || prev_count == 0),
  1034. "cvClearSet doesn't remove all the elements" );
  1035. continue;
  1036. }
  1037. else if( op == 0 || op == 1 ) // add element
  1038. {
  1039. if( sset->free_count == 0 )
  1040. continue;
  1041. elem_mat = Mat(1, cvset->elem_size, CV_8U, &elem_buf[0]);
  1042. cvtest::randUni( rng, elem_mat, cvScalarAll(0), cvScalarAll(255) );
  1043. elem = (CvSetElem*)&elem_buf[0];
  1044. if( by_ptr )
  1045. {
  1046. elem2 = cvSetNew( cvset );
  1047. CV_TS_SEQ_CHECK_CONDITION( elem2 != 0, "cvSetNew returned NULL pointer" );
  1048. }
  1049. else
  1050. {
  1051. pass_data = cvtest::randInt(rng) % 2;
  1052. idx = cvSetAdd( cvset, pass_data ? elem : 0, &elem2 );
  1053. CV_TS_SEQ_CHECK_CONDITION( elem2 != 0 && elem2->flags == idx,
  1054. "cvSetAdd returned NULL pointer or a wrong index" );
  1055. }
  1056. elem_data = (schar*)elem + sizeof(int);
  1057. if( !pass_data )
  1058. memcpy( (schar*)elem2 + sizeof(int), elem_data, pure_elem_size );
  1059. idx = elem2->flags;
  1060. idx0 = cvTsSimpleSetAdd( sset, elem_data );
  1061. elem3 = cvGetSetElem( cvset, idx );
  1062. CV_TS_SEQ_CHECK_CONDITION( CV_IS_SET_ELEM(elem3) &&
  1063. idx == idx0 && elem3 == elem2 && (!pass_data ||
  1064. memcmp( (char*)elem3 + sizeof(int), elem_data, pure_elem_size) == 0),
  1065. "The added element is not correct" );
  1066. CV_TS_SEQ_CHECK_CONDITION( (!first_free || elem3 == first_free) &&
  1067. (!next_free || cvset->free_elems == next_free) &&
  1068. cvset->active_count == prev_count + 1,
  1069. "The free node list is modified incorrectly" );
  1070. }
  1071. else if( op == 2 || op == 3 ) // remove element
  1072. {
  1073. idx = cvtest::randInt(rng) % sset->max_count;
  1074. if( sset->free_count == sset->max_count || idx >= sset->count )
  1075. continue;
  1076. elem_data = cvTsSimpleSetFind(sset, idx);
  1077. if( elem_data == 0 )
  1078. continue;
  1079. elem = cvGetSetElem( cvset, idx );
  1080. CV_TS_SEQ_CHECK_CONDITION( CV_IS_SET_ELEM(elem) && elem->flags == idx &&
  1081. memcmp((char*)elem + sizeof(int), elem_data, pure_elem_size) == 0,
  1082. "cvGetSetElem returned wrong element" );
  1083. if( by_ptr )
  1084. {
  1085. cvSetRemoveByPtr( cvset, elem );
  1086. }
  1087. else
  1088. {
  1089. cvSetRemove( cvset, idx );
  1090. }
  1091. cvTsSimpleSetRemove( sset, idx );
  1092. CV_TS_SEQ_CHECK_CONDITION( !CV_IS_SET_ELEM(elem) && !cvGetSetElem(cvset, idx) &&
  1093. (elem->flags & CV_SET_ELEM_IDX_MASK) == idx,
  1094. "cvSetRemove[ByPtr] didn't release the element properly" );
  1095. CV_TS_SEQ_CHECK_CONDITION( elem->next_free == first_free &&
  1096. cvset->free_elems == elem &&
  1097. cvset->active_count == prev_count - 1,
  1098. "The free node list has not been updated properly" );
  1099. }
  1100. //max_active_count = MAX( max_active_count, cvset->active_count );
  1101. //mean_active_count += cvset->active_count;
  1102. CV_TS_SEQ_CHECK_CONDITION( cvset->active_count == sset->max_count - sset->free_count &&
  1103. cvset->total >= cvset->active_count &&
  1104. (cvset->total == 0 || cvset->total >= prev_total),
  1105. "The total number of cvset elements is not correct" );
  1106. // CvSet and simple set do not necessary have the same "total" (active & free) number,
  1107. // so pass "set->total" to skip that check
  1108. test_seq_block_consistence( struct_idx, (CvSeq*)cvset, cvset->total );
  1109. update_progressbar();
  1110. }
  1111. return 0;
  1112. }
  1113. void Core_SetTest::run( int )
  1114. {
  1115. try
  1116. {
  1117. RNG& rng = ts->get_rng();
  1118. double t;
  1119. clear();
  1120. test_progress = -1;
  1121. simple_struct.resize(struct_count, 0);
  1122. cxcore_struct.resize(struct_count, 0);
  1123. for( gen = 0; gen < generations; gen++ )
  1124. {
  1125. struct_idx = iter = -1;
  1126. t = cvtest::randReal(rng)*(max_log_storage_block_size - min_log_storage_block_size) + min_log_storage_block_size;
  1127. storage.reset(cvCreateMemStorage( cvRound( exp(t * CV_LOG2) ) ));
  1128. for( int i = 0; i < struct_count; i++ )
  1129. {
  1130. t = cvtest::randReal(rng)*(max_log_elem_size - min_log_elem_size) + min_log_elem_size;
  1131. int pure_elem_size = cvRound( exp(t * CV_LOG2) );
  1132. int elem_size = pure_elem_size + sizeof(int);
  1133. elem_size = (elem_size + sizeof(size_t) - 1) & ~(sizeof(size_t)-1);
  1134. elem_size = MAX( elem_size, (int)sizeof(CvSetElem) );
  1135. elem_size = MIN( elem_size, (int)(storage->block_size - sizeof(void*) - sizeof(CvMemBlock) - sizeof(CvSeqBlock)) );
  1136. pure_elem_size = MIN( pure_elem_size, elem_size-(int)sizeof(CvSetElem) );
  1137. cvTsReleaseSimpleSet( (CvTsSimpleSet**)&simple_struct[i] );
  1138. simple_struct[i] = cvTsCreateSimpleSet( max_struct_size, pure_elem_size );
  1139. cxcore_struct[i] = cvCreateSet( 0, sizeof(CvSet), elem_size, storage );
  1140. }
  1141. if( test_set_ops( iterations*100 ) < 0 )
  1142. return;
  1143. storage.release();
  1144. }
  1145. }
  1146. catch(const int &)
  1147. {
  1148. }
  1149. }
  1150. /////////////////////////////////////// graph tests //////////////////////////////////
  1151. class Core_GraphTest : public Core_DynStructBaseTest
  1152. {
  1153. public:
  1154. Core_GraphTest();
  1155. virtual ~Core_GraphTest();
  1156. void clear();
  1157. void run( int );
  1158. protected:
  1159. //int test_seq_block_consistence( int struct_idx );
  1160. int test_graph_ops( int iters );
  1161. };
  1162. Core_GraphTest::Core_GraphTest()
  1163. {
  1164. }
  1165. Core_GraphTest::~Core_GraphTest()
  1166. {
  1167. clear();
  1168. }
  1169. void Core_GraphTest::clear()
  1170. {
  1171. for( size_t i = 0; i < simple_struct.size(); i++ )
  1172. cvTsReleaseSimpleGraph( (CvTsSimpleGraph**)&simple_struct[i] );
  1173. Core_DynStructBaseTest::clear();
  1174. }
  1175. int Core_GraphTest::test_graph_ops( int iters )
  1176. {
  1177. const int max_op = 4;
  1178. int i, k;
  1179. int max_elem_size = 0;
  1180. int idx, idx0;
  1181. CvGraphVtx *vtx = 0, *vtx2 = 0, *vtx3 = 0;
  1182. CvGraphEdge* edge = 0, *edge2 = 0;
  1183. RNG& rng = ts->get_rng();
  1184. //int max_active_count = 0, mean_active_count = 0;
  1185. for( i = 0; i < struct_count; i++ )
  1186. {
  1187. CvGraph* graph = (CvGraph*)cxcore_struct[i];
  1188. max_elem_size = MAX( max_elem_size, graph->elem_size );
  1189. max_elem_size = MAX( max_elem_size, graph->edges->elem_size );
  1190. }
  1191. vector<schar> elem_buf(max_elem_size);
  1192. Mat elem_mat;
  1193. for( iter = 0; iter < iters; iter++ )
  1194. {
  1195. struct_idx = cvtest::randInt(rng) % struct_count;
  1196. CvGraph* graph = (CvGraph*)cxcore_struct[struct_idx];
  1197. CvTsSimpleGraph* sgraph = (CvTsSimpleGraph*)simple_struct[struct_idx];
  1198. CvSet* edges = graph->edges;
  1199. schar *vtx_data;
  1200. char *edge_data;
  1201. int pure_vtx_size = sgraph->vtx->elem_size - 1,
  1202. pure_edge_size = sgraph->edge_size - 1;
  1203. int prev_vtx_total = graph->total,
  1204. prev_edge_total = graph->edges->total,
  1205. prev_vtx_count = graph->active_count,
  1206. prev_edge_count = graph->edges->active_count;
  1207. int op = cvtest::randInt(rng) % max_op;
  1208. int pass_data = 0, vtx_degree0 = 0, vtx_degree = 0;
  1209. CvSetElem *first_free, *next_free;
  1210. if( cvtest::randInt(rng) % 200 == 0 ) // clear graph
  1211. {
  1212. int prev_vtx_count2 = graph->total, prev_edge_count2 = graph->edges->total;
  1213. cvClearGraph( graph );
  1214. cvTsClearSimpleGraph( sgraph );
  1215. CV_TS_SEQ_CHECK_CONDITION( graph->active_count == 0 && graph->total == 0 &&
  1216. graph->first == 0 && graph->free_elems == 0 &&
  1217. (graph->free_blocks != 0 || prev_vtx_count2 == 0),
  1218. "The graph is not empty after clearing" );
  1219. CV_TS_SEQ_CHECK_CONDITION( edges->active_count == 0 && edges->total == 0 &&
  1220. edges->first == 0 && edges->free_elems == 0 &&
  1221. (edges->free_blocks != 0 || prev_edge_count2 == 0),
  1222. "The graph is not empty after clearing" );
  1223. }
  1224. else if( op == 0 ) // add vertex
  1225. {
  1226. if( sgraph->vtx->free_count == 0 )
  1227. continue;
  1228. first_free = graph->free_elems;
  1229. next_free = first_free ? first_free->next_free : 0;
  1230. if( pure_vtx_size )
  1231. {
  1232. elem_mat = Mat(1, graph->elem_size, CV_8U, &elem_buf[0]);
  1233. cvtest::randUni( rng, elem_mat, cvScalarAll(0), cvScalarAll(255) );
  1234. }
  1235. vtx = (CvGraphVtx*)&elem_buf[0];
  1236. idx0 = cvTsSimpleGraphAddVertex( sgraph, vtx + 1 );
  1237. pass_data = cvtest::randInt(rng) % 2;
  1238. idx = cvGraphAddVtx( graph, pass_data ? vtx : 0, &vtx2 );
  1239. if( !pass_data && pure_vtx_size > 0 )
  1240. memcpy( vtx2 + 1, vtx + 1, pure_vtx_size );
  1241. vtx3 = cvGetGraphVtx( graph, idx );
  1242. CV_TS_SEQ_CHECK_CONDITION( (CV_IS_SET_ELEM(vtx3) && vtx3->flags == idx &&
  1243. vtx3->first == 0) || (idx == idx0 && vtx3 == vtx2 &&
  1244. (!pass_data || pure_vtx_size == 0 ||
  1245. memcmp(vtx3 + 1, vtx + 1, pure_vtx_size) == 0)),
  1246. "The added element is not correct" );
  1247. CV_TS_SEQ_CHECK_CONDITION( (!first_free || first_free == (CvSetElem*)vtx3) &&
  1248. (!next_free || graph->free_elems == next_free) &&
  1249. graph->active_count == prev_vtx_count + 1,
  1250. "The free node list is modified incorrectly" );
  1251. }
  1252. else if( op == 1 ) // remove vertex
  1253. {
  1254. idx = cvtest::randInt(rng) % sgraph->vtx->max_count;
  1255. if( sgraph->vtx->free_count == sgraph->vtx->max_count || idx >= sgraph->vtx->count )
  1256. continue;
  1257. vtx_data = cvTsSimpleGraphFindVertex(sgraph, idx);
  1258. if( vtx_data == 0 )
  1259. continue;
  1260. vtx_degree0 = cvTsSimpleGraphVertexDegree( sgraph, idx );
  1261. first_free = graph->free_elems;
  1262. vtx = cvGetGraphVtx( graph, idx );
  1263. CV_TS_SEQ_CHECK_CONDITION( CV_IS_SET_ELEM(vtx) && vtx->flags == idx &&
  1264. (pure_vtx_size == 0 || memcmp( vtx + 1, vtx_data, pure_vtx_size) == 0),
  1265. "cvGetGraphVtx returned wrong element" );
  1266. if( cvtest::randInt(rng) % 2 )
  1267. {
  1268. vtx_degree = cvGraphVtxDegreeByPtr( graph, vtx );
  1269. cvGraphRemoveVtxByPtr( graph, vtx );
  1270. }
  1271. else
  1272. {
  1273. vtx_degree = cvGraphVtxDegree( graph, idx );
  1274. cvGraphRemoveVtx( graph, idx );
  1275. }
  1276. cvTsSimpleGraphRemoveVertex( sgraph, idx );
  1277. CV_TS_SEQ_CHECK_CONDITION( vtx_degree == vtx_degree0,
  1278. "Number of incident edges is different in two graph representations" );
  1279. CV_TS_SEQ_CHECK_CONDITION( !CV_IS_SET_ELEM(vtx) && !cvGetGraphVtx(graph, idx) &&
  1280. (vtx->flags & CV_SET_ELEM_IDX_MASK) == idx,
  1281. "cvGraphRemoveVtx[ByPtr] didn't release the vertex properly" );
  1282. CV_TS_SEQ_CHECK_CONDITION( graph->edges->active_count == prev_edge_count - vtx_degree,
  1283. "cvGraphRemoveVtx[ByPtr] didn't remove all the incident edges "
  1284. "(or removed some extra)" );
  1285. CV_TS_SEQ_CHECK_CONDITION( ((CvSetElem*)vtx)->next_free == first_free &&
  1286. graph->free_elems == (CvSetElem*)vtx &&
  1287. graph->active_count == prev_vtx_count - 1,
  1288. "The free node list has not been updated properly" );
  1289. }
  1290. else if( op == 2 ) // add edge
  1291. {
  1292. int v_idx[2] = {0,0}, res = 0;
  1293. int v_prev_degree[2] = {0,0}, v_degree[2] = {0,0};
  1294. if( sgraph->vtx->free_count >= sgraph->vtx->max_count-1 )
  1295. continue;
  1296. for( i = 0, k = 0; i < 10; i++ )
  1297. {
  1298. int j = cvtest::randInt(rng) % sgraph->vtx->count;
  1299. vtx_data = cvTsSimpleGraphFindVertex( sgraph, j );
  1300. if( vtx_data )
  1301. {
  1302. v_idx[k] = j;
  1303. if( k == 0 )
  1304. k++;
  1305. else if( v_idx[0] != v_idx[1] &&
  1306. cvTsSimpleGraphFindEdge( sgraph, v_idx[0], v_idx[1] ) == 0 )
  1307. {
  1308. k++;
  1309. break;
  1310. }
  1311. }
  1312. }
  1313. if( k < 2 )
  1314. continue;
  1315. first_free = graph->edges->free_elems;
  1316. next_free = first_free ? first_free->next_free : 0;
  1317. edge = cvFindGraphEdge( graph, v_idx[0], v_idx[1] );
  1318. CV_TS_SEQ_CHECK_CONDITION( edge == 0, "Extra edge appeared in the graph" );
  1319. if( pure_edge_size > 0 )
  1320. {
  1321. elem_mat = Mat(1, graph->edges->elem_size, CV_8U, &elem_buf[0]);
  1322. cvtest::randUni( rng, elem_mat, cvScalarAll(0), cvScalarAll(255) );
  1323. }
  1324. edge = (CvGraphEdge*)&elem_buf[0];
  1325. // assign some default weight that is easy to check for
  1326. // consistensy, 'cause an edge weight is not stored
  1327. // in the simple graph
  1328. edge->weight = (float)(v_idx[0] + v_idx[1]);
  1329. pass_data = cvtest::randInt(rng) % 2;
  1330. vtx = cvGetGraphVtx( graph, v_idx[0] );
  1331. vtx2 = cvGetGraphVtx( graph, v_idx[1] );
  1332. CV_TS_SEQ_CHECK_CONDITION( vtx != 0 && vtx2 != 0 && vtx->flags == v_idx[0] &&
  1333. vtx2->flags == v_idx[1], "Some of the vertices are missing" );
  1334. if( cvtest::randInt(rng) % 2 )
  1335. {
  1336. v_prev_degree[0] = cvGraphVtxDegreeByPtr( graph, vtx );
  1337. v_prev_degree[1] = cvGraphVtxDegreeByPtr( graph, vtx2 );
  1338. res = cvGraphAddEdgeByPtr(graph, vtx, vtx2, pass_data ? edge : 0, &edge2);
  1339. v_degree[0] = cvGraphVtxDegreeByPtr( graph, vtx );
  1340. v_degree[1] = cvGraphVtxDegreeByPtr( graph, vtx2 );
  1341. }
  1342. else
  1343. {
  1344. v_prev_degree[0] = cvGraphVtxDegree( graph, v_idx[0] );
  1345. v_prev_degree[1] = cvGraphVtxDegree( graph, v_idx[1] );
  1346. res = cvGraphAddEdge(graph, v_idx[0], v_idx[1], pass_data ? edge : 0, &edge2);
  1347. v_degree[0] = cvGraphVtxDegree( graph, v_idx[0] );
  1348. v_degree[1] = cvGraphVtxDegree( graph, v_idx[1] );
  1349. }
  1350. //edge3 = (CvGraphEdge*)cvGetSetElem( graph->edges, idx );
  1351. CV_TS_SEQ_CHECK_CONDITION( res == 1 && edge2 != 0 && CV_IS_SET_ELEM(edge2) &&
  1352. ((edge2->vtx[0] == vtx && edge2->vtx[1] == vtx2) ||
  1353. (!CV_IS_GRAPH_ORIENTED(graph) && edge2->vtx[0] == vtx2 && edge2->vtx[1] == vtx)) &&
  1354. (!pass_data || pure_edge_size == 0 || memcmp( edge2 + 1, edge + 1, pure_edge_size ) == 0),
  1355. "The edge has been added incorrectly" );
  1356. if( !pass_data )
  1357. {
  1358. if( pure_edge_size > 0 )
  1359. memcpy( edge2 + 1, edge + 1, pure_edge_size );
  1360. edge2->weight = edge->weight;
  1361. }
  1362. CV_TS_SEQ_CHECK_CONDITION( v_degree[0] == v_prev_degree[0] + 1 &&
  1363. v_degree[1] == v_prev_degree[1] + 1,
  1364. "The vertices lists have not been updated properly" );
  1365. cvTsSimpleGraphAddEdge( sgraph, v_idx[0], v_idx[1], edge + 1 );
  1366. CV_TS_SEQ_CHECK_CONDITION( (!first_free || first_free == (CvSetElem*)edge2) &&
  1367. (!next_free || graph->edges->free_elems == next_free) &&
  1368. graph->edges->active_count == prev_edge_count + 1,
  1369. "The free node list is modified incorrectly" );
  1370. }
  1371. else if( op == 3 ) // find & remove edge
  1372. {
  1373. int v_idx[2] = {0,0}, by_ptr;
  1374. int v_prev_degree[2] = {0,0}, v_degree[2] = {0,0};
  1375. if( sgraph->vtx->free_count >= sgraph->vtx->max_count-1 )
  1376. continue;
  1377. edge_data = 0;
  1378. for( i = 0, k = 0; i < 10; i++ )
  1379. {
  1380. int j = cvtest::randInt(rng) % sgraph->vtx->count;
  1381. vtx_data = cvTsSimpleGraphFindVertex( sgraph, j );
  1382. if( vtx_data )
  1383. {
  1384. v_idx[k] = j;
  1385. if( k == 0 )
  1386. k++;
  1387. else
  1388. {
  1389. edge_data = cvTsSimpleGraphFindEdge( sgraph, v_idx[0], v_idx[1] );
  1390. if( edge_data )
  1391. {
  1392. k++;
  1393. break;
  1394. }
  1395. }
  1396. }
  1397. }
  1398. if( k < 2 )
  1399. continue;
  1400. by_ptr = cvtest::randInt(rng) % 2;
  1401. first_free = graph->edges->free_elems;
  1402. vtx = cvGetGraphVtx( graph, v_idx[0] );
  1403. vtx2 = cvGetGraphVtx( graph, v_idx[1] );
  1404. CV_TS_SEQ_CHECK_CONDITION( vtx != 0 && vtx2 != 0 && vtx->flags == v_idx[0] &&
  1405. vtx2->flags == v_idx[1], "Some of the vertices are missing" );
  1406. if( by_ptr )
  1407. {
  1408. edge = cvFindGraphEdgeByPtr( graph, vtx, vtx2 );
  1409. v_prev_degree[0] = cvGraphVtxDegreeByPtr( graph, vtx );
  1410. v_prev_degree[1] = cvGraphVtxDegreeByPtr( graph, vtx2 );
  1411. }
  1412. else
  1413. {
  1414. edge = cvFindGraphEdge( graph, v_idx[0], v_idx[1] );
  1415. v_prev_degree[0] = cvGraphVtxDegree( graph, v_idx[0] );
  1416. v_prev_degree[1] = cvGraphVtxDegree( graph, v_idx[1] );
  1417. }
  1418. idx = edge->flags;
  1419. CV_TS_SEQ_CHECK_CONDITION( edge != 0 && edge->weight == v_idx[0] + v_idx[1] &&
  1420. ((edge->vtx[0] == vtx && edge->vtx[1] == vtx2) ||
  1421. (!CV_IS_GRAPH_ORIENTED(graph) && edge->vtx[1] == vtx && edge->vtx[0] == vtx2)) &&
  1422. (pure_edge_size == 0 || memcmp(edge + 1, edge_data, pure_edge_size) == 0),
  1423. "An edge is missing or incorrect" );
  1424. if( by_ptr )
  1425. {
  1426. cvGraphRemoveEdgeByPtr( graph, vtx, vtx2 );
  1427. edge2 = cvFindGraphEdgeByPtr( graph, vtx, vtx2 );
  1428. v_degree[0] = cvGraphVtxDegreeByPtr( graph, vtx );
  1429. v_degree[1] = cvGraphVtxDegreeByPtr( graph, vtx2 );
  1430. }
  1431. else
  1432. {
  1433. cvGraphRemoveEdge(graph, v_idx[0], v_idx[1] );
  1434. edge2 = cvFindGraphEdge( graph, v_idx[0], v_idx[1] );
  1435. v_degree[0] = cvGraphVtxDegree( graph, v_idx[0] );
  1436. v_degree[1] = cvGraphVtxDegree( graph, v_idx[1] );
  1437. }
  1438. CV_TS_SEQ_CHECK_CONDITION( !edge2 && !CV_IS_SET_ELEM(edge),
  1439. "The edge has not been removed from the edge set" );
  1440. CV_TS_SEQ_CHECK_CONDITION( v_degree[0] == v_prev_degree[0] - 1 &&
  1441. v_degree[1] == v_prev_degree[1] - 1,
  1442. "The vertices lists have not been updated properly" );
  1443. cvTsSimpleGraphRemoveEdge( sgraph, v_idx[0], v_idx[1] );
  1444. CV_TS_SEQ_CHECK_CONDITION( graph->edges->free_elems == (CvSetElem*)edge &&
  1445. graph->edges->free_elems->next_free == first_free &&
  1446. graph->edges->active_count == prev_edge_count - 1,
  1447. "The free edge list has not been modified properly" );
  1448. }
  1449. //max_active_count = MAX( max_active_count, graph->active_count );
  1450. //mean_active_count += graph->active_count;
  1451. CV_TS_SEQ_CHECK_CONDITION( graph->active_count == sgraph->vtx->max_count - sgraph->vtx->free_count &&
  1452. graph->total >= graph->active_count &&
  1453. (graph->total == 0 || graph->total >= prev_vtx_total),
  1454. "The total number of graph vertices is not correct" );
  1455. CV_TS_SEQ_CHECK_CONDITION( graph->edges->total >= graph->edges->active_count &&
  1456. (graph->edges->total == 0 || graph->edges->total >= prev_edge_total),
  1457. "The total number of graph vertices is not correct" );
  1458. // CvGraph and simple graph do not necessary have the same "total" (active & free) number,
  1459. // so pass "graph->total" (or "graph->edges->total") to skip that check
  1460. test_seq_block_consistence( struct_idx, (CvSeq*)graph, graph->total );
  1461. test_seq_block_consistence( struct_idx, (CvSeq*)graph->edges, graph->edges->total );
  1462. update_progressbar();
  1463. }
  1464. return 0;
  1465. }
  1466. void Core_GraphTest::run( int )
  1467. {
  1468. try
  1469. {
  1470. RNG& rng = ts->get_rng();
  1471. int i, k;
  1472. double t;
  1473. clear();
  1474. test_progress = -1;
  1475. simple_struct.resize(struct_count, 0);
  1476. cxcore_struct.resize(struct_count, 0);
  1477. for( gen = 0; gen < generations; gen++ )
  1478. {
  1479. struct_idx = iter = -1;
  1480. t = cvtest::randReal(rng)*(max_log_storage_block_size - min_log_storage_block_size) + min_log_storage_block_size;
  1481. int block_size = cvRound( exp(t * CV_LOG2) );
  1482. block_size = MAX(block_size, (int)(sizeof(CvGraph) + sizeof(CvMemBlock) + sizeof(CvSeqBlock)));
  1483. storage.reset(cvCreateMemStorage(block_size));
  1484. for( i = 0; i < struct_count; i++ )
  1485. {
  1486. int pure_elem_size[2], elem_size[2];
  1487. int is_oriented = (gen + i) % 2;
  1488. for( k = 0; k < 2; k++ )
  1489. {
  1490. t = cvtest::randReal(rng)*(max_log_elem_size - min_log_elem_size) + min_log_elem_size;
  1491. int pe = cvRound( exp(t * CV_LOG2) ) - 1; // pure_elem_size==0 does also make sense
  1492. int delta = k == 0 ? sizeof(CvGraphVtx) : sizeof(CvGraphEdge);
  1493. int e = pe + delta;
  1494. e = (e + sizeof(size_t) - 1) & ~(sizeof(size_t)-1);
  1495. e = MIN( e, (int)(storage->block_size - sizeof(CvMemBlock) -
  1496. sizeof(CvSeqBlock) - sizeof(void*)) );
  1497. pe = MIN(pe, e - delta);
  1498. pure_elem_size[k] = pe;
  1499. elem_size[k] = e;
  1500. }
  1501. cvTsReleaseSimpleGraph( (CvTsSimpleGraph**)&simple_struct[i] );
  1502. simple_struct[i] = cvTsCreateSimpleGraph( max_struct_size/4, pure_elem_size[0],
  1503. pure_elem_size[1], is_oriented );
  1504. cxcore_struct[i] = cvCreateGraph( is_oriented ? CV_ORIENTED_GRAPH : CV_GRAPH,
  1505. sizeof(CvGraph), elem_size[0], elem_size[1],
  1506. storage );
  1507. }
  1508. if( test_graph_ops( iterations*10 ) < 0 )
  1509. return;
  1510. storage.release();
  1511. }
  1512. }
  1513. catch(const int &)
  1514. {
  1515. }
  1516. }
  1517. //////////// graph scan test //////////////
  1518. class Core_GraphScanTest : public Core_DynStructBaseTest
  1519. {
  1520. public:
  1521. Core_GraphScanTest();
  1522. void run( int );
  1523. protected:
  1524. //int test_seq_block_consistence( int struct_idx );
  1525. int create_random_graph( int );
  1526. };
  1527. Core_GraphScanTest::Core_GraphScanTest()
  1528. {
  1529. iterations = 100;
  1530. struct_count = 1;
  1531. }
  1532. int Core_GraphScanTest::create_random_graph( int _struct_idx )
  1533. {
  1534. RNG& rng = ts->get_rng();
  1535. int is_oriented = cvtest::randInt(rng) % 2;
  1536. int i, vtx_count = cvtest::randInt(rng) % max_struct_size;
  1537. int edge_count = cvtest::randInt(rng) % MAX(vtx_count*20, 1);
  1538. CvGraph* graph;
  1539. struct_idx = _struct_idx;
  1540. cxcore_struct[_struct_idx] = graph =
  1541. cvCreateGraph(is_oriented ? CV_ORIENTED_GRAPH : CV_GRAPH,
  1542. sizeof(CvGraph), sizeof(CvGraphVtx),
  1543. sizeof(CvGraphEdge), storage );
  1544. for( i = 0; i < vtx_count; i++ )
  1545. cvGraphAddVtx( graph );
  1546. CV_Assert( graph->active_count == vtx_count );
  1547. for( i = 0; i < edge_count; i++ )
  1548. {
  1549. int j = cvtest::randInt(rng) % vtx_count;
  1550. int k = cvtest::randInt(rng) % vtx_count;
  1551. if( j != k )
  1552. cvGraphAddEdge( graph, j, k );
  1553. }
  1554. CV_Assert( graph->active_count == vtx_count && graph->edges->active_count <= edge_count );
  1555. return 0;
  1556. }
  1557. void Core_GraphScanTest::run( int )
  1558. {
  1559. CvGraphScanner* scanner = 0;
  1560. try
  1561. {
  1562. RNG& rng = ts->get_rng();
  1563. vector<uchar> vtx_mask, edge_mask;
  1564. double t;
  1565. int i;
  1566. clear();
  1567. test_progress = -1;
  1568. cxcore_struct.resize(struct_count, 0);
  1569. for( gen = 0; gen < generations; gen++ )
  1570. {
  1571. struct_idx = iter = -1;
  1572. t = cvtest::randReal(rng)*(max_log_storage_block_size - min_log_storage_block_size) + min_log_storage_block_size;
  1573. int storage_blocksize = cvRound( exp(t * CV_LOG2) );
  1574. storage_blocksize = MAX(storage_blocksize, (int)(sizeof(CvGraph) + sizeof(CvMemBlock) + sizeof(CvSeqBlock)));
  1575. storage_blocksize = MAX(storage_blocksize, (int)(sizeof(CvGraphEdge) + sizeof(CvMemBlock) + sizeof(CvSeqBlock)));
  1576. storage_blocksize = MAX(storage_blocksize, (int)(sizeof(CvGraphVtx) + sizeof(CvMemBlock) + sizeof(CvSeqBlock)));
  1577. storage.reset(cvCreateMemStorage(storage_blocksize));
  1578. if( gen == 0 )
  1579. {
  1580. // special regression test for one sample graph.
  1581. // !!! ATTENTION !!! The test relies on the particular order of the inserted edges
  1582. // (LIFO: the edge inserted last goes first in the list of incident edges).
  1583. // if it is changed, the test will have to be modified.
  1584. int vtx_count = -1, edge_count = 0, edges[][3] =
  1585. {
  1586. {0,4,'f'}, {0,1,'t'}, {1,4,'t'}, {1,2,'t'}, {2,3,'t'}, {4,3,'c'}, {3,1,'b'},
  1587. {5,7,'t'}, {7,5,'b'}, {5,6,'t'}, {6,0,'c'}, {7,6,'c'}, {6,4,'c'}, {-1,-1,0}
  1588. };
  1589. CvGraph* graph = cvCreateGraph( CV_ORIENTED_GRAPH, sizeof(CvGraph),
  1590. sizeof(CvGraphVtx), sizeof(CvGraphEdge), storage );
  1591. for( i = 0; edges[i][0] >= 0; i++ )
  1592. {
  1593. vtx_count = MAX( vtx_count, edges[i][0] );
  1594. vtx_count = MAX( vtx_count, edges[i][1] );
  1595. }
  1596. vtx_count++;
  1597. for( i = 0; i < vtx_count; i++ )
  1598. cvGraphAddVtx( graph );
  1599. for( i = 0; edges[i][0] >= 0; i++ )
  1600. {
  1601. CvGraphEdge* edge;
  1602. cvGraphAddEdge( graph, edges[i][0], edges[i][1], 0, &edge );
  1603. edge->weight = (float)edges[i][2];
  1604. }
  1605. edge_count = i;
  1606. scanner = cvCreateGraphScanner( graph, 0, CV_GRAPH_ALL_ITEMS );
  1607. for(;;)
  1608. {
  1609. int code, a = -1, b = -1;
  1610. const char* event = "";
  1611. code = cvNextGraphItem( scanner );
  1612. switch( code )
  1613. {
  1614. case CV_GRAPH_VERTEX:
  1615. event = "Vertex";
  1616. vtx_count--;
  1617. a = cvGraphVtxIdx( graph, scanner->vtx );
  1618. break;
  1619. case CV_GRAPH_TREE_EDGE:
  1620. event = "Tree Edge";
  1621. edge_count--;
  1622. CV_TS_SEQ_CHECK_CONDITION( scanner->edge->weight == (float)'t',
  1623. "Invalid edge type" );
  1624. a = cvGraphVtxIdx( graph, scanner->vtx );
  1625. b = cvGraphVtxIdx( graph, scanner->dst );
  1626. break;
  1627. case CV_GRAPH_BACK_EDGE:
  1628. event = "Back Edge";
  1629. edge_count--;
  1630. CV_TS_SEQ_CHECK_CONDITION( scanner->edge->weight == (float)'b',
  1631. "Invalid edge type" );
  1632. a = cvGraphVtxIdx( graph, scanner->vtx );
  1633. b = cvGraphVtxIdx( graph, scanner->dst );
  1634. break;
  1635. case CV_GRAPH_CROSS_EDGE:
  1636. event = "Cross Edge";
  1637. edge_count--;
  1638. CV_TS_SEQ_CHECK_CONDITION( scanner->edge->weight == (float)'c',
  1639. "Invalid edge type" );
  1640. a = cvGraphVtxIdx( graph, scanner->vtx );
  1641. b = cvGraphVtxIdx( graph, scanner->dst );
  1642. break;
  1643. case CV_GRAPH_FORWARD_EDGE:
  1644. event = "Forward Edge";
  1645. edge_count--;
  1646. CV_TS_SEQ_CHECK_CONDITION( scanner->edge->weight == (float)'f',
  1647. "Invalid edge type" );
  1648. a = cvGraphVtxIdx( graph, scanner->vtx );
  1649. b = cvGraphVtxIdx( graph, scanner->dst );
  1650. break;
  1651. case CV_GRAPH_BACKTRACKING:
  1652. event = "Backtracking";
  1653. a = cvGraphVtxIdx( graph, scanner->vtx );
  1654. break;
  1655. case CV_GRAPH_NEW_TREE:
  1656. event = "New search tree";
  1657. break;
  1658. case CV_GRAPH_OVER:
  1659. event = "End of procedure";
  1660. break;
  1661. default:
  1662. CV_TS_SEQ_CHECK_CONDITION( 0, "Invalid code appeared during graph scan" );
  1663. }
  1664. ts->printf( cvtest::TS::LOG, "%s", event );
  1665. if( a >= 0 )
  1666. {
  1667. if( b >= 0 )
  1668. ts->printf( cvtest::TS::LOG, ": (%d,%d)", a, b );
  1669. else
  1670. ts->printf( cvtest::TS::LOG, ": %d", a );
  1671. }
  1672. ts->printf( cvtest::TS::LOG, "\n" );
  1673. if( code < 0 )
  1674. break;
  1675. }
  1676. CV_TS_SEQ_CHECK_CONDITION( vtx_count == 0 && edge_count == 0,
  1677. "Not every vertex/edge has been visited" );
  1678. update_progressbar();
  1679. cvReleaseGraphScanner( &scanner );
  1680. }
  1681. // for a random graph the test just checks that every graph vertex and
  1682. // every edge is vitisted during the scan
  1683. for( iter = 0; iter < iterations; iter++ )
  1684. {
  1685. create_random_graph(0);
  1686. CvGraph* graph = (CvGraph*)cxcore_struct[0];
  1687. // iterate twice to check that scanner doesn't damage the graph
  1688. for( i = 0; i < 2; i++ )
  1689. {
  1690. CvGraphVtx* start_vtx = cvtest::randInt(rng) % 2 || graph->active_count == 0 ? 0 :
  1691. cvGetGraphVtx( graph, cvtest::randInt(rng) % graph->active_count );
  1692. scanner = cvCreateGraphScanner( graph, start_vtx, CV_GRAPH_ALL_ITEMS );
  1693. vtx_mask.resize(0);
  1694. vtx_mask.resize(graph->active_count, 0);
  1695. edge_mask.resize(0);
  1696. edge_mask.resize(graph->edges->active_count, 0);
  1697. for(;;)
  1698. {
  1699. int code = cvNextGraphItem( scanner );
  1700. if( code == CV_GRAPH_OVER )
  1701. break;
  1702. else if( code & CV_GRAPH_ANY_EDGE )
  1703. {
  1704. int edge_idx = scanner->edge->flags & CV_SET_ELEM_IDX_MASK;
  1705. CV_TS_SEQ_CHECK_CONDITION( edge_idx < graph->edges->active_count &&
  1706. edge_mask[edge_idx] == 0,
  1707. "The edge is not found or visited for the second time" );
  1708. edge_mask[edge_idx] = 1;
  1709. }
  1710. else if( code & CV_GRAPH_VERTEX )
  1711. {
  1712. int vtx_idx = scanner->vtx->flags & CV_SET_ELEM_IDX_MASK;
  1713. CV_TS_SEQ_CHECK_CONDITION( vtx_idx < graph->active_count &&
  1714. vtx_mask[vtx_idx] == 0,
  1715. "The vtx is not found or visited for the second time" );
  1716. vtx_mask[vtx_idx] = 1;
  1717. }
  1718. }
  1719. cvReleaseGraphScanner( &scanner );
  1720. CV_TS_SEQ_CHECK_CONDITION( cvtest::norm(Mat(vtx_mask),CV_L1) == graph->active_count &&
  1721. cvtest::norm(Mat(edge_mask),CV_L1) == graph->edges->active_count,
  1722. "Some vertices or edges have not been visited" );
  1723. update_progressbar();
  1724. }
  1725. cvClearMemStorage( storage );
  1726. }
  1727. storage.release();
  1728. }
  1729. }
  1730. catch(const int &)
  1731. {
  1732. }
  1733. }
  1734. TEST(Core_DS_Seq, basic_operations) { Core_SeqBaseTest test; test.safe_run(); }
  1735. TEST(Core_DS_Seq, sort_invert) { Core_SeqSortInvTest test; test.safe_run(); }
  1736. TEST(Core_DS_Set, basic_operations) { Core_SetTest test; test.safe_run(); }
  1737. TEST(Core_DS_Graph, basic_operations) { Core_GraphTest test; test.safe_run(); }
  1738. TEST(Core_DS_Graph, scan) { Core_GraphScanTest test; test.safe_run(); }
  1739. }} // namespace