Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring #17

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 72 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ second_site:
password1: password1
user2: user2
password2: password2
solrurl: http://someserver:8080/solr
triplestoreurl: http://someserver:8080/fuseki/test/sparql
```

To use the `second_site` configuration, simply start the testrunner with
Expand All @@ -82,11 +84,13 @@ You can also choose to run only a subset of all tests using the `-t|--tests` arg
of the following values which indicate which tests to run.
* `authz` - Authorization tests
* `basic` - Basic interaction tests
* `sparql` - Sparql operation tests
* `camel` - Camel toolbox tests (see [note](#camel-tests))
* `fixity` - Binary fixity tests
* `indirect` - Indirect container tests
* `rdf` - RDF serialization tests
* `version` - Versioning tests
* `sparql` - Sparql operation tests
* `transaction` - Transcation tests
* `fixity` - Binary fixity tests
* `version` - Versioning tests

Without this parameter all the above tests will be run.

Expand All @@ -95,6 +99,14 @@ To run only the `authz` and `sparql` tests you would execute:
./testrunner.py -c config.yml -t authz,sparql
```

##### Camel Tests
`camel` tests are **NOT** executed by default, due to timing issues they should be run separately.

They also require the configuration to have a `solrurl` parameter pointing to a Solr endpoint and a
`triplestoreurl` parameter pointing to the SPARQL endpoint of a triplestore.

Both of these systems must be fed by the fcrepo-camel-toolbox for this testing.

## Tests implemented

### authz
Expand All @@ -108,6 +120,34 @@ To run only the `authz` and `sparql` tests you would execute:
1. Verify regular user 1 can access **cover**
1. Verify regular user 2 can't access **cover**


1. Create a container that is readonly for regular user 1
1. Create a container that regular user 1 has read/write access to.
1. Verify that regular user 1 can create/edit/append the container
1. Verify that regular user 1 cannot create a direct or indirect container
that targets the read-only container as the membership resource.


1. Create a container
1. Add an acl with multiple authorizations for user 1
1. Verify that user 1 receives the most permissive set of permissions
from the authorizations


1. Verify that the `rel="acl"` link header is the same for:
* a binary
* its description
* the binary timemap
* the description timemap
* a binary memento
* a description memento


1. Verify that both a binary and its description share the permissions give
to the binary.



### basic
1. Create a container
1. Create a container inside the container from step 1
Expand All @@ -121,11 +161,39 @@ To run only the `authz` and `sparql` tests you would execute:
1. Create a LDP Indirect container
1. Validate the correct Link header type


1. Create a basic container
1. Create an indirect container
1. Create a direct container
1. Create a NonRDFSource
1. Try to create a ldp:Resource (not allowed)
1. Try to create a ldp:Container (not allowed)


1. Try to change each of the following (basic, direct, indirect container
and binary) to all other types.

### camel - see [note](#camel-tests)
1. Create a container
1. Check the container is indexed to Solr
1. Check the container is indexed to the triplestore

### fixity
1. Create a binary resource
1. Get a fixity result for that resource
1. Compare that the SHA-1 hash matches the expected value

### indirect
1. Create a pcdm:Object
2. Create a pcdm:Collection
3. Create an indirect container "members" inside the pcdm:Collection
4. Create a proxy object for the pcdm:Object inside the **members** indirectContainer
5. Verify that the pcdm:Collection has the memberRelation property added pointing to the pcdm:Object

### rdf
1. Create a RDFSource object.
1. Retrieve that object in all possible RDF serializations.

### sparql
1. Create a container
1. Set the dc:title of the container with a Patch request
Expand All @@ -137,7 +205,7 @@ To run only the `authz` and `sparql` tests you would execute:
1. Verify the title
1. Create a container
1. Update the title to text with Unicode characters
1. Verify the title
1. Verify the title

### transaction
1. Create a transaction
Expand Down Expand Up @@ -170,9 +238,3 @@ To run only the `authz` and `sparql` tests you would execute:
1. Create Memento at deleted memento's datetime
1. Verify Memento exists

