test_graph.py 15 KB

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