test_resource_api.py 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. import pdb
  2. import pytest
  3. from io import BytesIO
  4. from uuid import uuid4
  5. from rdflib import Graph, Literal, URIRef
  6. from lakesuperior.api import resource as rsrc_api
  7. from lakesuperior.dictionaries.namespaces import ns_collection as nsc
  8. from lakesuperior.exceptions import (
  9. IncompatibleLdpTypeError, InvalidResourceError, ResourceNotExistsError,
  10. TombstoneError)
  11. from lakesuperior.globals import RES_CREATED, RES_UPDATED
  12. from lakesuperior.model.ldpr import Ldpr
  13. @pytest.fixture(scope='module')
  14. def random_uuid():
  15. return str(uuid.uuid4())
  16. @pytest.mark.usefixtures('db')
  17. class TestResourceApi:
  18. '''
  19. Test interaction with the Resource API.
  20. '''
  21. def test_nodes_exist(self):
  22. """
  23. Verify whether nodes exist or not.
  24. """
  25. assert rsrc_api.exists('/') is True
  26. assert rsrc_api.exists('/{}'.format(uuid4())) is False
  27. def test_get_root_node_metadata(self):
  28. """
  29. Get the root node metadata.
  30. The ``dcterms:title`` property should NOT be included.
  31. """
  32. gr = rsrc_api.get_metadata('/')
  33. assert isinstance(gr, Graph)
  34. assert len(gr) == 9
  35. assert gr[gr.identifier : nsc['rdf'].type : nsc['ldp'].Resource ]
  36. assert not gr[gr.identifier : nsc['dcterms'].title : "Repository Root"]
  37. def test_get_root_node(self):
  38. """
  39. Get the root node.
  40. The ``dcterms:title`` property should be included.
  41. """
  42. rsrc = rsrc_api.get('/')
  43. assert isinstance(rsrc, Ldpr)
  44. gr = rsrc.imr
  45. assert len(gr) == 10
  46. assert gr[gr.identifier : nsc['rdf'].type : nsc['ldp'].Resource ]
  47. assert gr[
  48. gr.identifier : nsc['dcterms'].title : Literal('Repository Root')]
  49. def test_get_nonexisting_node(self):
  50. """
  51. Get a non-existing node.
  52. """
  53. with pytest.raises(ResourceNotExistsError):
  54. gr = rsrc_api.get('/{}'.format(uuid4()))
  55. def test_create_ldp_rs(self):
  56. """
  57. Create an RDF resource (LDP-RS) from a provided graph.
  58. """
  59. uid = '/rsrc_from_graph'
  60. uri = nsc['fcres'][uid]
  61. gr = Graph().parse(
  62. data='<> a <http://ex.org/type#A> .', format='turtle',
  63. publicID=uri)
  64. #pdb.set_trace()
  65. evt = rsrc_api.create_or_replace(uid, graph=gr)
  66. rsrc = rsrc_api.get(uid)
  67. assert rsrc.imr[
  68. rsrc.uri : nsc['rdf'].type : URIRef('http://ex.org/type#A')]
  69. assert rsrc.imr[
  70. rsrc.uri : nsc['rdf'].type : nsc['ldp'].RDFSource]
  71. def test_create_ldp_nr(self):
  72. """
  73. Create a non-RDF resource (LDP-NR).
  74. """
  75. uid = '/{}'.format(uuid4())
  76. data = b'Hello. This is some dummy content.'
  77. rsrc_api.create_or_replace(
  78. uid, stream=BytesIO(data), mimetype='text/plain')
  79. rsrc = rsrc_api.get(uid)
  80. assert rsrc.content.read() == data
  81. def test_replace_rsrc(self):
  82. uid = '/test_replace'
  83. uri = nsc['fcres'][uid]
  84. gr1 = Graph().parse(
  85. data='<> a <http://ex.org/type#A> .', format='turtle',
  86. publicID=uri)
  87. evt = rsrc_api.create_or_replace(uid, graph=gr1)
  88. assert evt == RES_CREATED
  89. rsrc = rsrc_api.get(uid)
  90. assert rsrc.imr[
  91. rsrc.uri : nsc['rdf'].type : URIRef('http://ex.org/type#A')]
  92. assert rsrc.imr[
  93. rsrc.uri : nsc['rdf'].type : nsc['ldp'].RDFSource]
  94. gr2 = Graph().parse(
  95. data='<> a <http://ex.org/type#B> .', format='turtle',
  96. publicID=uri)
  97. #pdb.set_trace()
  98. evt = rsrc_api.create_or_replace(uid, graph=gr2)
  99. assert evt == RES_UPDATED
  100. rsrc = rsrc_api.get(uid)
  101. assert not rsrc.imr[
  102. rsrc.uri : nsc['rdf'].type : URIRef('http://ex.org/type#A')]
  103. assert rsrc.imr[
  104. rsrc.uri : nsc['rdf'].type : URIRef('http://ex.org/type#B')]
  105. assert rsrc.imr[
  106. rsrc.uri : nsc['rdf'].type : nsc['ldp'].RDFSource]
  107. def test_replace_incompatible_type(self):
  108. """
  109. Verify replacing resources with incompatible type.
  110. Replacing a LDP-NR with a LDP-RS, or vice versa, should fail.
  111. """
  112. uid_rs = '/test_incomp_rs'
  113. uid_nr = '/test_incomp_nr'
  114. data = b'mock binary content'
  115. gr = Graph().parse(
  116. data='<> a <http://ex.org/type#A> .', format='turtle',
  117. publicID=nsc['fcres'][uid_rs])
  118. rsrc_api.create_or_replace(uid_rs, graph=gr)
  119. rsrc_api.create_or_replace(
  120. uid_nr, stream=BytesIO(data), mimetype='text/plain')
  121. with pytest.raises(IncompatibleLdpTypeError):
  122. rsrc_api.create_or_replace(uid_nr, graph=gr)
  123. with pytest.raises(IncompatibleLdpTypeError):
  124. rsrc_api.create_or_replace(
  125. uid_rs, stream=BytesIO(data), mimetype='text/plain')
  126. with pytest.raises(IncompatibleLdpTypeError):
  127. rsrc_api.create_or_replace(uid_nr)
  128. def test_delta_update(self):
  129. """
  130. Update a resource with two sets of add and remove triples.
  131. """
  132. uid = '/test_delta_patch'
  133. uri = nsc['fcres'][uid]
  134. init_trp = {
  135. (URIRef(uri), nsc['rdf'].type, nsc['foaf'].Person),
  136. (URIRef(uri), nsc['foaf'].name, Literal('Joe Bob')),
  137. }
  138. remove_trp = {
  139. (URIRef(uri), nsc['rdf'].type, nsc['foaf'].Person),
  140. }
  141. add_trp = {
  142. (URIRef(uri), nsc['rdf'].type, nsc['foaf'].Organization),
  143. }
  144. gr = Graph()
  145. gr += init_trp
  146. rsrc_api.create_or_replace(uid, graph=gr)
  147. rsrc_api.update_delta(uid, remove_trp, add_trp)
  148. rsrc = rsrc_api.get(uid)
  149. assert rsrc.imr[
  150. rsrc.uri : nsc['rdf'].type : nsc['foaf'].Organization]
  151. assert rsrc.imr[rsrc.uri : nsc['foaf'].name : Literal('Joe Bob')]
  152. assert not rsrc.imr[
  153. rsrc.uri : nsc['rdf'].type : nsc['foaf'].Person]
  154. def test_delta_update_wildcard(self):
  155. """
  156. Update a resource using wildcard modifiers.
  157. """
  158. uid = '/test_delta_patch_wc'
  159. uri = nsc['fcres'][uid]
  160. init_trp = {
  161. (URIRef(uri), nsc['rdf'].type, nsc['foaf'].Person),
  162. (URIRef(uri), nsc['foaf'].name, Literal('Joe Bob')),
  163. (URIRef(uri), nsc['foaf'].name, Literal('Joe Average Bob')),
  164. (URIRef(uri), nsc['foaf'].name, Literal('Joe 12oz Bob')),
  165. }
  166. remove_trp = {
  167. (URIRef(uri), nsc['foaf'].name, None),
  168. }
  169. add_trp = {
  170. (URIRef(uri), nsc['foaf'].name, Literal('Joan Knob')),
  171. }
  172. gr = Graph()
  173. gr += init_trp
  174. rsrc_api.create_or_replace(uid, graph=gr)
  175. rsrc_api.update_delta(uid, remove_trp, add_trp)
  176. rsrc = rsrc_api.get(uid)
  177. assert rsrc.imr[
  178. rsrc.uri : nsc['rdf'].type : nsc['foaf'].Person]
  179. assert rsrc.imr[rsrc.uri : nsc['foaf'].name : Literal('Joan Knob')]
  180. assert not rsrc.imr[rsrc.uri : nsc['foaf'].name : Literal('Joe Bob')]
  181. assert not rsrc.imr[
  182. rsrc.uri : nsc['foaf'].name : Literal('Joe Average Bob')]
  183. assert not rsrc.imr[
  184. rsrc.uri : nsc['foaf'].name : Literal('Joe 12oz Bob')]