### indirect
1. Create a pcdm:Object
2. Create a pcdm:Collection
3. Create an indirect container "members" inside the pcdm:Collection
4. Create a proxy object for the pcdm:Object inside the **members** indirectContainer
5. Verify that the pcdm:Collection has the memberRelation property added pointing to the pcdm:Object
25 changes: 22 additions & 3 deletions TestConstants.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,18 @@
USER2_PASS_PARAM = "password2"
LOG_FILE_PARAM = "logfile"
SELECTED_TESTS_PARAM = "selected_tests"
SOLR_URL_PARAM = "solrurl"
TRIPLESTORE_URL_PARAM = "triplestoreurl"
# Via RFC 7231 3.3
PAYLOAD_HEADERS = ['Content-Length', 'Content-Range', 'Trailer', 'Transfer-Encoding']

# Fedora specific constants
FEDORA_NS = "http://fedora.info/definitions/v4/repository#"
FCR_VERSIONS = "fcr:versions"
FCR_FIXITY = "fcr:fixity"
SERVER_MANAGED = "http://fedora.info/definitions/v4/repository#ServerManaged"
INBOUND_REFERENCE = "http://fedora.info/definitions/v4/repository#InboundReferences"
EMBEDED_RESOURCE = "http://fedora.info/definitions/v4/repository#EmbedResources"
SERVER_MANAGED = FEDORA_NS + "ServerManaged"
INBOUND_REFERENCE = FEDORA_NS + "InboundReferences"
EMBEDED_RESOURCE = FEDORA_NS + "EmbedResources"

GET_PREFER_MINIMAL = "return=minimal"
PUT_PREFER_LENIENT = "handling=lenient; received=\"minimal\""
Expand All @@ -31,6 +34,10 @@
# General Mime and LDP constants
JSONLD_MIMETYPE = "application/ld+json"
SPARQL_UPDATE_MIMETYPE = "application/sparql-update"
TURTLE_MIMETYPE = "text/turtle"
SPARQL_QUERY_MIMETYPE = "application/sparql-query"
SPARQL_RESULT_JSON_MIMETYPE = "application/sparql-results+json"
LINK_FORMAT_MIMETYPE = "application/link-format"

LDP_NS = "http://www.w3.org/ns/ldp#"
LDP_CONTAINER = LDP_NS + "Container"
Expand All @@ -44,9 +51,21 @@
MEM_ORIGINAL_RESOURCE = MEMENTO_NS + "OriginalResource"
MEM_TIMEGATE = MEMENTO_NS + "TimeGate"
MEM_TIMEMAP = MEMENTO_NS + "TimeMap"
MEM_MEMENTO = MEMENTO_NS + "Memento"

ACL_NS = "http://www.w3.org/ns/auth/acl#"

PURL_NS = "http://purl.org/dc/elements/1.1/"

# Test constructs
OBJECT_TTL = "@prefix dc: <http://purl.org/dc/elements/1.1/> ." \
"@prefix pcdm: <http://pcdm.org/models#> ." \
"<> a pcdm:Object ;" \
"dc:title \"An Object\" ."

PCDM_CONTAINER_TITLE = "PCDM Container"

PCDM_CONTAINER_TTL = "@prefix dc: <http://purl.org/dc/elements/1.1/> ." \
"@prefix pcdm: <http://pcdm.org/models#> ." \
"<> a pcdm:Object ;" \
"dc:title \"{0}\" .".format(PCDM_CONTAINER_TITLE)
63 changes: 48 additions & 15 deletions abstract_fedora_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,23 @@ def getFedoraBase(self):
""" Return the Fedora Base URI """
return self.config[TestConstants.BASE_URL_PARAM]

@staticmethod
def getCurrentClass():
return inspect.stack()[1][0].f_locals['self'].__class__.__name__

def run_tests(self):
current = FedoraTests.getCurrentClass()
self.check_for_retest(self.getBaseUri())
self.log("\nStarting class {0}\n".format(current))
""" Check we can access the machine and then run the tests """
self.not_authorized()
for test in self._testdict:
method = getattr(self, test)
self.log("Running {0}".format(test))
method()
self.log("Passed\n")
self.cleanup(self.getBaseUri())
self.log("\nExiting class {0}".format(current))

