rtlnktest.cpp 68 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483
  1. /*##############################################################################
  2. you may not use this file except in compliance with the License.
  3. You may obtain a copy of the License at
  4. http://www.apache.org/licenses/LICENSE-2.0
  5. Unless required by applicable law or agreed to in writing, software
  6. distributed under the License is distributed on an "AS IS" BASIS,
  7. WITHOUT WARRANTIES OR getValue OF ANY KIND, either express or implied.
  8. See the License for the specific language governing permissions and
  9. limitations under the License.
  10. ############################################################################## */
  11. #include <initializer_list>
  12. #include "jlib.hpp"
  13. #include "jdebug.hpp"
  14. #include "jsort.hpp"
  15. #include "jexcept.hpp"
  16. #include "rtlnewkey.hpp"
  17. #include "eclrtl_imp.hpp"
  18. #include "rtlrecord.hpp"
  19. #include "rtlkey.hpp"
  20. #include "rtlnewkey.hpp"
  21. #include "rtlfield.hpp"
  22. #include "rtldynfield.hpp"
  23. #ifdef _USE_CPPUNIT
  24. #include <cppunit/extensions/HelperMacros.h>
  25. class InMemoryRows
  26. {
  27. public:
  28. InMemoryRows(size_t _countRows, const byte * * _rows, const RtlRecord & _record)
  29. : countRows(_countRows), rows(_rows), record(_record)
  30. {
  31. }
  32. const byte * queryRow(unsigned i) const { return rows[i]; }
  33. size_t numRows() const { return countRows; }
  34. const RtlRecord & queryRecord() const { return record; }
  35. protected:
  36. size_t countRows;
  37. const byte * * rows;
  38. const RtlRecord & record;
  39. };
  40. //Always has an even number of transitions
  41. //Null transitions can be used at the start and end of the ranges to map anything
  42. //equality conditions repeat the transition
  43. class InMemoryRowCursor : public ISourceRowCursor
  44. {
  45. public:
  46. InMemoryRowCursor(InMemoryRows & _source) : source(_source), seekRow(_source.queryRecord())
  47. {
  48. }
  49. virtual const byte * findNext(const RowCursor & search) override
  50. {
  51. size_t numRows = source.numRows();
  52. if (numRows == 0)
  53. return nullptr;
  54. size_t high = numRows;
  55. size_t low = 0; // Could be cur
  56. bool scanOnNext = false;
  57. if (cur != 0 && scanOnNext)
  58. {
  59. //MORE: The next match is likely to be close, so first of all look for a match in the next few rows
  60. //An always searching forwards, so can guarantee that it follows cur > low
  61. }
  62. //Find the value of low,high where all rows 0..low-1 are < search and rows low..max are >= search
  63. while (low<high)
  64. {
  65. size_t mid = low + (high - low) / 2;
  66. seekRow.setRow(source.queryRow(mid), search.numFilterFields());
  67. int rc = search.compareNext(seekRow); // compare seekRow with the row we are hoping to find
  68. if (rc < 0)
  69. low = mid + 1; // if this row is lower than the seek row, exclude mid from the potential positions
  70. else
  71. high = mid; // otherwise exclude all above mid from the potential positions.
  72. }
  73. cur = low;
  74. if (low == numRows)
  75. return nullptr;
  76. return source.queryRow(cur);
  77. }
  78. virtual const byte * next() override
  79. {
  80. cur++;
  81. if (cur == source.numRows())
  82. return nullptr;
  83. return source.queryRow(cur);
  84. }
  85. virtual void reset() override
  86. {
  87. cur = 0;
  88. seekRow.setRow(nullptr);
  89. }
  90. protected:
  91. size_t cur = 0;
  92. InMemoryRows & source;
  93. RtlDynRow seekRow;
  94. };
  95. /*
  96. class IStdException : extends std::exception
  97. {
  98. Owned<IException> jException;
  99. public:
  100. IStdException(IException *E) : jException(E) {};
  101. };
  102. */
  103. //Scan a set of rows to find the matches - used to check that the keyed operations are correct
  104. class RowScanner
  105. {
  106. public:
  107. RowScanner(const RtlRecord & _info, RowFilter & _filter, const PointerArray & _rows) : rows(_rows), curRow(_info, nullptr), filter(_filter)
  108. {
  109. }
  110. bool first()
  111. {
  112. return resolveNext(0);
  113. }
  114. bool next()
  115. {
  116. return resolveNext(curIndex+1);
  117. }
  118. bool resolveNext(unsigned next)
  119. {
  120. while (next < rows.ordinality())
  121. {
  122. curRow.setRow(rows.item(next));
  123. if (filter.matches(curRow))
  124. {
  125. curIndex = next;
  126. return true;
  127. }
  128. next++;
  129. }
  130. curIndex = next;
  131. return false;
  132. }
  133. const RtlRow & queryRow() const { return curRow; }
  134. protected:
  135. const PointerArray & rows;
  136. RtlDynRow curRow;
  137. RowFilter & filter;
  138. unsigned curIndex = 0;
  139. };
  140. static void addRange(IValueSet * set, const char * lower, const char * upper, size32_t subLength = MatchFullString)
  141. {
  142. Owned<IValueTransition> lowerBound = lower ? set->createUtf8Transition(CMPge, rtlUtf8Length(strlen(lower), lower), lower, subLength) : nullptr;
  143. Owned<IValueTransition> upperBound = upper ? set->createUtf8Transition(CMPle, rtlUtf8Length(strlen(upper), upper), upper, subLength) : nullptr;
  144. set->addRange(lowerBound, upperBound);
  145. };
  146. class RawRowCompare : public ICompare
  147. {
  148. public:
  149. RawRowCompare(const RtlRecord & _record) : record(_record) {}
  150. virtual int docompare(const void * left,const void * right) const
  151. {
  152. return record.compare((const byte *)left, (const byte *)right);
  153. }
  154. const RtlRecord & record;
  155. };
  156. class ValueSetTest : public CppUnit::TestFixture
  157. {
  158. CPPUNIT_TEST_SUITE(ValueSetTest);
  159. CPPUNIT_TEST(testBounds);
  160. CPPUNIT_TEST(testSubStrings);
  161. CPPUNIT_TEST(testKeyed2);
  162. CPPUNIT_TEST(testRange);
  163. CPPUNIT_TEST(testSerialize);
  164. CPPUNIT_TEST(testUnion);
  165. CPPUNIT_TEST(testExclude);
  166. CPPUNIT_TEST(testInverse);
  167. CPPUNIT_TEST(testIntersect);
  168. CPPUNIT_TEST(testStr2);
  169. CPPUNIT_TEST(testFilter);
  170. CPPUNIT_TEST(testKeyed1);
  171. CPPUNIT_TEST_SUITE_END();
  172. protected:
  173. void checkSet(const IValueSet * set, const char * expected)
  174. {
  175. StringBuffer temp;
  176. set->serialize(temp);
  177. if (!streq(expected, temp))
  178. CPPUNIT_ASSERT_EQUAL(expected, temp.str());
  179. }
  180. void testRange(const RtlTypeInfo & type, const char * low, const char * high, const char * expected)
  181. {
  182. Owned<IValueSet> set = createValueSet(type);
  183. addRange(set, low, high);
  184. checkSet(set, expected);
  185. }
  186. void testRangeStr1(const char * low, const char * high, const char * expected)
  187. {
  188. RtlStringTypeInfo str1(type_string, 1);
  189. testRange(str1, low, high, expected);
  190. }
  191. void testRangeInt2(const char * low, const char * high, const char * expected)
  192. {
  193. RtlIntTypeInfo int2(type_int, 2);
  194. testRange(int2, low, high, expected);
  195. }
  196. void testRangeStrX(const char * low, const char * high, const char * expected)
  197. {
  198. RtlStringTypeInfo type(type_string|RFTMunknownsize, 0);
  199. testRange(type, low, high, expected);
  200. }
  201. void testRangeUniX(const char * low, const char * high, const char * expected)
  202. {
  203. RtlUnicodeTypeInfo type(type_string|RFTMunknownsize, 0, "");
  204. testRange(type, low, high, expected);
  205. }
  206. void testRange()
  207. {
  208. testRangeStr1("A","Z","['A','Z']");
  209. testRangeStr1("X","z","['X','z']");
  210. testRangeStr1("Z","X","");
  211. testRangeStr1(nullptr, "z","(,'z']");
  212. testRangeStr1("Z", nullptr,"['Z',)");
  213. testRangeStr1("A", "A","['A']");
  214. testRangeStr1(nullptr, nullptr,"(,)");
  215. testRangeStr1("é", "é","['é']"); // Test utf8 translation
  216. testRangeStr1("AB", "ZX","['A','Z']");
  217. testRangeInt2("0","1","[0,1]");
  218. testRangeInt2("-1","1","[-1,1]");
  219. testRangeInt2("-32768","32767","[-32768,32767]");
  220. testRangeInt2("32768","0","[-32768,0]");
  221. testRangeStrX("A", "Z","['A','Z']");
  222. testRangeStrX("AB", "ZX","['AB','ZX']");
  223. testRangeStrX("éèabc", "ab","");
  224. testRangeStrX("a'b", "éèabc", "['a\\'b','éèabc']");
  225. testRangeUniX("A", "Z","['A','Z']");
  226. testRangeUniX("AB", "ZX","['AB','ZX']");
  227. testRangeUniX("éèabc", "ab","");
  228. testRangeUniX("a'b", "éèabc", "['a\\'b','éèabc']");
  229. }
  230. void testSerialize(const RtlTypeInfo & type, const char * filter, const char * expected = nullptr)
  231. {
  232. Owned<IValueSet> set = createValueSet(type);
  233. deserializeSet(*set, filter);
  234. checkSet(set, expected ? expected : filter);
  235. MemoryBuffer mb;
  236. set->serialize(mb);
  237. Owned<IValueSet> newset = createValueSet(type, mb);
  238. checkSet(newset, expected ? expected : filter);
  239. CPPUNIT_ASSERT(set->equals(*newset));
  240. StringBuffer s;
  241. set->serialize(s);
  242. Owned<IValueSet> newset2 = createValueSet(type);
  243. deserializeSet(*newset2, s);
  244. CPPUNIT_ASSERT(set->equals(*newset2));
  245. }
  246. void testUnion(const RtlTypeInfo & type, const char * filter, const char * next, const char * expected)
  247. {
  248. Owned<IValueSet> set = createValueSet(type);
  249. deserializeSet(*set, filter);
  250. deserializeSet(*set, next);
  251. checkSet(set, expected);
  252. //test the arguments in the opposite order
  253. Owned<IValueSet> set2 = createValueSet(type);
  254. deserializeSet(*set2, next);
  255. deserializeSet(*set2, filter);
  256. checkSet(set, expected);
  257. //test the arguments in the opposite order
  258. Owned<IValueSet> set3a = createValueSet(type);
  259. Owned<IValueSet> set3b = createValueSet(type);
  260. deserializeSet(*set3a, next);
  261. deserializeSet(*set3b, filter);
  262. set3a->unionSet(set3b);
  263. checkSet(set3a, expected);
  264. }
  265. void testSerialize()
  266. {
  267. RtlStringTypeInfo str1(type_string, 1);
  268. RtlIntTypeInfo int2(type_int, 2);
  269. RtlIntTypeInfo int8(type_int, 8);
  270. RtlSwapIntTypeInfo swapint2(type_int, 2);
  271. RtlSwapIntTypeInfo swapint8(type_int, 8);
  272. RtlKeyedIntTypeInfo keyedint8(type_keyedint, 8, &swapint8);
  273. RtlStringTypeInfo strx(type_string|RFTMunknownsize, 0);
  274. RtlUtf8TypeInfo utf8(type_utf8|RFTMunknownsize, 0, nullptr);
  275. testSerialize(int2, "[123]");
  276. testSerialize(int2, "(123,234]");
  277. testSerialize(int2, "[123,234)");
  278. testSerialize(int2, "(123,234)");
  279. testSerialize(int2, "(,234)");
  280. testSerialize(int2, "(128,)");
  281. testSerialize(int2, "(,)");
  282. testSerialize(int2, "(123,234),(456,567)");
  283. testSerialize(int2, "(456,567),(123,234)", "(123,234),(456,567)");
  284. testSerialize(swapint2, "[123]");
  285. testSerialize(swapint2, "(123,234]");
  286. testSerialize(swapint2, "[123,234)");
  287. testSerialize(swapint2, "(123,234)");
  288. testSerialize(swapint2, "(,234)");
  289. testSerialize(swapint2, "(128,)");
  290. testSerialize(swapint2, "(,)");
  291. testSerialize(swapint2, "(123,234),(456,567)");
  292. testSerialize(swapint2, "(456,567),(123,234)", "(123,234),(456,567)");
  293. testSerialize(int8, "[9223372036854775807]");
  294. testSerialize(int8, "[-9223372036854775808]");
  295. testSerialize(swapint8, "[9223372036854775807]");
  296. testSerialize(swapint8, "[-9223372036854775808]");
  297. testSerialize(keyedint8, "[10]");
  298. testSerialize(keyedint8, "[-10]");
  299. testSerialize(str1, "['A']");
  300. testSerialize(str1, "[',']");
  301. testSerialize(str1, "['\\'']");
  302. testSerialize(str1, "['\\u0041']", "['A']");
  303. testSerialize(str1, "['\\n']");
  304. testSerialize(utf8, "['\\u611b']", "['愛']");
  305. testSerialize(strx, "['\\'\\'','}']");
  306. testSerialize(str1, "[A]", "['A']");
  307. testSerialize(int2, "(123]", "");
  308. testSerialize(int2, "[123)", "");
  309. testSerialize(int2, "[1,0]", "");
  310. }
  311. void testUnion()
  312. {
  313. RtlIntTypeInfo int2(type_int, 2);
  314. testSerialize(int2, "[3,5],[5,7]", "[3,7]");
  315. testSerialize(int2, "[3,5],(5,7]", "[3,7]");
  316. testSerialize(int2, "[3,5),[5,7]", "[3,7]");
  317. testSerialize(int2, "[3,5),(5,7]");
  318. testSerialize(int2, "[4],[4]", "[4]");
  319. testSerialize(int2, "[4,5],[4]", "[4,5]");
  320. testSerialize(int2, "[4,5],[5]", "[4,5]");
  321. testUnion(int2, "[3,5]", "[,1]", "(,1],[3,5]");
  322. testUnion(int2, "[3,5]", "[,3]", "(,5]");
  323. testUnion(int2, "[3,5]", "[,4]", "(,5]");
  324. testUnion(int2, "[3,5]", "[,]", "(,)");
  325. testUnion(int2, "[3,5]", "[1,)", "[1,)");
  326. testUnion(int2, "[3,5]", "[3,)", "[3,)");
  327. testUnion(int2, "[3,5]", "[5,)", "[3,)");
  328. testUnion(int2, "[3,5]", "(5,)", "[3,)");
  329. testUnion(int2, "[3,5]", "[6,)", "[3,5],[6,)");
  330. testUnion(int2, "[3,5]", "(6,)", "[3,5],(6,)");
  331. testUnion(int2, "[4,7],[12,15]", "[1,1]", "[1],[4,7],[12,15]");
  332. testUnion(int2, "[4,7],[12,15]", "[1,4)", "[1,7],[12,15]");
  333. testUnion(int2, "[4,7],[12,15]", "[1,4]", "[1,7],[12,15]");
  334. testUnion(int2, "[4,7],[12,15]", "[1,5)", "[1,7],[12,15]");
  335. testUnion(int2, "[4,7],[12,15]", "[1,7)", "[1,7],[12,15]");
  336. testUnion(int2, "[4,7],[12,15]", "[1,7]", "[1,7],[12,15]");
  337. testUnion(int2, "[4,7],[12,15]", "[1,8]", "[1,8],[12,15]");
  338. testUnion(int2, "[4,7],[12,15]", "[1,12)", "[1,15]");
  339. testUnion(int2, "[4,7],[12,15]", "[1,12]", "[1,15]");
  340. testUnion(int2, "[4,7],[12,15]", "[1,14]", "[1,15]");
  341. testUnion(int2, "[4,7],[12,15]", "[1,15]", "[1,15]");
  342. testUnion(int2, "[4,7],[12,15]", "[1,16]", "[1,16]");
  343. testUnion(int2, "[4,7],[12,15]", "[1,17]", "[1,17]");
  344. testUnion(int2, "[4,7],[12,15]", "(4,5)", "[4,7],[12,15]");
  345. testUnion(int2, "[4,7],[12,15]", "(4,7)", "[4,7],[12,15]");
  346. testUnion(int2, "[4,7],[12,15]", "(4,7]", "[4,7],[12,15]");
  347. testUnion(int2, "[4,7],[12,15]", "(4,8]", "[4,8],[12,15]");
  348. testUnion(int2, "[4,7],[12,15]", "(4,12)", "[4,15]");
  349. testUnion(int2, "[4,7],[12,15]", "(4,12]", "[4,15]");
  350. testUnion(int2, "[4,7],[12,15]", "[4,4]", "[4,7],[12,15]");
  351. testUnion(int2, "[4,7],[12,15]", "[4,5)", "[4,7],[12,15]");
  352. testUnion(int2, "[4,7],[12,15]", "[4,7)", "[4,7],[12,15]");
  353. testUnion(int2, "[4,7],[12,15]", "[4,7]", "[4,7],[12,15]");
  354. testUnion(int2, "[4,7],[12,15]", "[4,8]", "[4,8],[12,15]");
  355. testUnion(int2, "[4,7],[12,15]", "[4,12)", "[4,15]");
  356. testUnion(int2, "[4,7],[12,15]", "[4,12]", "[4,15]");
  357. testUnion(int2, "[4,7],[12,15]", "[4,14]", "[4,15]");
  358. testUnion(int2, "[4,7],[12,15]", "[4,15]", "[4,15]");
  359. testUnion(int2, "[4,7],[12,15]", "[4,16]", "[4,16]");
  360. testUnion(int2, "[4,7],[12,15]", "[4,17]", "[4,17]");
  361. testUnion(int2, "[4,7],[12,15]", "(5,7)", "[4,7],[12,15]");
  362. testUnion(int2, "[4,7],[12,15]", "(5,7]", "[4,7],[12,15]");
  363. testUnion(int2, "[4,7],[12,15]", "(5,8]", "[4,8],[12,15]");
  364. testUnion(int2, "[4,7],[12,15]", "(5,12)", "[4,15]");
  365. testUnion(int2, "[4,7],[12,15]", "(5,12]", "[4,15]");
  366. testUnion(int2, "[4,7],[12,15]", "(5,14]", "[4,15]");
  367. testUnion(int2, "[4,7],[12,15]", "(5,15]", "[4,15]");
  368. testUnion(int2, "[4,7],[12,15]", "(5,17]", "[4,17]");
  369. testUnion(int2, "[4,7],[12,15]", "(7,8]", "[4,8],[12,15]");
  370. testUnion(int2, "[4,7],[12,15]", "(7,8)", "[4,8),[12,15]");
  371. testUnion(int2, "[4,7],[12,15]", "(7,12)", "[4,15]");
  372. testUnion(int2, "[4,7],[12,15]", "(7,12]", "[4,15]");
  373. testUnion(int2, "[4,7],[12,15]", "(7,14]", "[4,15]");
  374. testUnion(int2, "[4,7],[12,15]", "(7,15]", "[4,15]");
  375. testUnion(int2, "[4,7],[12,15]", "(7,17]", "[4,17]");
  376. testUnion(int2, "[4,7],[12,15]", "[7,7]", "[4,7],[12,15]");
  377. testUnion(int2, "[4,7],[12,15]", "[7,8]", "[4,8],[12,15]");
  378. testUnion(int2, "[4,7],[12,15]", "[7,12)", "[4,15]");
  379. testUnion(int2, "[4,7],[12,15]", "[7,17]", "[4,17]");
  380. testUnion(int2, "[4,7],[12,15]", "[8,8]", "[4,7],[8],[12,15]");
  381. testUnion(int2, "[4,7],[12,15]", "[8,12)", "[4,7],[8,15]");
  382. testUnion(int2, "[4,7],[12,15]", "[8,12]", "[4,7],[8,15]");
  383. testUnion(int2, "[4,7],[12,15]", "[8,14]", "[4,7],[8,15]");
  384. testUnion(int2, "[4,7],[12,15]", "[8,15]", "[4,7],[8,15]");
  385. testUnion(int2, "[4,7],[12,15]", "[8,16]", "[4,7],[8,16]");
  386. testUnion(int2, "[4,7],[12,15]", "[8,17]", "[4,7],[8,17]");
  387. testUnion(int2, "[4,7],[12,15]", "(8,11)", "[4,7],(8,11),[12,15]");
  388. testUnion(int2, "[4,7],[12,15]", "(8,12)", "[4,7],(8,15]");
  389. testUnion(int2, "[4,7],[12,15]", "(8,12]", "[4,7],(8,15]");
  390. testUnion(int2, "[4,7],[12,15]", "(8,14]", "[4,7],(8,15]");
  391. testUnion(int2, "[4,7],[12,15]", "(8,15]", "[4,7],(8,15]");
  392. testUnion(int2, "[4,7],[12,15]", "(8,16]", "[4,7],(8,16]");
  393. testUnion(int2, "[4,7],[12,15]", "(8,17]", "[4,7],(8,17]");
  394. testUnion(int2, "[4,7],[12,15]", "(12,14]", "[4,7],[12,15]");
  395. testUnion(int2, "[4,7],[12,15]", "(12,15]", "[4,7],[12,15]");
  396. testUnion(int2, "[4,7],[12,15]", "(12,16]", "[4,7],[12,16]");
  397. testUnion(int2, "[4,7],[12,15]", "(12,17]", "[4,7],[12,17]");
  398. testUnion(int2, "[4,7],[12,15]", "[12,12]", "[4,7],[12,15]");
  399. testUnion(int2, "[4,7],[12,15]", "[12,14]", "[4,7],[12,15]");
  400. testUnion(int2, "[4,7],[12,15]", "[12,15]", "[4,7],[12,15]");
  401. testUnion(int2, "[4,7],[12,15]", "[12,16]", "[4,7],[12,16]");
  402. testUnion(int2, "[4,7],[12,15]", "[12,17]", "[4,7],[12,17]");
  403. testUnion(int2, "[4,7],[12,15]", "[14,14]", "[4,7],[12,15]");
  404. testUnion(int2, "[4,7],[12,15]", "[14,15]", "[4,7],[12,15]");
  405. testUnion(int2, "[4,7],[12,15]", "[14,16]", "[4,7],[12,16]");
  406. testUnion(int2, "[4,7],[12,15]", "[14,17]", "[4,7],[12,17]");
  407. testUnion(int2, "[4,7],[12,15]", "[15]", "[4,7],[12,15]");
  408. testUnion(int2, "[4,7],[12,15]", "[15,16]", "[4,7],[12,16]");
  409. testUnion(int2, "[4,7],[12,15]", "[15,17]", "[4,7],[12,17]");
  410. testUnion(int2, "[4,7],[12,15]", "[15,17)", "[4,7],[12,17)");
  411. testUnion(int2, "[4,7],[12,15]", "[16]", "[4,7],[12,15],[16]");
  412. testUnion(int2, "[4,7],[12,15]", "[16,17]", "[4,7],[12,15],[16,17]");
  413. testUnion(int2, "[4,7],[12,15]", "[17]", "[4,7],[12,15],[17]");
  414. testUnion(int2, "(4,7),(12,15)", "[1,1]", "[1],(4,7),(12,15)");
  415. testUnion(int2, "(4,7),(12,15)", "[1,4)", "[1,4),(4,7),(12,15)");
  416. testUnion(int2, "(4,7),(12,15)", "[1,4]", "[1,7),(12,15)");
  417. testUnion(int2, "(4,7),(12,15)", "[1,5)", "[1,7),(12,15)");
  418. testUnion(int2, "(4,7),(12,15)", "[1,7)", "[1,7),(12,15)");
  419. testUnion(int2, "(4,7),(12,15)", "[1,7]", "[1,7],(12,15)");
  420. testUnion(int2, "(4,7),(12,15)", "[1,8]", "[1,8],(12,15)");
  421. testUnion(int2, "(4,7),(12,15)", "[1,12)", "[1,12),(12,15)");
  422. testUnion(int2, "(4,7),(12,15)", "[1,12]", "[1,15)");
  423. testUnion(int2, "(4,7),(12,15)", "[1,14]", "[1,15)");
  424. testUnion(int2, "(4,7),(12,15)", "[1,15]", "[1,15]");
  425. testUnion(int2, "(4,7),(12,15)", "[1,16]", "[1,16]");
  426. testUnion(int2, "(4,7),(12,15)", "[1,17]", "[1,17]");
  427. testUnion(int2, "(4,7),(12,15)", "(4,5)", "(4,7),(12,15)");
  428. testUnion(int2, "(4,7),(12,15)", "(4,7)", "(4,7),(12,15)");
  429. testUnion(int2, "(4,7),(12,15)", "(4,7]", "(4,7],(12,15)");
  430. testUnion(int2, "(4,7),(12,15)", "(4,8]", "(4,8],(12,15)");
  431. testUnion(int2, "(4,7),(12,15)", "(4,12)", "(4,12),(12,15)");
  432. testUnion(int2, "(4,7),(12,15)", "(4,12]", "(4,15)");
  433. testUnion(int2, "(4,7),(12,15)", "[4,4]", "[4,7),(12,15)");
  434. testUnion(int2, "(4,7),(12,15)", "[4,5)", "[4,7),(12,15)");
  435. testUnion(int2, "(4,7),(12,15)", "[4,7)", "[4,7),(12,15)");
  436. testUnion(int2, "(4,7),(12,15)", "[4,7]", "[4,7],(12,15)");
  437. testUnion(int2, "(4,7),(12,15)", "[4,8]", "[4,8],(12,15)");
  438. testUnion(int2, "(4,7),(12,15)", "[4,12)", "[4,12),(12,15)");
  439. testUnion(int2, "(4,7),(12,15)", "[4,12]", "[4,15)");
  440. testUnion(int2, "(4,7),(12,15)", "[4,14]", "[4,15)");
  441. testUnion(int2, "(4,7),(12,15)", "[4,15]", "[4,15]");
  442. testUnion(int2, "(4,7),(12,15)", "[4,16]", "[4,16]");
  443. testUnion(int2, "(4,7),(12,15)", "[4,17]", "[4,17]");
  444. testUnion(int2, "(4,7),(12,15)", "(5,7)", "(4,7),(12,15)");
  445. testUnion(int2, "(4,7),(12,15)", "(5,7]", "(4,7],(12,15)");
  446. testUnion(int2, "(4,7),(12,15)", "(5,8]", "(4,8],(12,15)");
  447. testUnion(int2, "(4,7),(12,15)", "(5,12)", "(4,12),(12,15)");
  448. testUnion(int2, "(4,7),(12,15)", "(5,12]", "(4,15)");
  449. testUnion(int2, "(4,7),(12,15)", "(5,14]", "(4,15)");
  450. testUnion(int2, "(4,7),(12,15)", "(5,15]", "(4,15]");
  451. testUnion(int2, "(4,7),(12,15)", "(5,17]", "(4,17]");
  452. testUnion(int2, "(4,7),(12,15)", "(7,8]", "(4,7),(7,8],(12,15)");
  453. testUnion(int2, "(4,7),(12,15)", "(7,8)", "(4,7),(7,8),(12,15)");
  454. testUnion(int2, "(4,7),(12,15)", "(7,12)", "(4,7),(7,12),(12,15)");
  455. testUnion(int2, "(4,7),(12,15)", "(7,12]", "(4,7),(7,15)");
  456. testUnion(int2, "(4,7),(12,15)", "(7,14]", "(4,7),(7,15)");
  457. testUnion(int2, "(4,7),(12,15)", "(7,15]", "(4,7),(7,15]");
  458. testUnion(int2, "(4,7),(12,15)", "(7,17]", "(4,7),(7,17]");
  459. testUnion(int2, "(4,7),(12,15)", "[7,7]", "(4,7],(12,15)");
  460. testUnion(int2, "(4,7),(12,15)", "[7,8]", "(4,8],(12,15)");
  461. testUnion(int2, "(4,7),(12,15)", "[7,12)", "(4,12),(12,15)");
  462. testUnion(int2, "(4,7),(12,15)", "[7,17]", "(4,17]");
  463. testUnion(int2, "(4,7),(12,15)", "[8,8]", "(4,7),[8],(12,15)");
  464. testUnion(int2, "(4,7),(12,15)", "[8,12)", "(4,7),[8,12),(12,15)");
  465. testUnion(int2, "(4,7),(12,15)", "[8,12]", "(4,7),[8,15)");
  466. testUnion(int2, "(4,7),(12,15)", "[8,14]", "(4,7),[8,15)");
  467. testUnion(int2, "(4,7),(12,15)", "[8,15]", "(4,7),[8,15]");
  468. testUnion(int2, "(4,7),(12,15)", "[8,16]", "(4,7),[8,16]");
  469. testUnion(int2, "(4,7),(12,15)", "[8,17]", "(4,7),[8,17]");
  470. testUnion(int2, "(4,7),(12,15)", "(8,11)", "(4,7),(8,11),(12,15)");
  471. testUnion(int2, "(4,7),(12,15)", "(8,12)", "(4,7),(8,12),(12,15)");
  472. testUnion(int2, "(4,7),(12,15)", "(8,12]", "(4,7),(8,15)");
  473. testUnion(int2, "(4,7),(12,15)", "(8,14]", "(4,7),(8,15)");
  474. testUnion(int2, "(4,7),(12,15)", "(8,15]", "(4,7),(8,15]");
  475. testUnion(int2, "(4,7),(12,15)", "(8,16]", "(4,7),(8,16]");
  476. testUnion(int2, "(4,7),(12,15)", "(8,17]", "(4,7),(8,17]");
  477. testUnion(int2, "(4,7),(12,15)", "(12,14]", "(4,7),(12,15)");
  478. testUnion(int2, "(4,7),(12,15)", "(12,15]", "(4,7),(12,15]");
  479. testUnion(int2, "(4,7),(12,15)", "(12,16]", "(4,7),(12,16]");
  480. testUnion(int2, "(4,7),(12,15)", "(12,17]", "(4,7),(12,17]");
  481. testUnion(int2, "(4,7),(12,15)", "[12,12]", "(4,7),[12,15)");
  482. testUnion(int2, "(4,7),(12,15)", "[12,14]", "(4,7),[12,15)");
  483. testUnion(int2, "(4,7),(12,15)", "[12,15]", "(4,7),[12,15]");
  484. testUnion(int2, "(4,7),(12,15)", "[12,16]", "(4,7),[12,16]");
  485. testUnion(int2, "(4,7),(12,15)", "[12,17]", "(4,7),[12,17]");
  486. testUnion(int2, "(4,7),(12,15)", "[14,14]", "(4,7),(12,15)");
  487. testUnion(int2, "(4,7),(12,15)", "[14,15]", "(4,7),(12,15]");
  488. testUnion(int2, "(4,7),(12,15)", "[14,16]", "(4,7),(12,16]");
  489. testUnion(int2, "(4,7),(12,15)", "[14,17]", "(4,7),(12,17]");
  490. testUnion(int2, "(4,7),(12,15)", "[15]", "(4,7),(12,15]");
  491. testUnion(int2, "(4,7),(12,15)", "[15,16]", "(4,7),(12,16]");
  492. testUnion(int2, "(4,7),(12,15)", "(15,16]", "(4,7),(12,15),(15,16]");
  493. testUnion(int2, "(4,7),(12,15)", "[15,17]", "(4,7),(12,17]");
  494. testUnion(int2, "(4,7),(12,15)", "[15,17)", "(4,7),(12,17)");
  495. testUnion(int2, "(4,7),(12,15)", "[16]", "(4,7),(12,15),[16]");
  496. testUnion(int2, "(4,7),(12,15)", "[16,17]", "(4,7),(12,15),[16,17]");
  497. testUnion(int2, "(4,7),(12,15)", "[17]", "(4,7),(12,15),[17]");
  498. }
  499. void testExclude(const RtlTypeInfo & type, const char * filter, const char * next, const char * expected)
  500. {
  501. Owned<IValueSet> set = createValueSet(type);
  502. deserializeSet(*set, filter);
  503. Owned<IValueSet> set2 = createValueSet(type);
  504. deserializeSet(*set2, next);
  505. set->excludeSet(set2);
  506. checkSet(set, expected);
  507. }
  508. //Tests killRange which is used by excludeSet()
  509. void testExclude()
  510. {
  511. RtlIntTypeInfo int2(type_int, 2);
  512. testExclude(int2, "[4]", "(4,5]", "[4]");
  513. testExclude(int2, "[4,7],[12,15]", "[1,1]", "[4,7],[12,15]");
  514. testExclude(int2, "[4,7],[12,15]", "[1,4)", "[4,7],[12,15]");
  515. testExclude(int2, "[4,7],[12,15]", "[1,4]", "(4,7],[12,15]");
  516. testExclude(int2, "[4,7],[12,15]", "[1,5)", "[5,7],[12,15]");
  517. testExclude(int2, "[4,7],[12,15]", "[1,7)", "[7],[12,15]");
  518. testExclude(int2, "[4,7],[12,15]", "[1,7]", "[12,15]");
  519. testExclude(int2, "[4,7],[12,15]", "(,)", "");
  520. testExclude(int2, "[4,7],[12,15]", "(,12]", "(12,15]");
  521. testExclude(int2, "[4,7],[12,15]", "(6,)", "[4,6]");
  522. testExclude(int2, "[4,7],[12,15]", "[1,8]", "[12,15]");
  523. testExclude(int2, "[4,7],[12,15]", "[1,12)", "[12,15]");
  524. testExclude(int2, "[4,7],[12,15]", "[1,12]", "(12,15]");
  525. testExclude(int2, "[4,7],[12,15]", "[1,14]", "(14,15]");
  526. testExclude(int2, "[4,7],[12,15]", "[1,15]", "");
  527. testExclude(int2, "[4,7],[12,15]", "[1,16]", "");
  528. testExclude(int2, "[4,7],[12,15]", "(4,5)", "[4],[5,7],[12,15]");
  529. testExclude(int2, "[4,7],[12,15]", "(4,7)", "[4],[7],[12,15]");
  530. testExclude(int2, "[4,7],[12,15]", "(4,7]", "[4],[12,15]");
  531. testExclude(int2, "[4,7],[12,15]", "(4,8]", "[4],[12,15]");
  532. testExclude(int2, "[4,7],[12,15]", "(4,12)", "[4],[12,15]");
  533. testExclude(int2, "[4,7],[12,15]", "(4,12]", "[4],(12,15]");
  534. testExclude(int2, "[4,7],[12,15]", "[4,4]", "(4,7],[12,15]");
  535. testExclude(int2, "[4,7],[12,15]", "[4,5)", "[5,7],[12,15]");
  536. testExclude(int2, "[4,7],[12,15]", "[4,7)", "[7],[12,15]");
  537. testExclude(int2, "[4,7],[12,15]", "[4,7]", "[12,15]");
  538. testExclude(int2, "[4,7],[12,15]", "[4,8]", "[12,15]");
  539. testExclude(int2, "[4,7],[12,15]", "[4,12)", "[12,15]");
  540. testExclude(int2, "[4,7],[12,15]", "[4,12]", "(12,15]");
  541. testExclude(int2, "[4,7],[12,15]", "[4,14]", "(14,15]");
  542. testExclude(int2, "[4,7],[12,15]", "[4,15]", "");
  543. testExclude(int2, "[4,7],[12,15]", "[4,16]", "");
  544. testExclude(int2, "[4,7],[12,15]", "(5,7)", "[4,5],[7],[12,15]");
  545. testExclude(int2, "[4,7],[12,15]", "(5,7]", "[4,5],[12,15]");
  546. testExclude(int2, "[4,7],[12,15]", "(5,8]", "[4,5],[12,15]");
  547. testExclude(int2, "[4,7],[12,15]", "(5,12)", "[4,5],[12,15]");
  548. testExclude(int2, "[4,7],[12,15]", "(5,12]", "[4,5],(12,15]");
  549. testExclude(int2, "[4,7],[12,15]", "(5,14]", "[4,5],(14,15]");
  550. testExclude(int2, "[4,7],[12,15]", "(5,15)", "[4,5],[15]");
  551. testExclude(int2, "[4,7],[12,15]", "(5,15]", "[4,5]");
  552. testExclude(int2, "[4,7],[12,15]", "(5,17]", "[4,5]");
  553. testExclude(int2, "[4,7],[12,15]", "(7,8]", "[4,7],[12,15]");
  554. testExclude(int2, "[4,7],[12,15]", "(7,8)", "[4,7],[12,15]");
  555. testExclude(int2, "[4,7],[12,15]", "(7,12)", "[4,7],[12,15]");
  556. testExclude(int2, "[4,7],[12,15]", "(7,12]", "[4,7],(12,15]");
  557. testExclude(int2, "[4,7],[12,15]", "(7,14]", "[4,7],(14,15]");
  558. testExclude(int2, "[4,7],[12,15]", "(7,15]", "[4,7]");
  559. testExclude(int2, "[4,7],[12,15]", "(7,17]", "[4,7]");
  560. testExclude(int2, "[4,7],[12,15]", "[7,7]", "[4,7),[12,15]");
  561. testExclude(int2, "[4,7],[12,15]", "[7,8]", "[4,7),[12,15]");
  562. testExclude(int2, "[4,7],[12,15]", "[7,12)", "[4,7),[12,15]");
  563. testExclude(int2, "[4,7],[12,15]", "[7,17]", "[4,7)");
  564. testExclude(int2, "[4,7],[12,15]", "[8,8]", "[4,7],[12,15]");
  565. testExclude(int2, "[4,7],[12,15]", "[8,12)", "[4,7],[12,15]");
  566. testExclude(int2, "[4,7],[12,15]", "[8,12]", "[4,7],(12,15]");
  567. testExclude(int2, "[4,7],[12,15]", "[8,14]", "[4,7],(14,15]");
  568. testExclude(int2, "[4,7],[12,15]", "[8,15]", "[4,7]");
  569. testExclude(int2, "[4,7],[12,15]", "[8,16]", "[4,7]");
  570. testExclude(int2, "[4,7],[12,15]", "[8,17]", "[4,7]");
  571. testExclude(int2, "[4,7],[12,15]", "(8,11)", "[4,7],[12,15]");
  572. testExclude(int2, "[4,7],[12,15]", "(8,12)", "[4,7],[12,15]");
  573. testExclude(int2, "[4,7],[12,15]", "(8,12]", "[4,7],(12,15]");
  574. testExclude(int2, "[4,7],[12,15]", "(12,14]", "[4,7],[12],(14,15]");
  575. testExclude(int2, "[4,7],[12,15]", "(12,15]", "[4,7],[12]");
  576. testExclude(int2, "[4,7],[12,15]", "(12,16]", "[4,7],[12]");
  577. testExclude(int2, "[4,7],[12,15]", "[12,12]", "[4,7],(12,15]");
  578. testExclude(int2, "[4,7],[12,15]", "[12,14]", "[4,7],(14,15]");
  579. testExclude(int2, "[4,7],[12,15]", "[12,15]", "[4,7]");
  580. testExclude(int2, "[4,7],[12,15]", "[12,16]", "[4,7]");
  581. testExclude(int2, "[4,7],[12,15]", "[14,14]", "[4,7],[12,14),(14,15]");
  582. testExclude(int2, "[4,7],[12,15]", "[14,15]", "[4,7],[12,14)");
  583. testExclude(int2, "[4,7],[12,15]", "[14,16]", "[4,7],[12,14)");
  584. testExclude(int2, "[4,7],[12,15]", "[14,17]", "[4,7],[12,14)");
  585. testExclude(int2, "[4,7],[12,15]", "[15]", "[4,7],[12,15)");
  586. testExclude(int2, "[4,7],[12,15]", "[15,16]", "[4,7],[12,15)");
  587. testExclude(int2, "[4,7],[12,15]", "[15,17]", "[4,7],[12,15)");
  588. testExclude(int2, "[4,7],[12,15]", "[15,17)", "[4,7],[12,15)");
  589. testExclude(int2, "[4,7],[12,15]", "[16]", "[4,7],[12,15]");
  590. testExclude(int2, "(4,7),(12,15)", "[1,1]", "(4,7),(12,15)");
  591. testExclude(int2, "(4,7),(12,15)", "[1,4)", "(4,7),(12,15)");
  592. testExclude(int2, "(4,7),(12,15)", "[1,4]", "(4,7),(12,15)");
  593. testExclude(int2, "(4,7),(12,15)", "[1,5)", "[5,7),(12,15)");
  594. testExclude(int2, "(4,7),(12,15)", "[1,7)", "(12,15)");
  595. testExclude(int2, "(4,7),(12,15)", "[1,7]", "(12,15)");
  596. testExclude(int2, "(4,7),(12,15)", "[1,8]", "(12,15)");
  597. testExclude(int2, "(4,7),(12,15)", "[1,12)", "(12,15)");
  598. testExclude(int2, "(4,7),(12,15)", "[1,12]", "(12,15)");
  599. testExclude(int2, "(4,7),(12,15)", "[1,14]", "(14,15)");
  600. testExclude(int2, "(4,7),(12,15)", "[1,15]", "");
  601. testExclude(int2, "(4,7),(12,15)", "[1,16]", "");
  602. testExclude(int2, "(4,7),(12,15)", "(4,5)", "[5,7),(12,15)");
  603. testExclude(int2, "(4,7),(12,15)", "(4,7)", "(12,15)");
  604. testExclude(int2, "(4,7),(12,15)", "(4,7]", "(12,15)");
  605. testExclude(int2, "(4,7),(12,15)", "(4,8]", "(12,15)");
  606. testExclude(int2, "(4,7),(12,15)", "(4,12)", "(12,15)");
  607. testExclude(int2, "(4,7),(12,15)", "(4,12]", "(12,15)");
  608. testExclude(int2, "(4,7),(12,15)", "[4,4]", "(4,7),(12,15)");
  609. testExclude(int2, "(4,7),(12,15)", "[4,5)", "[5,7),(12,15)");
  610. testExclude(int2, "(4,7),(12,15)", "[4,7)", "(12,15)");
  611. testExclude(int2, "(4,7),(12,15)", "[4,7]", "(12,15)");
  612. testExclude(int2, "(4,7),(12,15)", "[4,8]", "(12,15)");
  613. testExclude(int2, "(4,7),(12,15)", "[4,12)", "(12,15)");
  614. testExclude(int2, "(4,7),(12,15)", "[4,12]", "(12,15)");
  615. testExclude(int2, "(4,7),(12,15)", "[4,14]", "(14,15)");
  616. testExclude(int2, "(4,7),(12,15)", "[4,15]", "");
  617. testExclude(int2, "(4,7),(12,15)", "(5,6)", "(4,5],[6,7),(12,15)");
  618. testExclude(int2, "(4,7),(12,15)", "(5,7)", "(4,5],(12,15)");
  619. testExclude(int2, "(4,7),(12,15)", "(5,7]", "(4,5],(12,15)");
  620. testExclude(int2, "(4,7),(12,15)", "(5,8]", "(4,5],(12,15)");
  621. testExclude(int2, "(4,7),(12,15)", "(5,12)", "(4,5],(12,15)");
  622. testExclude(int2, "(4,7),(12,15)", "(5,12]", "(4,5],(12,15)");
  623. testExclude(int2, "(4,7),(12,15)", "(5,14]", "(4,5],(14,15)");
  624. testExclude(int2, "(4,7),(12,15)", "(5,15]", "(4,5]");
  625. testExclude(int2, "(4,7),(12,15)", "(5,17]", "(4,5]");
  626. //return;
  627. testExclude(int2, "(4,7),(12,15)", "(7,8]", "(4,7),(12,15)");
  628. testExclude(int2, "(4,7),(12,15)", "(7,8)", "(4,7),(12,15)");
  629. testExclude(int2, "(4,7),(12,15)", "(7,12)", "(4,7),(12,15)");
  630. testExclude(int2, "(4,7),(12,15)", "(7,12]", "(4,7),(12,15)");
  631. testExclude(int2, "(4,7),(12,15)", "(7,14]", "(4,7),(14,15)");
  632. testExclude(int2, "(4,7),(12,15)", "(7,15]", "(4,7)");
  633. testExclude(int2, "(4,7),(12,15)", "(7,17]", "(4,7)");
  634. testExclude(int2, "(4,7),(12,15)", "[7,7]", "(4,7),(12,15)");
  635. testExclude(int2, "(4,7),(12,15)", "[7,8]", "(4,7),(12,15)");
  636. testExclude(int2, "(4,7),(12,15)", "[7,12)", "(4,7),(12,15)");
  637. testExclude(int2, "(4,7),(12,15)", "[7,17]", "(4,7)");
  638. testExclude(int2, "(4,7),(12,15)", "[8,8]", "(4,7),(12,15)");
  639. testExclude(int2, "(4,7),(12,15)", "[8,12)", "(4,7),(12,15)");
  640. testExclude(int2, "(4,7),(12,15)", "[8,12]", "(4,7),(12,15)");
  641. testExclude(int2, "(4,7),(12,15)", "[8,14]", "(4,7),(14,15)");
  642. testExclude(int2, "(4,7),(12,15)", "[8,15]", "(4,7)");
  643. testExclude(int2, "(4,7),(12,15)", "[8,16]", "(4,7)");
  644. testExclude(int2, "(4,7),(12,15)", "[8,17]", "(4,7)");
  645. testExclude(int2, "(4,7),(12,15)", "(8,11)", "(4,7),(12,15)");
  646. testExclude(int2, "(4,7),(12,15)", "(8,12)", "(4,7),(12,15)");
  647. testExclude(int2, "(4,7),(12,15)", "(8,12]", "(4,7),(12,15)");
  648. testExclude(int2, "(4,7),(12,15)", "(8,14]", "(4,7),(14,15)");
  649. testExclude(int2, "(4,7),(12,15)", "(8,15]", "(4,7)");
  650. testExclude(int2, "(4,7),(12,15)", "(8,16]", "(4,7)");
  651. testExclude(int2, "(4,7),(12,15)", "(8,17]", "(4,7)");
  652. testExclude(int2, "(4,7),(12,15)", "(12,14]", "(4,7),(14,15)");
  653. testExclude(int2, "(4,7),(12,15)", "(12,15]", "(4,7)");
  654. testExclude(int2, "(4,7),(12,15)", "(12,16]", "(4,7)");
  655. testExclude(int2, "(4,7),(12,15)", "[12,12]", "(4,7),(12,15)");
  656. testExclude(int2, "(4,7),(12,15)", "[13]", "(4,7),(12,13),(13,15)");
  657. testExclude(int2, "(4,7),(12,15)", "[12,14)", "(4,7),[14,15)");
  658. testExclude(int2, "(4,7),(12,15)", "[12,15)", "(4,7)");
  659. testExclude(int2, "(4,7),(12,15)", "[12,16)", "(4,7)");
  660. testExclude(int2, "(4,7),(12,15)", "[14,14]", "(4,7),(12,14),(14,15)");
  661. testExclude(int2, "(4,7),(12,15)", "[14,15]", "(4,7),(12,14)");
  662. testExclude(int2, "(4,7),(12,15)", "[14,16]", "(4,7),(12,14)");
  663. testExclude(int2, "(4,7),(12,15)", "[15]", "(4,7),(12,15)");
  664. }
  665. void testInverse(const RtlTypeInfo & type, const char * filter, const char * expected)
  666. {
  667. Owned<IValueSet> set = createValueSet(type);
  668. deserializeSet(*set, filter);
  669. set->invertSet();
  670. checkSet(set, expected);
  671. }
  672. //Tests killRange which is used by excludeSet()
  673. void testInverse()
  674. {
  675. RtlIntTypeInfo int2(type_int, 2);
  676. testInverse(int2, "[4]", "(,4),(4,)");
  677. testInverse(int2, "[4,5]", "(,4),(5,)");
  678. testInverse(int2, "(4,5)", "(,4],[5,)");
  679. testInverse(int2, "(,5)", "[5,)");
  680. testInverse(int2, "[6,)", "(,6)");
  681. testInverse(int2, "", "(,)");
  682. testInverse(int2, "(,)", "");
  683. testInverse(int2, "[4,5],(8,9),[12,14)", "(,4),(5,8],[9,12),[14,)");
  684. }
  685. void testIntersect(const RtlTypeInfo & type, const char * filter, const char * next, const char * expected)
  686. {
  687. Owned<IValueSet> set = createValueSet(type);
  688. deserializeSet(*set, filter);
  689. Owned<IValueSet> set2 = createValueSet(type);
  690. deserializeSet(*set2, next);
  691. set->intersectSet(set2);
  692. checkSet(set, expected);
  693. //Test the opposite way around
  694. Owned<IValueSet> seta = createValueSet(type);
  695. deserializeSet(*seta, filter);
  696. Owned<IValueSet> setb = createValueSet(type);
  697. deserializeSet(*setb, next);
  698. setb->intersectSet(seta);
  699. checkSet(set, expected);
  700. }
  701. void testIntersect()
  702. {
  703. RtlIntTypeInfo int2(type_int, 2);
  704. testIntersect(int2, "", "[1,2],(3,6)", "");
  705. testIntersect(int2, "(,)", "[1,2],(3,6)", "[1,2],(3,6)");
  706. testIntersect(int2, "(,)", "", "");
  707. testIntersect(int2, "", "", "");
  708. testIntersect(int2, "(,)", "(,)", "(,)");
  709. testIntersect(int2, "(3,7),[10,20]", "[2]", "");
  710. testIntersect(int2, "(3,7),[10,20]", "[3]", "");
  711. testIntersect(int2, "(3,7),[10,20]", "[4]", "[4]");
  712. testIntersect(int2, "(3,7),[10,20]", "[6]", "[6]");
  713. testIntersect(int2, "(3,7),[10,20]", "[7]", "");
  714. testIntersect(int2, "(3,7),[10,20]", "[10]", "[10]");
  715. testIntersect(int2, "(3,7),[10,20]", "[20]", "[20]");
  716. testIntersect(int2, "(3,7),[10,20]", "[21]", "");
  717. testIntersect(int2, "(3,7),[10,20]", "[2,3]", "");
  718. testIntersect(int2, "(3,7),[10,20]", "[2,5]", "(3,5]");
  719. testIntersect(int2, "(3,7),[10,20]", "[2,7]", "(3,7)");
  720. testIntersect(int2, "(3,7),[10,20]", "[2,8]", "(3,7)");
  721. testIntersect(int2, "(3,7),[10,20]", "[2,10]", "(3,7),[10]");
  722. testIntersect(int2, "(3,7),[10,20]", "[2,15]", "(3,7),[10,15]");
  723. testIntersect(int2, "(3,7),[10,20]", "[2,20]", "(3,7),[10,20]");
  724. testIntersect(int2, "(3,7),[10,20]", "[2,25]", "(3,7),[10,20]");
  725. testIntersect(int2, "(3,7),[10,20]", "[3,3]", "");
  726. testIntersect(int2, "(3,7),[10,20]", "[3,5]", "(3,5]");
  727. testIntersect(int2, "(3,7),[10,20]", "[3,7]", "(3,7)");
  728. testIntersect(int2, "(3,7),[10,20]", "[3,8]", "(3,7)");
  729. testIntersect(int2, "(3,7),[10,20]", "[3,10]", "(3,7),[10]");
  730. testIntersect(int2, "(3,7),[10,20]", "[3,15]", "(3,7),[10,15]");
  731. testIntersect(int2, "(3,7),[10,20]", "[3,20]", "(3,7),[10,20]");
  732. testIntersect(int2, "(3,7),[10,20]", "[3,25]", "(3,7),[10,20]");
  733. testIntersect(int2, "(3,7),[10,20]", "[5,7]", "[5,7)");
  734. testIntersect(int2, "(3,7),[10,20]", "[5,8]", "[5,7)");
  735. testIntersect(int2, "(3,7),[10,20]", "[5,10]", "[5,7),[10]");
  736. testIntersect(int2, "(3,7),[10,20]", "[5,15]", "[5,7),[10,15]");
  737. testIntersect(int2, "(3,7),[10,20]", "[5,20]", "[5,7),[10,20]");
  738. testIntersect(int2, "(3,7),[10,20]", "[5,25]", "[5,7),[10,20]");
  739. testIntersect(int2, "(3,7),[10,20]", "[7,8]", "");
  740. testIntersect(int2, "(3,7),[10,20]", "[7,10]", "[10]");
  741. testIntersect(int2, "(3,7),[10,20]", "[7,15]", "[10,15]");
  742. testIntersect(int2, "(3,7),[10,20]", "[7,20]", "[10,20]");
  743. testIntersect(int2, "(3,7),[10,20]", "[7,25]", "[10,20]");
  744. testIntersect(int2, "(3,7),[10,20]", "[10,15]", "[10,15]");
  745. testIntersect(int2, "(3,7),[10,20]", "[10,20]", "[10,20]");
  746. testIntersect(int2, "(3,7),[10,20]", "[10,25]", "[10,20]");
  747. testIntersect(int2, "(3,7),[10,20]", "[15,20]", "[15,20]");
  748. testIntersect(int2, "(3,7),[10,20]", "[15,25]", "[15,20]");
  749. testIntersect(int2, "(3,7),[10,20]", "[20,25]", "[20]");
  750. testIntersect(int2, "(3,7),[10,20]", "(2,3)", "");
  751. testIntersect(int2, "(3,7),[10,20]", "(2,5)", "(3,5)");
  752. testIntersect(int2, "(3,7),[10,20]", "(2,7)", "(3,7)");
  753. testIntersect(int2, "(3,7),[10,20]", "(2,8)", "(3,7)");
  754. testIntersect(int2, "(3,7),[10,20]", "(2,10)", "(3,7)");
  755. testIntersect(int2, "(3,7),[10,20]", "(2,15)", "(3,7),[10,15)");
  756. testIntersect(int2, "(3,7),[10,20]", "(2,20)", "(3,7),[10,20)");
  757. testIntersect(int2, "(3,7),[10,20]", "(2,25)", "(3,7),[10,20]");
  758. testIntersect(int2, "(3,7),[10,20]", "(3,5)", "(3,5)");
  759. testIntersect(int2, "(3,7),[10,20]", "(3,7)", "(3,7)");
  760. testIntersect(int2, "(3,7),[10,20]", "(3,8)", "(3,7)");
  761. testIntersect(int2, "(3,7),[10,20]", "(3,10)", "(3,7)");
  762. testIntersect(int2, "(3,7),[10,20]", "(3,15)", "(3,7),[10,15)");
  763. testIntersect(int2, "(3,7),[10,20]", "(3,20)", "(3,7),[10,20)");
  764. testIntersect(int2, "(3,7),[10,20]", "(3,25)", "(3,7),[10,20]");
  765. testIntersect(int2, "(3,7),[10,20]", "(5,7)", "(5,7)");
  766. testIntersect(int2, "(3,7),[10,20]", "(5,8)", "(5,7)");
  767. testIntersect(int2, "(3,7),[10,20]", "(5,10)", "(5,7)");
  768. testIntersect(int2, "(3,7),[10,20]", "(5,15)", "(5,7),[10,15)");
  769. testIntersect(int2, "(3,7),[10,20]", "(5,20)", "(5,7),[10,20)");
  770. testIntersect(int2, "(3,7),[10,20]", "(5,25)", "(5,7),[10,20]");
  771. testIntersect(int2, "(3,7),[10,20]", "(7,8)", "");
  772. testIntersect(int2, "(3,7),[10,20]", "(7,10)", "");
  773. testIntersect(int2, "(3,7),[10,20]", "(7,15)", "[10,15)");
  774. testIntersect(int2, "(3,7),[10,20]", "(7,20)", "[10,20)");
  775. testIntersect(int2, "(3,7),[10,20]", "(7,25)", "[10,20]");
  776. testIntersect(int2, "(3,7),[10,20]", "(10,15)", "(10,15)");
  777. testIntersect(int2, "(3,7),[10,20]", "(10,20)", "(10,20)");
  778. testIntersect(int2, "(3,7),[10,20]", "(15,20)", "(15,20)");
  779. testIntersect(int2, "(3,7),[10,20]", "(15,25)", "(15,20]");
  780. testIntersect(int2, "(3,7),[10,20]", "(20,25)", "");
  781. testIntersect(int2, "(3,5),[7,10),[15,20),(30,32),[37]", "(4,7],(9,12),[13,31],(36,)", "(4,5),[7],(9,10),[15,20),(30,31],[37]");
  782. }
  783. void testSubStrings()
  784. {
  785. RtlStringTypeInfo str3(type_string, 3);
  786. RtlStringTypeInfo str8(type_string, 8);
  787. RtlStringTypeInfo strx(type_string|RFTMunknownsize, 0);
  788. testSerialize(str3, "['a':1],", "['a ':1]");
  789. testSerialize(str3, "['a':1,'b':1],", "['a ':1,'b ':1]");
  790. testSerialize(str3, "['a':1,'bx':2),", "['a ':1,'bx ':2)");
  791. testSerialize(str3, "['aa':1],", "");
  792. testSerialize(str3, "['aaa':3],", "['aaa']");
  793. testSerialize(str3, "['aaa':4],", "['aaa']");
  794. testSerialize(str3, "['aa':1,'bc':1],", "('a ':1,'b ':1]");
  795. testUnion(str3, "['aaa']", "['aaa']", "['aaa']");
  796. testUnion(str3, "['a':1]", "['aaa']", "['a ':1]");
  797. testUnion(str3, "['a':1]", "['aa':2]", "['a ':1]");
  798. testUnion(str3, "['a':1]", "['b':1]", "['a ':1],['b ':1]"); //subranges are not merged
  799. testUnion(str3, "['a':1]", "['bb':2]", "['a ':1],['bb ':2]");
  800. testUnion(str3, "['abc':2,'abz':2]", "['bbx':2,'bdz':2]", "('bb ':2,'bd ':2]");
  801. testIntersect(str3, "['a':1]", "['aaa']", "['aaa']");
  802. testIntersect(str3, "['a':1]", "['aa':2]", "['aa ':2]");
  803. testIntersect(str3, "['a':1]", "['b':1]", "");
  804. testIntersect(str3, "['a':1]", "['bb':2]", "");
  805. testIntersect(str3, "['ab':1,]", "[,'bb':2]", "('a ':1,'bb ':2]");
  806. testIntersect(str3, "['ax':1,]", "[,'bx':1]", "('a ':1,'b ':1]");
  807. testExclude(str3, "['a':1]", "['aaa']", "['a ':1,'aaa'),('aaa','a ':1]");
  808. testExclude(str3, "['a':1]", "['aa':2]", "['a ':1,'aa ':2),('aa ':2,'a ':1]");
  809. testExclude(str3, "['a':1]", "['b':1]", "['a ':1]");
  810. testExclude(str3, "['a':1]", "['bb':2]", "['a ':1]");
  811. testExclude(str3, "['a':1,]", "[,'bb':2]", "('bb ':2,)");
  812. testExclude(str3, "['a':1,]", "[,'bbx':2]", "('bb ':2,)");
  813. testExclude(str3, "[,'ccx':2]", "['bbx':2,]", "(,'bb ':2]");
  814. testExclude(str3, "['aax':2,'ddx':2]", "['bbx':2,'ccx':2]", "('aa ':2,'bb ':2],('cc ':2,'dd ':2]");
  815. testExclude(str3, "[,]", "['bbx':2,'ccx':2]", "(,'bb ':2],('cc ':2,)");
  816. testUnion(str3, "['ab':2],['bc':2],['gh':2]", "['e':1]", "['ab ':2],['bc ':2],['e ':1],['gh ':2]");
  817. testUnion(str8, "['KT19':4],['KT40':4],['KT3 ':4],['KT50':4]", "['KT2':3]","['KT19 ':4],['KT2 ':3],['KT3 ':4],['KT40 ':4],['KT50 ':4]");
  818. verifyRawSet("['MA':2]", strx, "+", { "\002\000\000\000MA", "\002\000\000\000MA" }, { 2 });
  819. verifyRawSet("['a ':1],['b ':1]", str3, "++", { "a ", "a ", "b ", "b " }, { 1, 1 });
  820. verifyRawSet("['a ':1],['bb ':2]", str3, "++", { "a ", "a ", "bb ", "bb " }, { 1, 2 });
  821. verifyRawSet("('bb ':2,'bd ':2]", str3, "++", { "abc", "abz", "bbx", "bdz" }, { 2, 2 });
  822. verifyRawSet("(,'bb ':2]", str3, "+-", { nullptr, "ccx", "bbx", nullptr }, { 2, 2} );
  823. verifyRawSet("('aa ':2,'bb ':2],('cc ':2,'dd ':2]", str3, "+-", { "aax", "ddx", "bbx", "ccx"}, { 2, 2} );
  824. verifyRawSet("(,'bb ':2],('cc ':2,)", str3, "+-", { nullptr, nullptr, "bbx", "ccx" }, { 2, 2} );
  825. }
  826. void testStr2()
  827. {
  828. RtlStringTypeInfo str1(type_string, 1);
  829. Owned<IValueSet> az = createValueSet(str1);
  830. addRange(az, "A", "Z");
  831. checkSet(az, "['A','Z']");
  832. Owned<IValueSet> dj = createValueSet(str1);
  833. addRange(dj, "D", "J");
  834. checkSet(dj, "['D','J']");
  835. Owned<IValueSet> hz = createValueSet(str1);
  836. addRange(hz, "H", "Z");
  837. Owned<IValueSet> jk = createValueSet(str1);
  838. addRange(jk, "J", "K");
  839. Owned<IValueSet> kj = createValueSet(str1);
  840. addRange(kj, "K", "J");
  841. checkSet(kj, "");
  842. }
  843. // id:int2 extra:string padding:! name:string2
  844. // Keep in sorted order so they can be reused for index testing
  845. const char *testRows[6] = {
  846. "\001\000\004\000\000\000MARK!GH",
  847. "\002\000\000\000\000\000!AB",
  848. "\000\001\003\000\000\000FRY!JH",
  849. "\001\001\003\000\000\000MAR!AC",
  850. "\002\001\003\000\000\000MAS!JH",
  851. "\003\002\004\000\000\000MASK!JH",
  852. };
  853. const RtlIntTypeInfo int2 = RtlIntTypeInfo(type_int, 2);
  854. const RtlIntTypeInfo int4 = RtlIntTypeInfo(type_int, 4);
  855. const RtlStringTypeInfo str1 = RtlStringTypeInfo(type_string, 1);
  856. const RtlStringTypeInfo str2 = RtlStringTypeInfo(type_string, 2);
  857. const RtlStringTypeInfo str4 = RtlStringTypeInfo(type_string, 4);
  858. const RtlStringTypeInfo strx = RtlStringTypeInfo(type_string|RFTMunknownsize, 0);
  859. const RtlDataTypeInfo data4 = RtlDataTypeInfo(type_data, 4);
  860. const RtlFieldInfo id = RtlFieldInfo("id", nullptr, &int2);
  861. const RtlFieldInfo extra = RtlFieldInfo("extra", nullptr, &strx);
  862. const RtlFieldInfo padding = RtlFieldInfo("padding", nullptr, &str1);
  863. const RtlFieldInfo name = RtlFieldInfo("name", nullptr, &str2);
  864. const RtlFieldInfo * const fields[5] = { &id, &extra, &padding, &name, nullptr };
  865. const RtlRecordTypeInfo recordType = RtlRecordTypeInfo(type_record, 4, fields);
  866. const RtlRecord record = RtlRecord(recordType, true);
  867. void verifyFilter(const RtlRecord & searchRecord, IFieldFilter * filter)
  868. {
  869. StringBuffer str1, str2;
  870. filter->serialize(str1);
  871. Owned<IFieldFilter> clone1 = deserializeFieldFilter(searchRecord, str1);
  872. clone1->serialize(str2);
  873. MemoryBuffer mem1, mem2;
  874. filter->serialize(mem1);
  875. Owned<IFieldFilter> clone2 = deserializeFieldFilter(searchRecord, mem1);
  876. clone2->serialize(mem2);
  877. if (!streq(str1, str2))
  878. CPPUNIT_ASSERT_EQUAL(str1.str(), str2.str());
  879. if ((mem1.length() != mem2.length()) || memcmp(mem1.bytes(), mem2.bytes(), mem1.length()) != 0)
  880. {
  881. printf("Filter %s failed\n", str1.str());
  882. CPPUNIT_ASSERT_MESSAGE("Binary filter deserialize failed", false);
  883. }
  884. }
  885. void processFilter(RowFilter & cursor, const char * originalFilter, const RtlRecord & searchRecord)
  886. {
  887. const char * filter = originalFilter;
  888. while (filter && *filter)
  889. {
  890. StringBuffer next;
  891. const char * semi = strchr(filter, ';');
  892. if (semi)
  893. {
  894. next.append(semi-filter, filter);
  895. filter = semi+1;
  896. }
  897. else
  898. {
  899. next.append(filter);
  900. filter = nullptr;
  901. }
  902. IFieldFilter * fieldFilter = deserializeFieldFilter(searchRecord, next);
  903. assertex(fieldFilter);
  904. cursor.addFilter(*fieldFilter);
  905. verifyFilter(searchRecord, fieldFilter);
  906. }
  907. }
  908. //testFilter("id=[1,3];name=(,GH)", { false, true, false, false, false });
  909. void testFilter(RowFilter & cursor, const char * originalFilter, const std::initializer_list<bool> & expected)
  910. {
  911. const byte * * rows = reinterpret_cast<const byte * *>(testRows);
  912. RtlDynRow row(record, nullptr);
  913. assertex((expected.end() - expected.begin()) == (unsigned)_elements_in(testRows));
  914. const bool * curExpected = expected.begin();
  915. for (unsigned i= 0; i < _elements_in(testRows); i++)
  916. {
  917. row.setRow(rows[i]);
  918. if (cursor.matches(row) != curExpected[i])
  919. {
  920. StringBuffer actual;
  921. for (unsigned i=0; i<cursor.numFilterFields(); i++)
  922. cursor.queryFilter(i).serialize(actual.append(","));
  923. printf("Failure to match row %u filter '%s' (%s)\n", i, originalFilter, actual.str());
  924. CPPUNIT_ASSERT_EQUAL(curExpected[i], cursor.matches(row));
  925. }
  926. }
  927. };
  928. void testFilter(const char * originalFilter, const std::initializer_list<bool> & expected)
  929. {
  930. RowFilter cursor;
  931. processFilter(cursor, originalFilter, record);
  932. testFilter(cursor, originalFilter, expected);
  933. }
  934. IValueSet * createRawSet(const RtlTypeInfo * fieldType, const char * key, const std::initializer_list<const char *> & transitions, const std::initializer_list<unsigned> & lengths)
  935. {
  936. RowFilter cursor;
  937. unsigned numTransitions = (transitions.end() - transitions.begin());
  938. unsigned numLengths = (lengths.end() - lengths.begin());
  939. assertex((numTransitions & 1) == 0);
  940. assertex(strlen(key) == numTransitions/2);
  941. assertex(numLengths == numTransitions/2);
  942. Owned<IValueSet> set = createValueSet(*fieldType);
  943. const unsigned * lens = lengths.begin();
  944. for (unsigned i=0; i < numTransitions; i+= 2)
  945. {
  946. const char * low = transitions.begin()[i];
  947. const char * high = transitions.begin()[i+1];
  948. if (key[i/2] == '+')
  949. set->addRawRangeEx(low, high, lens[i/2]);
  950. else
  951. set->killRawRangeEx(low, high, lens[i/2]);
  952. }
  953. return set.getClear();
  954. }
  955. void verifyRawSet(const char * expected, const RtlTypeInfo & fieldType, const char * key, const std::initializer_list<const char *> & transitions, const std::initializer_list<unsigned> & lengths)
  956. {
  957. Owned<IValueSet> set = createRawSet(&fieldType, key, transitions, lengths);
  958. StringBuffer actual;
  959. set->serialize(actual);
  960. if (!streq(expected, actual))
  961. CPPUNIT_ASSERT_EQUAL(expected, actual.str());
  962. }
  963. void testRawFilter(const char * fieldName, const char * key, const std::initializer_list<const char *> & transitions, const std::initializer_list<unsigned> & lengths, const std::initializer_list<bool> & expected)
  964. {
  965. unsigned fieldNum = record.getFieldNum(fieldName);
  966. assertex(fieldNum != (unsigned) -1);
  967. const RtlTypeInfo *fieldType = record.queryType(fieldNum);
  968. Owned<IValueSet> set = createRawSet(fieldType, key, transitions, lengths);
  969. IFieldFilter * filter = createFieldFilter(fieldNum, set);
  970. RowFilter cursor;
  971. cursor.addFilter(*filter);
  972. testFilter(cursor, "<raw>", expected);
  973. }
  974. void testFilter()
  975. {
  976. testFilter("", { true, true, true, true, true, true });
  977. testFilter("id=[1]", { true, false, false, false, false, false });
  978. testFilter("id=[1],[2],[4],[6],[12],[23],[255],[256],[300],[301],[320]", { true, true, true, false, false, false });
  979. testFilter("id=[1,2]", { true, true, false, false, false, false });
  980. testFilter("id=(1,2]", { false, true, false, false, false, false });
  981. testFilter("id=[1,3];name=(,GH)", { false, true, false, false, false, false });
  982. testFilter("id=[1,3];name=(,GH]", { true, true, false, false, false, false });
  983. testFilter("extra=['MAR','MAS']", { true, false, false, true, true, false });
  984. testFilter("extra=('MAR','MAS')", { true, false, false, false, false, false });
  985. testFilter("id=(,257]", { true, true, true, true, false, false });
  986. testFilter("extra:2=['MA']", { true, false, false, true, true, true });
  987. testFilter("extra:2=[' ']", { false, true, false, false, false, false });
  988. testFilter("extra:0=['XX']", { false, false, false, false, false, false });
  989. testFilter("extra:0=['']", { true, true, true, true, true, true });
  990. testFilter("name:1=['A']", { false, true, false, true, false, false });
  991. //Check substring ranges are correctly truncated
  992. testFilter("extra:3=['MARK','MAST']", { false, false, false, false, true, true });
  993. testFilter("name:1=['AB','JA']", { true, false, true, false, true, true });
  994. //New substring implementation
  995. testFilter("extra=['MA':2]", { true, false, false, true, true, true });
  996. testFilter("extra=[' ':2]", { false, true, false, false, false, false });
  997. testFilter("extra=['XX':0]", { false, false, false, false, false, false });
  998. testFilter("extra=['':0]", { true, true, true, true, true, true });
  999. testFilter("name=['A':1]", { false, true, false, true, false, false });
  1000. //Check substring ranges are correctly truncated
  1001. testFilter("extra=['MARK':3,'MAST':3]", { false, false, false, false, true, true });
  1002. testFilter("name=['AB':1,'JA':1]", { true, false, true, false, true, true });
  1003. testFilter("extra=[' ':1],['MA':2]", { true, true, false, true, true, true });
  1004. testFilter("extra=['MARK':3,]", { false, false, false, false, true, true });
  1005. testFilter("extra=[,'MARK':3]", { true, true, true, true, false, false });
  1006. testFilter("extra=['FRA':2,]", { true, false, false, true, true, true });
  1007. testFilter("extra=['FRA':2,'MARK':3]", { true, false, false, true, false, false });
  1008. testFilter("extra=['FRA':2,],[,'MARK':3]", { true, true, true, true, true, true });
  1009. testFilter("extra=['FRZ':2,'MARK':3]", { true, false, false, true, false, false });
  1010. testFilter("extra=['MARK':3,],[,'FRZ':2]", { false, true, true, false, true, true });
  1011. testRawFilter("extra", "+", { "\002\000\000\000MA", "\002\000\000\000MA" }, { 2 }, { true, false, false, true, true, true });
  1012. testRawFilter("extra", "+", { "\004\000\000\000MARK", nullptr }, { 3 }, { false, false, false, false, true, true });
  1013. }
  1014. void testKeyed(const char * originalFilter, const char * expected)
  1015. {
  1016. const byte * * rows = reinterpret_cast<const byte * *>(testRows);
  1017. RowFilter filter;
  1018. processFilter(filter, originalFilter, record);
  1019. InMemoryRows source(_elements_in(testRows), rows, record);
  1020. InMemoryRowCursor sourceCursor(source); // could be created by source.createCursor()
  1021. KeySearcher searcher(source.queryRecord(), filter, &sourceCursor);
  1022. StringBuffer matches;
  1023. while (searcher.next())
  1024. {
  1025. searcher.queryRow().lazyCalcOffsets(1); // In unkeyed case we may not have calculated field 0 offset (though it is always going to be 0).
  1026. matches.append(searcher.queryRow().getInt(0)).append("|");
  1027. }
  1028. if (!streq(matches, expected))
  1029. {
  1030. printf("Failure to match expected keyed filter '%s' (%s, %s)\n", originalFilter, expected, matches.str());
  1031. CPPUNIT_ASSERT(streq(matches, expected));
  1032. }
  1033. }
  1034. void testKeyed1()
  1035. {
  1036. testKeyed("extra=['MAR','MAS']", "1|257|258|");
  1037. testKeyed("","1|2|256|257|258|515|");
  1038. testKeyed("id=[1,2]","1|2|");
  1039. testKeyed("id=[1],[256]","1|256|");
  1040. testKeyed("id=[1],[256,280]","1|256|257|258|");
  1041. testKeyed("id=[1],[256,280],[1000],[1023]","1|256|257|258|");
  1042. testKeyed("id=[1],[2],[4],[6],[12],[23],[255],[256],[300],[301],[320]","1|2|256|");
  1043. testKeyed("id!=[1],[256]","2|257|258|515|");
  1044. testKeyed("id!=","1|2|256|257|258|515|");
  1045. testKeyed("extra=['MAR','MAS']", "1|257|258|");
  1046. testKeyed("extra=('MAR','MAS')", "1|");
  1047. testKeyed("name=['AB','AC']", "2|257|");
  1048. }
  1049. void generateOrderedRows(PointerArray & rows, const RtlRecord & rowRecord)
  1050. {
  1051. //Generate rows with 3 fields. Try and ensure:
  1052. // each trailing field starts with 0, non zero.
  1053. // the third field has significant distribution in the number of elements for each value of field2
  1054. // duplicates occur in the full keyed values.
  1055. // sometimes the next value in sequence happens to match a trailing filter condition e.g. field3=1
  1056. //Last field First field x ranges from 0 to n1
  1057. //Second field
  1058. //Second field y ranges from 0 .. n2, and is included if (x + y) % 3 != 0 and (x + y) % 5 != 0
  1059. //Third field is sparse from 0..n3. m = ((x + y) % 11 ^2 + 1; if (n3 + x *2 + y) % m = 0 then it is included
  1060. unsigned n = 100000;
  1061. unsigned f1 = 0;
  1062. unsigned f2 = 0;
  1063. unsigned f3 = 0;
  1064. unsigned numf2 = 1;
  1065. unsigned countf2 = 0;
  1066. unsigned numf3 = 1;
  1067. unsigned countf3 = 0;
  1068. MemoryBuffer buff;
  1069. for (unsigned i = 0; i < n; i++)
  1070. {
  1071. buff.setLength(0);
  1072. MemoryBufferBuilder builder(buff, 0);
  1073. size32_t offset = 0;
  1074. offset = rowRecord.queryType(0)->buildInt(builder, offset, nullptr, f1);
  1075. offset = rowRecord.queryType(1)->buildInt(builder, offset, nullptr, f2);
  1076. offset = rowRecord.queryType(2)->buildInt(builder, offset, nullptr, f3);
  1077. byte * row = new byte[offset];
  1078. memcpy(row, buff.bufferBase(), offset);
  1079. rows.append(row);
  1080. if (++countf3 == numf3)
  1081. {
  1082. f2++;
  1083. if (++countf2 == numf2)
  1084. {
  1085. f1++;
  1086. f2 = i % 2;
  1087. numf2 = i % 23;
  1088. if (numf2 == 0)
  1089. {
  1090. f1++;
  1091. numf2 = (i % 21) + 1;
  1092. }
  1093. countf2 = 0;
  1094. }
  1095. f3 = i % 7;
  1096. countf3 = 0;
  1097. numf3 = i % 9;
  1098. if (numf3 == 0)
  1099. {
  1100. f3++;
  1101. numf3 = (i % 11) + 1;
  1102. }
  1103. }
  1104. if (i % 5)
  1105. f3++;
  1106. }
  1107. //Sort the rows - to allow different field types to be used.
  1108. RawRowCompare compareRow(rowRecord);
  1109. qsortvec(rows.getArray(), rows.ordinality(), compareRow);
  1110. }
  1111. void traceRow(const RtlRow & row)
  1112. {
  1113. row.lazyCalcOffsets(3);
  1114. printf("%u %u %u", (unsigned)row.getInt(0), (unsigned)row.getInt(1), (unsigned)row.getInt(2));
  1115. }
  1116. const RtlFieldInfo f1 = RtlFieldInfo("f1", nullptr, &int2);
  1117. const RtlFieldInfo f2 = RtlFieldInfo("f2", nullptr, &int2);
  1118. const RtlFieldInfo f3 = RtlFieldInfo("f3", nullptr, &int2);
  1119. const RtlFieldInfo * const testFields[4] = { &f1, &f2, &f3, nullptr };
  1120. const RtlRecordTypeInfo testRecordType = RtlRecordTypeInfo(type_record, 6, testFields);
  1121. const RtlRecord testRecord = RtlRecord(testRecordType, true);
  1122. const RtlFieldInfo f1s = RtlFieldInfo("f1", nullptr, &strx);
  1123. const RtlFieldInfo f2s = RtlFieldInfo("f2", nullptr, &str4);
  1124. const RtlFieldInfo f3s = RtlFieldInfo("f3", nullptr, &str2);
  1125. const RtlFieldInfo * const testFieldsB[4] = { &f1s, &f2s, &f3s, nullptr };
  1126. const RtlRecordTypeInfo testRecordTypeB = RtlRecordTypeInfo(type_record, 10, testFieldsB);
  1127. const RtlRecord testRecordB = RtlRecord(testRecordTypeB, true);
  1128. void timeKeyedScan(const PointerArray & rows, const RtlRecord & searchRecord, const char * filterText)
  1129. {
  1130. RowFilter filter;
  1131. processFilter(filter, filterText, searchRecord);
  1132. CCycleTimer timeKeyed;
  1133. unsigned countKeyed = 0;
  1134. {
  1135. InMemoryRows source(rows.ordinality(), (const byte * *)rows.getArray(), searchRecord);
  1136. InMemoryRowCursor sourceCursor(source); // could be created by source.createCursor()
  1137. KeySearcher searcher(source.queryRecord(), filter, &sourceCursor);
  1138. while (searcher.next())
  1139. {
  1140. countKeyed++;
  1141. }
  1142. }
  1143. unsigned __int64 keyedMs = timeKeyed.elapsedNs();
  1144. CCycleTimer timeScan;
  1145. unsigned countScan = 0;
  1146. {
  1147. RowScanner scanner(searchRecord, filter, rows);
  1148. bool hasSearch = scanner.first();
  1149. while (hasSearch)
  1150. {
  1151. countScan++;
  1152. hasSearch = scanner.next();
  1153. }
  1154. }
  1155. unsigned __int64 scanMs = timeScan.elapsedNs();
  1156. CPPUNIT_ASSERT_EQUAL(countScan, countKeyed);
  1157. printf("[%s] %u matches keyed(%" I64F "u) scan(%" I64F "u) (%.3f)\n", filterText, countScan, keyedMs, scanMs, (double)keyedMs/scanMs);
  1158. }
  1159. void testKeyed(const PointerArray & rows, const RtlRecord & searchRecord, const char * filterText)
  1160. {
  1161. RowFilter filter;
  1162. processFilter(filter, filterText, searchRecord);
  1163. InMemoryRows source(rows.ordinality(), (const byte * *)rows.getArray(), searchRecord);
  1164. InMemoryRowCursor sourceCursor(source); // could be created by source.createCursor()
  1165. KeySearcher searcher(source.queryRecord(), filter, &sourceCursor);
  1166. RowScanner scanner(source.queryRecord(), filter, rows);
  1167. unsigned count = 0;
  1168. bool hasSearch = searcher.next();
  1169. bool hasScan = scanner.first();
  1170. while (hasSearch && hasScan)
  1171. {
  1172. count++;
  1173. if (searchRecord.compare(searcher.queryRow().queryRow(), scanner.queryRow().queryRow()) != 0)
  1174. break;
  1175. hasSearch = searcher.next();
  1176. hasScan = scanner.next();
  1177. }
  1178. if (hasSearch || hasScan)
  1179. {
  1180. printf("[%s] Keyed: ", filterText);
  1181. if (hasSearch)
  1182. traceRow(searcher.queryRow());
  1183. else
  1184. printf("<missing>");
  1185. printf(" Scan: ");
  1186. if (hasScan)
  1187. traceRow(scanner.queryRow());
  1188. else
  1189. printf("<missing>");
  1190. printf("\n");
  1191. CPPUNIT_ASSERT_MESSAGE("Keyed search did not match scan", false);
  1192. }
  1193. else
  1194. {
  1195. const bool compareTiming = true;
  1196. if (compareTiming)
  1197. timeKeyedScan(rows, searchRecord, filterText);
  1198. else
  1199. printf("[%s] %u matches\n", filterText, count);
  1200. }
  1201. }
  1202. void testKeyed2(const RtlRecord & record, bool testSubString)
  1203. {
  1204. PointerArray rows;
  1205. generateOrderedRows(rows, record);
  1206. testKeyed(rows, record, "");
  1207. testKeyed(rows, record, "f1=[5]");
  1208. testKeyed(rows, record, "f1=[0]");
  1209. testKeyed(rows, record, "f2=[1]");
  1210. testKeyed(rows, record, "f3=[1]");
  1211. testKeyed(rows, record, "f3=[4]");
  1212. testKeyed(rows, record, "f3=[1,3]");
  1213. testKeyed(rows, record, "f3=[1],[2],[3]");
  1214. testKeyed(rows, record, "f1=[21];f2=[20];f3=[4]");
  1215. testKeyed(rows, record, "f1=[7];f3=[5]");
  1216. testKeyed(rows, record, "f1=[7,];f3=[,5]");
  1217. if (testSubString)
  1218. {
  1219. testKeyed(rows, record, "f1:1=['1']");
  1220. testKeyed(rows, record, "f1:2=['10']");
  1221. testKeyed(rows, record, "f1:30=['5']");
  1222. testKeyed(rows, record, "f3:1=['1']");
  1223. testKeyed(rows, record, "f3:2=['10']");
  1224. testKeyed(rows, record, "f3:2=['123']");
  1225. testKeyed(rows, record, "f3:2=['123','126']");
  1226. //new format substring
  1227. testKeyed(rows, record, "f1=['1':1]");
  1228. testKeyed(rows, record, "f1=['10':2]");
  1229. testKeyed(rows, record, "f1=['5':30]");
  1230. testKeyed(rows, record, "f3=['1':1]");
  1231. testKeyed(rows, record, "f3=['10':2]");
  1232. testKeyed(rows, record, "f3=['123':2]");
  1233. testKeyed(rows, record, "f3=['123','126':2]");
  1234. }
  1235. ForEachItemIn(i, rows)
  1236. delete [] (byte *)rows.item(i);
  1237. }
  1238. void testKeyed2()
  1239. {
  1240. testKeyed2(testRecord, false);
  1241. testKeyed2(testRecordB, true);
  1242. }
  1243. void appendHex(StringBuffer & target, size_t len, const void * data, bool lower)
  1244. {
  1245. for (unsigned i=0; i < len; i++)
  1246. target.appendhex(((const byte *)data)[i], lower);
  1247. }
  1248. void testBound(const RtlTypeInfo & type, const char * original, unsigned subLength, bool lower, bool inclusive, size_t sizeExpected, const char * expected)
  1249. {
  1250. MemoryBuffer buff;
  1251. MemoryBufferBuilder builder(buff, 0);
  1252. type.buildUtf8(builder, 0, nullptr, rtlUtf8Length(strlen(original), original), original);
  1253. byte result[1000];
  1254. if (lower)
  1255. type.setLowBound(result, (const byte *)buff.toByteArray(), subLength, inclusive);
  1256. else
  1257. type.setHighBound(result, (const byte *)buff.toByteArray(), subLength, inclusive);
  1258. size_t size = type.size(result, nullptr);
  1259. if ((size != sizeExpected) || memcmp(result, expected, size) != 0)
  1260. {
  1261. StringBuffer left, right;
  1262. appendHex(left, sizeExpected, expected, true);
  1263. appendHex(right, size, result, true);
  1264. CPPUNIT_ASSERT_EQUAL(left.str(), right.str());
  1265. }
  1266. }
  1267. void testBoundQstr(const RtlTypeInfo & type, const char * original, unsigned subLength, bool lower, bool inclusive, size_t sizeExpected, const char * expected)
  1268. {
  1269. size32_t tempLen;
  1270. rtlDataAttr temp;
  1271. rtlStrToQStrX(tempLen, temp.refstr(), sizeExpected, expected);
  1272. testBound(type, original, subLength, lower, inclusive, rtlQStrSize(tempLen), temp.getstr());
  1273. }
  1274. void testBounds()
  1275. {
  1276. //Lower bounds
  1277. testBound(str4, "X", MatchFullString, true, true, 4, "X ");
  1278. testBound(str4, "X", 4, true, true, 4, "X ");
  1279. testBound(str4, "X", 3, true, true, 4, "X \x00");
  1280. testBound(str4, "A", MatchFullString, true, false, 4, "A !");
  1281. testBound(str4, "A", 4, true, false, 4, "A !");
  1282. testBound(str4, "X", 3, true, false, 4, "X !\x00");
  1283. //Upper bounds
  1284. testBound(str4, "X", 4, false, true, 4, "X ");
  1285. testBound(str4, "X", 3, false, true, 4, "X \xFF");
  1286. testBound(str4, "A", 4, false, false, 4, "A \x1F");
  1287. testBound(str4, "X", 3, false, false, 4, "X \x1F\xFF");
  1288. //Lower bounds
  1289. testBound(data4, "X", MatchFullString, true, true, 4, "X\x00\x00\x00");
  1290. testBound(data4, "X", 4, true, true, 4, "X\x00\x00\x00");
  1291. testBound(data4, "X", 3, true, true, 4, "X\x00\x00\x00");
  1292. testBound(data4, "A", MatchFullString, true, false, 4, "A\x00\x00\x01");
  1293. testBound(data4, "A", 4, true, false, 4, "A\x00\x00\x01");
  1294. testBound(data4, "X", 3, true, false, 4, "X\x00\x01\x00");
  1295. //Upper bounds
  1296. testBound(data4, "X", 4, false, true, 4, "X\x00\x00\x00");
  1297. testBound(data4, "X", 3, false, true, 4, "X\x00\x00\xFF");
  1298. testBound(data4, "A", 4, false, false, 4, "@\xFF\xFF\xFF");
  1299. testBound(data4, "X", 3, false, false, 4, "W\xFF\xFF\xFF");
  1300. //Horrible cases
  1301. const RtlQStringTypeInfo qstr4(type_qstring, 4);
  1302. testBoundQstr(qstr4, "AAAA", MatchFullString, true, true, 4, "AAAA");
  1303. testBoundQstr(qstr4, "AAAA", MatchFullString, true, false, 4, "AAAB");
  1304. testBoundQstr(qstr4, "AAAA", 4, true, true, 4, "AAAA");
  1305. testBoundQstr(qstr4, "AAAA", 4, true, false, 4, "AAAB");
  1306. testBoundQstr(qstr4, "AAA ", 3, true, false, 4, "AAB ");
  1307. testBoundQstr(qstr4, "AAAA", 3, true, false, 4, "AAB ");
  1308. testBoundQstr(qstr4, "AA_ ", 3, true, false, 4, "AB ");
  1309. testBoundQstr(qstr4, "A__ ", 3, true, false, 4, "B ");
  1310. testBoundQstr(qstr4, "AA_", 3, true, false, 4, "AB ");
  1311. testBoundQstr(qstr4, "A_X", 2, true, false, 4, "B ");
  1312. testBoundQstr(qstr4, "A_ ", 2, true, false, 4, "B ");
  1313. testBoundQstr(qstr4, "AAAA", MatchFullString, false, true, 4, "AAAA");
  1314. testBoundQstr(qstr4, "AAAA", MatchFullString, false, false, 4, "AAA@");
  1315. testBoundQstr(qstr4, "AAAA", 4, false, true, 4, "AAAA");
  1316. testBoundQstr(qstr4, "AAAA", 4, false, false, 4, "AAA@");
  1317. testBoundQstr(qstr4, "AAA ", 3, false, false, 4, "AA@_");
  1318. testBoundQstr(qstr4, "AAAA", 3, false, false, 4, "AA@_");
  1319. testBoundQstr(qstr4, "AA ", 3, false, false, 4, "A@__");
  1320. testBoundQstr(qstr4, "A ", 3, false, false, 4, "@___");
  1321. testBoundQstr(qstr4, "A X", 2, false, false, 4, "@___");
  1322. testBoundQstr(qstr4, "A ", 2, false, false, 4, "@___");
  1323. testBoundQstr(qstr4, "A ", 4, false, false, 4, "@___");
  1324. testBoundQstr(qstr4, "A X ", 4, false, false, 4, "A W_");
  1325. }
  1326. };
  1327. CPPUNIT_TEST_SUITE_REGISTRATION(ValueSetTest);
  1328. CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(ValueSetTest, "ValueSetTest");
  1329. #endif