test_graph.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688
  1. import pytest
  2. from shutil import rmtree
  3. from rdflib import Graph, Namespace, URIRef
  4. from lakesuperior.model.graph.graph import SimpleGraph, Imr
  5. from lakesuperior.store.ldp_rs.lmdb_store import LmdbStore
  6. @pytest.fixture(scope='class')
  7. def store():
  8. """
  9. Test LMDB store.
  10. This store has a different life cycle than the one used for tests in higher
  11. levels of the stack and is not bootstrapped (i.e. starts completely empty).
  12. """
  13. env_path = '/tmp/test_lmdbstore'
  14. # Remove previous test DBs
  15. rmtree(env_path, ignore_errors=True)
  16. store = LmdbStore(env_path)
  17. yield store
  18. store.close()
  19. store.destroy()
  20. @pytest.fixture(scope='class')
  21. def trp():
  22. return (
  23. (URIRef('urn:s:0'), URIRef('urn:p:0'), URIRef('urn:o:0')),
  24. # Exact same as [0].
  25. (URIRef('urn:s:0'), URIRef('urn:p:0'), URIRef('urn:o:0')),
  26. # NOTE: s and o are in reversed order.
  27. (URIRef('urn:o:0'), URIRef('urn:p:0'), URIRef('urn:s:0')),
  28. (URIRef('urn:s:0'), URIRef('urn:p:1'), URIRef('urn:o:0')),
  29. (URIRef('urn:s:0'), URIRef('urn:p:1'), URIRef('urn:o:1')),
  30. (URIRef('urn:s:1'), URIRef('urn:p:1'), URIRef('urn:o:1')),
  31. (URIRef('urn:s:1'), URIRef('urn:p:2'), URIRef('urn:o:2')),
  32. )
  33. @pytest.mark.usefixtures('trp')
  34. @pytest.mark.usefixtures('store')
  35. class TestGraphInit:
  36. """
  37. Test initialization of graphs with different base data sets.
  38. """
  39. def test_empty(self):
  40. """
  41. Test creation of an empty graph.
  42. """
  43. gr = SimpleGraph()
  44. assert len(gr) == 0
  45. def test_init_triples(self, trp):
  46. """
  47. Test creation using a Python set.
  48. """
  49. gr = SimpleGraph(data=set(trp))
  50. assert len(gr) == 6
  51. for t in trp:
  52. assert t in gr
  53. @pytest.mark.usefixtures('trp')
  54. class TestGraphLookup:
  55. """
  56. Test triple lookup.
  57. TODO
  58. """
  59. @pytest.mark.skip(reason='TODO')
  60. def test_lookup_pattern(self, trp):
  61. """
  62. Test lookup by basic pattern.
  63. """
  64. pass
  65. @pytest.mark.usefixtures('trp')
  66. class TestGraphOps:
  67. """
  68. Test various graph operations.
  69. """
  70. def test_len(self, trp):
  71. """
  72. Test the length of a graph with and without duplicates.
  73. """
  74. gr = SimpleGraph()
  75. assert len(gr) == 0
  76. gr.add((trp[0],))
  77. assert len(gr) == 1
  78. gr.add((trp[1],)) # Same values
  79. assert len(gr) == 1
  80. gr.add((trp[2],))
  81. assert len(gr) == 2
  82. gr.add(trp)
  83. assert len(gr) == 6
  84. def test_dup(self, trp):
  85. """
  86. Test operations with duplicate triples.
  87. """
  88. gr = SimpleGraph()
  89. #import pdb; pdb.set_trace()
  90. gr.add((trp[0],))
  91. assert trp[1] in gr
  92. assert trp[2] not in gr
  93. def test_remove(self, trp):
  94. """
  95. Test adding and removing triples.
  96. """
  97. gr = SimpleGraph()
  98. gr.add(trp)
  99. gr.remove(trp[0])
  100. assert len(gr) == 5
  101. assert trp[0] not in gr
  102. assert trp[1] not in gr
  103. # This is the duplicate triple.
  104. gr.remove(trp[1])
  105. assert len(gr) == 5
  106. # This is the triple in reverse order.
  107. gr.remove(trp[2])
  108. assert len(gr) == 4
  109. gr.remove(trp[4])
  110. assert len(gr) == 3
  111. def test_union(self, trp):
  112. """
  113. Test graph union.
  114. """
  115. gr1 = SimpleGraph()
  116. gr2 = SimpleGraph()
  117. gr1.add(trp[0:3])
  118. gr2.add(trp[2:6])
  119. gr3 = gr1 | gr2
  120. assert len(gr3) == 5
  121. assert trp[0] in gr3
  122. assert trp[4] in gr3
  123. def test_ip_union(self, trp):
  124. """
  125. Test graph in-place union.
  126. """
  127. gr1 = SimpleGraph()
  128. gr2 = SimpleGraph()
  129. gr1.add(trp[0:3])
  130. gr2.add(trp[2:6])
  131. gr1 |= gr2
  132. assert len(gr1) == 5
  133. assert trp[0] in gr1
  134. assert trp[4] in gr1
  135. def test_addition(self, trp):
  136. """
  137. Test graph addition.
  138. """
  139. gr1 = SimpleGraph()
  140. gr2 = SimpleGraph()
  141. gr1.add(trp[0:3])
  142. gr2.add(trp[2:6])
  143. gr3 = gr1 + gr2
  144. assert len(gr3) == 5
  145. assert trp[0] in gr3
  146. assert trp[4] in gr3
  147. def test_ip_addition(self, trp):
  148. """
  149. Test graph in-place addition.
  150. """
  151. gr1 = SimpleGraph()
  152. gr2 = SimpleGraph()
  153. gr1.add(trp[0:3])
  154. gr2.add(trp[2:6])
  155. gr1 += gr2
  156. assert len(gr1) == 5
  157. assert trp[0] in gr1
  158. assert trp[4] in gr1
  159. def test_subtraction(self, trp):
  160. """
  161. Test graph addition.
  162. """
  163. gr1 = SimpleGraph()
  164. gr2 = SimpleGraph()
  165. gr1.add(trp[0:4])
  166. gr2.add(trp[2:6])
  167. gr3 = gr1 - gr2
  168. assert len(gr3) == 1
  169. assert trp[0] in gr3
  170. assert trp[1] in gr3
  171. assert trp[2] not in gr3
  172. assert trp[3] not in gr3
  173. assert trp[4] not in gr3
  174. gr3 = gr2 - gr1
  175. assert len(gr3) == 2
  176. assert trp[0] not in gr3
  177. assert trp[1] not in gr3
  178. assert trp[2] not in gr3
  179. assert trp[3] not in gr3
  180. assert trp[4] in gr3
  181. assert trp[5] in gr3
  182. def test_ip_subtraction(self, trp):
  183. """
  184. Test graph in-place addition.
  185. """
  186. gr1 = SimpleGraph()
  187. gr2 = SimpleGraph()
  188. gr1.add(trp[0:4])
  189. gr2.add(trp[2:6])
  190. gr1 -= gr2
  191. assert len(gr1) == 1
  192. assert trp[0] in gr1
  193. assert trp[1] in gr1
  194. assert trp[2] not in gr1
  195. assert trp[3] not in gr1
  196. assert trp[4] not in gr1
  197. def test_intersect(self, trp):
  198. """
  199. Test graph intersextion.
  200. """
  201. gr1 = SimpleGraph()
  202. gr2 = SimpleGraph()
  203. gr1.add(trp[0:4])
  204. gr2.add(trp[2:6])
  205. gr3 = gr1 & gr2
  206. assert len(gr3) == 2
  207. assert trp[2] in gr3
  208. assert trp[3] in gr3
  209. assert trp[0] not in gr3
  210. assert trp[5] not in gr3
  211. def test_ip_intersect(self, trp):
  212. """
  213. Test graph intersextion.
  214. """
  215. gr1 = SimpleGraph()
  216. gr2 = SimpleGraph()
  217. gr1.add(trp[0:4])
  218. gr2.add(trp[2:6])
  219. gr1 &= gr2
  220. assert len(gr1) == 2
  221. assert trp[2] in gr1
  222. assert trp[3] in gr1
  223. assert trp[0] not in gr1
  224. assert trp[5] not in gr1
  225. def test_xor(self, trp):
  226. """
  227. Test graph intersextion.
  228. """
  229. gr1 = SimpleGraph()
  230. gr2 = SimpleGraph()
  231. gr1.add(trp[0:4])
  232. gr2.add(trp[2:6])
  233. gr3 = gr1 ^ gr2
  234. assert len(gr3) == 3
  235. assert trp[2] not in gr3
  236. assert trp[3] not in gr3
  237. assert trp[0] in gr3
  238. assert trp[5] in gr3
  239. def test_ip_xor(self, trp):
  240. """
  241. Test graph intersextion.
  242. """
  243. gr1 = SimpleGraph()
  244. gr2 = SimpleGraph()
  245. gr1.add(trp[0:4])
  246. gr2.add(trp[2:6])
  247. gr1 ^= gr2
  248. assert len(gr1) == 3
  249. assert trp[2] not in gr1
  250. assert trp[3] not in gr1
  251. assert trp[0] in gr1
  252. assert trp[5] in gr1
  253. @pytest.mark.usefixtures('trp')
  254. class TestImrOps:
  255. """
  256. Test various graph operations.
  257. """
  258. def test_len(self, trp):
  259. """
  260. Test the length of a graph with and without duplicates.
  261. """
  262. imr = Imr(uri='http://example.edu/imr01')
  263. assert len(imr) == 0
  264. imr.add((trp[0],))
  265. assert len(imr) == 1
  266. imr.add((trp[1],)) # Same values
  267. assert len(imr) == 1
  268. imr.add((trp[2],))
  269. assert len(imr) == 2
  270. imr.add(trp)
  271. assert len(imr) == 6
  272. def test_dup(self, trp):
  273. """
  274. Test operations with duplicate triples.
  275. """
  276. imr = Imr(uri='http://example.edu/imr01')
  277. #import pdb; pdb.set_trace()
  278. imr.add((trp[0],))
  279. assert trp[1] in imr
  280. assert trp[2] not in imr
  281. def test_remove(self, trp):
  282. """
  283. Test adding and removing triples.
  284. """
  285. imr = Imr(uri='http://example.edu/imr01')
  286. imr.add(trp)
  287. imr.remove(trp[0])
  288. assert len(imr) == 5
  289. assert trp[0] not in imr
  290. assert trp[1] not in imr
  291. # This is the duplicate triple.
  292. imr.remove(trp[1])
  293. assert len(imr) == 5
  294. # This is the triple in reverse order.
  295. imr.remove(trp[2])
  296. assert len(imr) == 4
  297. imr.remove(trp[4])
  298. assert len(imr) == 3
  299. def test_union(self, trp):
  300. """
  301. Test graph union.
  302. """
  303. gr1 = Imr(uri='http://example.edu/imr01')
  304. gr2 = Imr(uri='http://example.edu/imr02')
  305. gr1.add(trp[0:3])
  306. gr2.add(trp[2:6])
  307. gr3 = gr1 | gr2
  308. assert len(gr3) == 5
  309. assert trp[0] in gr3
  310. assert trp[4] in gr3
  311. assert gr3.uri == URIRef('http://example.edu/imr01')
  312. def test_ip_union(self, trp):
  313. """
  314. Test graph in-place union.
  315. """
  316. gr1 = Imr(uri='http://example.edu/imr01')
  317. gr2 = Imr(uri='http://example.edu/imr02')
  318. gr1.add(trp[0:3])
  319. gr2.add(trp[2:6])
  320. gr1 |= gr2
  321. assert len(gr1) == 5
  322. assert trp[0] in gr1
  323. assert trp[4] in gr1
  324. assert gr1.uri == URIRef('http://example.edu/imr01')
  325. def test_addition(self, trp):
  326. """
  327. Test graph addition.
  328. """
  329. gr1 = Imr(uri='http://example.edu/imr01')
  330. gr2 = Imr(uri='http://example.edu/imr02')
  331. gr1.add(trp[0:3])
  332. gr2.add(trp[2:6])
  333. gr3 = gr1 + gr2
  334. assert len(gr3) == 5
  335. assert trp[0] in gr3
  336. assert trp[4] in gr3
  337. assert gr3.uri == URIRef('http://example.edu/imr01')
  338. def test_ip_addition(self, trp):
  339. """
  340. Test graph in-place addition.
  341. """
  342. gr1 = Imr(uri='http://example.edu/imr01')
  343. gr2 = Imr(uri='http://example.edu/imr02')
  344. gr1.add(trp[0:3])
  345. gr2.add(trp[2:6])
  346. gr1 += gr2
  347. assert len(gr1) == 5
  348. assert trp[0] in gr1
  349. assert trp[4] in gr1
  350. assert gr1.uri == URIRef('http://example.edu/imr01')
  351. def test_subtraction(self, trp):
  352. """
  353. Test graph addition.
  354. """
  355. gr1 = Imr(uri='http://example.edu/imr01')
  356. gr2 = Imr(uri='http://example.edu/imr02')
  357. gr1.add(trp[0:4])
  358. gr2.add(trp[2:6])
  359. gr3 = gr1 - gr2
  360. assert len(gr3) == 1
  361. assert trp[0] in gr3
  362. assert trp[1] in gr3
  363. assert trp[2] not in gr3
  364. assert trp[3] not in gr3
  365. assert trp[4] not in gr3
  366. assert gr3.uri == URIRef('http://example.edu/imr01')
  367. gr3 = gr2 - gr1
  368. assert len(gr3) == 2
  369. assert trp[0] not in gr3
  370. assert trp[1] not in gr3
  371. assert trp[2] not in gr3
  372. assert trp[3] not in gr3
  373. assert trp[4] in gr3
  374. assert trp[5] in gr3
  375. assert gr3.uri == URIRef('http://example.edu/imr02')
  376. def test_ip_subtraction(self, trp):
  377. """
  378. Test graph in-place addition.
  379. """
  380. gr1 = Imr(uri='http://example.edu/imr01')
  381. gr2 = Imr(uri='http://example.edu/imr02')
  382. gr1.add(trp[0:4])
  383. gr2.add(trp[2:6])
  384. gr1 -= gr2
  385. assert len(gr1) == 1
  386. assert trp[0] in gr1
  387. assert trp[1] in gr1
  388. assert trp[2] not in gr1
  389. assert trp[3] not in gr1
  390. assert trp[4] not in gr1
  391. assert gr1.uri == URIRef('http://example.edu/imr01')
  392. def test_intersect(self, trp):
  393. """
  394. Test graph intersextion.
  395. """
  396. gr1 = Imr(uri='http://example.edu/imr01')
  397. gr2 = Imr(uri='http://example.edu/imr02')
  398. gr1.add(trp[0:4])
  399. gr2.add(trp[2:6])
  400. gr3 = gr1 & gr2
  401. assert len(gr3) == 2
  402. assert trp[2] in gr3
  403. assert trp[3] in gr3
  404. assert trp[0] not in gr3
  405. assert trp[5] not in gr3
  406. assert gr3.uri == URIRef('http://example.edu/imr01')
  407. def test_ip_intersect(self, trp):
  408. """
  409. Test graph intersextion.
  410. """
  411. gr1 = Imr(uri='http://example.edu/imr01')
  412. gr2 = Imr(uri='http://example.edu/imr02')
  413. gr1.add(trp[0:4])
  414. gr2.add(trp[2:6])
  415. gr1 &= gr2
  416. assert len(gr1) == 2
  417. assert trp[2] in gr1
  418. assert trp[3] in gr1
  419. assert trp[0] not in gr1
  420. assert trp[5] not in gr1
  421. assert gr1.uri == URIRef('http://example.edu/imr01')
  422. def test_xor(self, trp):
  423. """
  424. Test graph intersextion.
  425. """
  426. gr1 = Imr(uri='http://example.edu/imr01')
  427. gr2 = Imr(uri='http://example.edu/imr02')
  428. gr1.add(trp[0:4])
  429. gr2.add(trp[2:6])
  430. gr3 = gr1 ^ gr2
  431. assert len(gr3) == 3
  432. assert trp[2] not in gr3
  433. assert trp[3] not in gr3
  434. assert trp[0] in gr3
  435. assert trp[5] in gr3
  436. assert gr3.uri == URIRef('http://example.edu/imr01')
  437. def test_ip_xor(self, trp):
  438. """
  439. Test graph intersextion.
  440. """
  441. gr1 = Imr(uri='http://example.edu/imr01')
  442. gr2 = Imr(uri='http://example.edu/imr02')
  443. gr1.add(trp[0:4])
  444. gr2.add(trp[2:6])
  445. gr1 ^= gr2
  446. assert len(gr1) == 3
  447. assert trp[2] not in gr1
  448. assert trp[3] not in gr1
  449. assert trp[0] in gr1
  450. assert trp[5] in gr1
  451. assert gr1.uri == URIRef('http://example.edu/imr01')
  452. @pytest.mark.usefixtures('trp')
  453. class TestHybridOps:
  454. """
  455. Test operations between IMR and graph.
  456. """
  457. def test_union(self, trp):
  458. """
  459. Test hybrid IMR + graph union.
  460. """
  461. gr1 = Imr(uri='http://example.edu/imr01')
  462. gr2 = SimpleGraph()
  463. gr1.add(trp[0:3])
  464. gr2.add(trp[2:6])
  465. gr3 = gr1 | gr2
  466. assert len(gr3) == 5
  467. assert trp[0] in gr3
  468. assert trp[4] in gr3
  469. assert isinstance(gr3, Imr)
  470. assert gr3.uri == URIRef('http://example.edu/imr01')
  471. gr4 = gr2 | gr1
  472. assert isinstance(gr4, SimpleGraph)
  473. assert gr3 == gr4
  474. def test_ip_union_imr(self, trp):
  475. """
  476. Test IMR + graph in-place union.
  477. """
  478. gr1 = Imr(uri='http://example.edu/imr01')
  479. gr2 = SimpleGraph()
  480. gr1.add(trp[0:3])
  481. gr2.add(trp[2:6])
  482. gr1 |= gr2
  483. assert len(gr1) == 5
  484. assert trp[0] in gr1
  485. assert trp[4] in gr1
  486. assert gr1.uri == URIRef('http://example.edu/imr01')
  487. def test_ip_union_gr(self, trp):
  488. """
  489. Test graph + IMR in-place union.
  490. """
  491. gr1 = SimpleGraph()
  492. gr2 = Imr(uri='http://example.edu/imr01')
  493. gr1.add(trp[0:3])
  494. gr2.add(trp[2:6])
  495. gr1 |= gr2
  496. assert len(gr1) == 5
  497. assert trp[0] in gr1
  498. assert trp[4] in gr1
  499. assert isinstance(gr1, SimpleGraph)