def not_authorized(self):
""" Ensure we can even access the repository """
Expand Down Expand Up @@ -71,6 +80,11 @@ def create_user_auth(self):
return FedoraTests.create_auth(
self.config[TestConstants.USER_NAME_PARAM], self.config[TestConstants.USER_PASS_PARAM])

def create_user2_auth(self):
""" Create a Basic Auth object using the test user 2 username:password """
return FedoraTests.create_auth(
self.config[TestConstants.USER2_NAME_PARAM], self.config[TestConstants.USER2_PASS_PARAM])

def get_auth(self, admin=True):
""" The admin argument of this function is used through out the testing infrastructure, it is explained here.
True - use admin username / password credentials
Expand Down Expand Up @@ -138,6 +152,7 @@ def do_options(self, url, admin=True):
return requests.options(url, auth=my_auth)

def assert_regex_in(self, pattern, container, msg):
""" Do a regex match against all members of a list """
for i in container:
if re.search(pattern, i):
return
Expand All @@ -146,13 +161,15 @@ def assert_regex_in(self, pattern, container, msg):
self.fail(self._formatMessage(msg, standard_msg))

def assert_regex_matches(self, pattern, text, msg):
""" Do a regex match against a string """
if re.search(pattern, text):
return
standard_msg = '%s pattern not matched in %s' % (unittest.util.safe_repr(pattern),
unittest.util.safe_repr(text))
self.fail(self._formatMessage(msg, standard_msg))

def make_type(self, type):
@staticmethod
def make_type(type):
""" Turn a URI to Link type format """
return "<{0}>; rel=\"type\"".format(type)

Expand Down Expand Up @@ -181,21 +198,29 @@ def cleanup(self, uri):

def check_for_retest(self, uri):
"""Try to create CONTAINER """
response = self.do_put(uri)
if response.status_code != 201:
caller = inspect.stack()[1][0].f_locals['self'].__class__.__name__
print("The class ({}) has been run.\nYou need to remove the resource ({}) and all it's "
"children before re-running the test.".format(caller, uri))
rerun = input("Remove the test objects and re-run? (y/N) ")
if rerun.lower().strip() == 'y':
if self.cleanup(uri):
self.do_put(uri)
try:
response = self.do_put(uri)
if response.status_code == 403:
print("Received a 403 Forbidden response, please check your credentials and try again.")
quit()
elif response.status_code != 201:
caller = FedoraTests.getCurrentClass()
print("The class ({0}) has been run.\nYou need to remove the resource ({1}) and all it's "
"children before re-running the test.".format(caller, uri))
rerun = input("Remove the test objects and re-run? (y/N) ")
if rerun.lower().strip() == 'y':
if self.cleanup(uri):
self.do_put(uri)
else:
print("Error removing {0}, you may need to remove it manually.".format(uri))
quit()
else:
print("Error removing $URL, you may need to remove it manually.")
print("Exiting...")
quit()
else:
print("Exiting...")
quit()
except requests.exceptions.ConnectionError:
self.log("Unable to connect to your repository, if you are sure its running. Please check your base uri "
"in the configuration.")
quit()

@staticmethod
def get_link_headers(response):
Expand Down Expand Up @@ -262,14 +287,22 @@ def assertTitleExists(self, expected, location):
return
self.fail("Did not find expected title \"{0}\" in response".format(expected))

def log(self, message):
@staticmethod
def log(message):
print(message)

def find_binary_description(self, response):
headers = FedoraTests.get_link_headers(response)
self.assertIsNotNone(headers['describedby'])
return headers['describedby'][0]

def checkResponse(self, expected, response):
self.checkValue(expected, response.status_code)

def checkValue(self, expected, received):
self.assertEqual(expected, received, "Did not get expected value")
FedoraTests.log(" Passed {0} == {0}".format(received))


def Test(func):
""" Decorator for isolating test functions """
Expand Down
Loading