From af77eb7fe1359ff21fc2ba40e6c879fd355b4c8a Mon Sep 17 00:00:00 2001 From: Anusha Ranganathan Date: Tue, 20 Sep 2011 11:52:36 +0100 Subject: [PATCH] Databank now support 3 embargo states - Dark, Embargoed and Open. Added a profiler to the pylons middleware --- development-jenkins.ini | 2 +- development.ini | 24 +- production.ini | 4 +- rdfdatabank/config/middleware.py | 10 +- rdfdatabank/controllers/datasets.py | 54 +- rdfdatabank/controllers/users.py | 1 + rdfdatabank/lib/file_unpack.py | 31 +- rdfdatabank/lib/utils.py | 39 +- rdfdatabank/templates/datasetview.html | 2 +- rdfdatabank/templates/part_list.html | 12 +- rdfdatabank/templates/part_list_display.html | 11 +- rdfdatabank/templates/rdf_manifest_form.html | 2 +- rdfdatabank/tests/TestSubmission.py | 1713 ++++++++++++----- rdfdatabank/tests/TestSubmission_load.py | 319 +++ rdfdatabank/tests/TestSubmission_submitter.py | 227 +-- rdfdatabank/tests/testdata/rdfdatabank.zip | Bin 0 -> 376392 bytes requirements-dev.txt | 13 + requirements.txt | 2 + 18 files changed, 1777 insertions(+), 689 deletions(-) create mode 100644 rdfdatabank/tests/TestSubmission_load.py create mode 100644 rdfdatabank/tests/testdata/rdfdatabank.zip create mode 100644 requirements-dev.txt diff --git a/development-jenkins.ini b/development-jenkins.ini index 71e005b..dd0421b 100644 --- a/development-jenkins.ini +++ b/development-jenkins.ini @@ -8,7 +8,7 @@ debug = false # Uncomment and replace with the address which should receive any error reports #email_to = you@yourdomain.com smtp_server = localhost -error_email_from = paste@localhost +error_email_from = paste@jenkins [server:main] use = egg:Paste#http diff --git a/development.ini b/development.ini index 516bbdf..6bad250 100644 --- a/development.ini +++ b/development.ini @@ -4,7 +4,7 @@ # The %(here)s variable will be replaced with the parent directory of this file # [DEFAULT] -debug = false +debug = true # Uncomment and replace with the address which should receive any error reports #email_to = you@yourdomain.com smtp_server = localhost @@ -13,11 +13,11 @@ error_email_from = paste@localhost [server:main] use = egg:Paste#http #Use these setings to run pylons using mod_wsgi and apache -host = 127.0.0.1 -port = 5000 +#host = 127.0.0.1 +#port = 5000 #Use these settings tp run pylons from the commandline -#host = 0.0.0.0 -#port = 80 +host = 0.0.0.0 +port = 80 [app:main] use = egg:rdfdatabank @@ -30,16 +30,18 @@ beaker.session.secret = somesecret who.config_file = %(here)s/who.ini who.log_level = info -who.log_file = /var/log/databank/who.log -#who.log_file = stdout +#who.log_file = /var/log/databank/who.log +who.log_file = stdout #who.log_file = %(here)s/logs/who.log redis.host = localhost granary.store = %(here)s/silos -#granary.uri_root = http://databank.bodleian.ox.ac.uk/datasets/ granary.uri_root = http://192.168.23.133/ +profile.log_filename = %(here)s/logs/profile.log +profile.path = /__profile__ + auth.file = %(here)s/passwd auth.info = %(here)s/rdfdatabank/config/users.py @@ -80,17 +82,17 @@ keys = generic [logger_root] level = INFO -handlers = logfile +handlers = console [logger_routes] level = INFO -handlers = logfile +handlers = console qualname = routes.middleware # "level = DEBUG" logs the route matched and routing variables. [logger_rdfdatabank] level = DEBUG -handlers = logfile +handlers = console qualname = rdfdatabank [handler_console] diff --git a/production.ini b/production.ini index 930caa7..02aad1a 100644 --- a/production.ini +++ b/production.ini @@ -8,7 +8,7 @@ debug = false # Uncomment and replace with the address which should receive any error reports email_to = anusha.ranganathan@bodleian.ox.ac.uk smtp_server = localhost -error_email_from = paste@localhost +error_email_from = paste@databank [server:main] use = egg:Paste#http @@ -35,10 +35,8 @@ who.log_file = /var/log/databank/who.log redis.host = localhost -#granary.store = %(here)s/silos granary.store = /silos granary.uri_root = http://databank.ora.ox.ac.uk/ -#granary.uri_root = http://163.1.127.173/ auth.file = %(here)s/passwd auth.info = %(here)s/rdfdatabank/config/users.py diff --git a/rdfdatabank/config/middleware.py b/rdfdatabank/config/middleware.py index a0f7371..d65d79e 100644 --- a/rdfdatabank/config/middleware.py +++ b/rdfdatabank/config/middleware.py @@ -46,13 +46,21 @@ def make_app(global_conf, full_stack=True, static_files=True, **app_conf): app = PylonsApp() #app = httpexceptions.make_middleware(app, global_conf) + if asbool(config['debug']): + from repoze.profile.profiler import AccumulatingProfileMiddleware + app = AccumulatingProfileMiddleware( + app, + log_filename=app_conf['profile.log_filename'], + discard_first_request=True, + flush_at_shutdown=True, + path=app_conf['profile.path'] + ) # Routing/Session/Cache Middleware app = RoutesMiddleware(app, config['routes.map']) app = SessionMiddleware(app, config) app = CacheMiddleware(app, config) - # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) if asbool(full_stack): # Handle Python exceptions diff --git a/rdfdatabank/controllers/datasets.py b/rdfdatabank/controllers/datasets.py index 31e367b..f2e51ef 100644 --- a/rdfdatabank/controllers/datasets.py +++ b/rdfdatabank/controllers/datasets.py @@ -3,6 +3,8 @@ import re, os, shutil, codecs import simplejson from datetime import datetime, timedelta +from dateutil.relativedelta import * +from dateutil.parser import parse import time from uuid import uuid4 from pylons import request, response, session, tmpl_context as c, url, app_globals as ag @@ -10,7 +12,7 @@ from pylons.decorators import rest from paste.fileapp import FileApp from rdfdatabank.lib.base import BaseController, render -from rdfdatabank.lib.utils import create_new, is_embargoed, get_readme_text, test_rdf, munge_manifest, serialisable_stat, allowable_id2 +from rdfdatabank.lib.utils import create_new, is_embargoed, get_readme_text, test_rdf, munge_manifest, serialisable_stat, allowable_id2, get_rdf_template from rdfdatabank.lib.file_unpack import get_zipfiles_in_dataset from rdfdatabank.lib.conneg import MimeType as MT, parse as conneg_parse @@ -218,14 +220,16 @@ def datasetview(self, silo, id): if ident['repoze.who.userid'] == creator or ident.get('role') in ["admin", "manager"]: c.editor = True - if c.version and not c.version == currentversion: - c.editor = False - + c.show_files = True #Only the administrator, manager and creator can view embargoed files. if embargoed and not c.editor: c.show_files = False + #Display but do not edit previous versions of files, since preious versions are read only. + if c.version and not c.version == currentversion: + c.editor = False + # View options if "view" in options and c.editor: c.view = options['view'] @@ -240,7 +244,8 @@ def datasetview(self, silo, id): c.embargos[id] = is_embargoed(c_silo, id) c.parts = item.list_parts(detailed=True) c.manifest_pretty = item.rdf_to_string(format="pretty-xml") - c.manifest = item.rdf_to_string() + #c.manifest = item.rdf_to_string() + c.manifest = get_rdf_template(item.uri, id) c.zipfiles = get_zipfiles_in_dataset(item) c.readme_text = None #if item.isfile("README"): @@ -366,20 +371,28 @@ def datasetview(self, silo, id): abort(403) item.increment_version_delta(clone_previous_version=True, copy_filenames=['manifest.rdf']) #if params.has_key('embargoed'): - if (params.has_key('embargo_change') and params.has_key('embargoed')) or \ - (params.has_key('embargoed') and params['embargoed'].lower() == 'true'): + if (params.has_key('embargo_change') and params.has_key('embargoed') and \ + params['embargoed'].lower() in ['true', '1'] and params['embargo_change'].lower() in ['true', '1']) or \ + (params.has_key('embargoed') and params['embargoed'].lower() in ['true', '1']): + embargoed_until_date = None if params.has_key('embargoed_until') and params['embargoed_until']: - embargoed_until_date = params['embargoed_until'] - elif params.has_key('embargo_days_from_now') and params['embargo_days_from_now']: - embargoed_until_date = (datetime.now() + timedelta(days=params['embargo_days_from_now'])).isoformat() - else: - embargoed_until_date = (datetime.now() + timedelta(days=365*70)).isoformat() + try: + embargoed_until_date = parse(params['embargoed_until']).isoformat() + except: + embargoed_until_date = (datetime.now() + relativedelta(years=+70)).isoformat() + elif params.has_key('embargo_days_from_now') and params['embargo_days_from_now'].isdigit(): + embargoed_until_date = (datetime.now() + timedelta(days=int(params['embargo_days_from_now']))).isoformat() + #It is embargoed indefinitely by default + #else: + # embargoed_until_date = (datetime.now() + timedelta(days=365*70)).isoformat() item.metadata['embargoed'] = True - item.metadata['embargoed_until'] = embargoed_until_date + item.metadata['embargoed_until'] = '' item.del_triple(item.uri, u"oxds:isEmbargoed") item.del_triple(item.uri, u"oxds:embargoedUntil") item.add_triple(item.uri, u"oxds:isEmbargoed", 'True') - item.add_triple(item.uri, u"oxds:embargoedUntil", embargoed_until_date) + if embargoed_until_date: + item.metadata['embargoed_until'] = embargoed_until_date + item.add_triple(item.uri, u"oxds:embargoedUntil", embargoed_until_date) else: #if is_embargoed(c_silo, id)[0] == True: item.metadata['embargoed'] = False @@ -822,13 +835,15 @@ def itemview(self, silo, id, path): if ident['repoze.who.userid'] == creator or ident.get('role') in ["admin", "manager"]: c.editor = True - if c.version and not c.version == currentversion: - c.editor = False - c.show_files = True + #Only the administrator, manager and creator can view embargoed files. if embargoed and not c.editor: c.show_files = False + #Display but do not edit previous versions of files, since preious versions are read only. + if c.version and not c.version == currentversion: + c.editor = False + # View options if "view" in options and c.editor: c.view = options['view'] @@ -1063,6 +1078,11 @@ def itemview(self, silo, id, path): response.status_int = 403 response.status = "403 Forbidden" return "Forbidden - Cannot delete the manifest" + if '3=' in path or '4=' in path: + response.content_type = "text/plain" + response.status_int = 403 + response.status = "403 Forbidden" + return "Forbidden - These files are generated by the system and connot be deleted" item.increment_version_delta(clone_previous_version=True, copy_filenames=['manifest.rdf']) item.del_stream(path) item.del_triple(item.uri, u"dcterms:modified") diff --git a/rdfdatabank/controllers/users.py b/rdfdatabank/controllers/users.py index 7fb88ef..dd399b0 100644 --- a/rdfdatabank/controllers/users.py +++ b/rdfdatabank/controllers/users.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- import logging import simplejson +import codecs from pylons import request, response, session, config, tmpl_context as c, url from pylons.controllers.util import abort, redirect from pylons.decorators import rest diff --git a/rdfdatabank/lib/file_unpack.py b/rdfdatabank/lib/file_unpack.py index fc18a80..3719b46 100644 --- a/rdfdatabank/lib/file_unpack.py +++ b/rdfdatabank/lib/file_unpack.py @@ -19,8 +19,12 @@ class BadZipfile(Exception): """Cannot open zipfile using commandline tool 'unzip' to target directory""" def check_file_mimetype(real_filepath, mimetype): + if os.path.isdir(real_filepath): + return False if os.path.islink(real_filepath): real_filepath = os.readlink(real_filepath) + if not os.path.isfile(real_filepath): + return False p = subprocess.Popen("file -ib '%s'" %(real_filepath), shell=True, stdout=subprocess.PIPE) output_file = p.stdout output_str = output_file.read() @@ -29,11 +33,15 @@ def check_file_mimetype(real_filepath, mimetype): else: return False -def get_zipfiles_in_dataset_old(dataset): +def get_zipfiles_in_dataset(dataset): derivative = dataset.list_rdf_objects("*", "ore:aggregates") zipfiles = {} - if derivative and derivative.values() and derivative.values()[0]: - for file_uri in derivative.values()[0]: + #if derivative and derivative.values() and derivative.values()[0]: + if derivative: + #for file_uri in derivative.values()[0]: + for file_uri in derivative: + if not file_uri.lower().endswith('.zip'): + continue filepath = file_uri[len(dataset.uri)+1:] real_filepath = dataset.to_dirpath(filepath) if os.path.islink(real_filepath): @@ -43,7 +51,7 @@ def get_zipfiles_in_dataset_old(dataset): zipfiles[filepath]="%s-%s"%(dataset.item_id, fn) return zipfiles -def get_zipfiles_in_dataset(dataset): +def get_zipfiles_in_dataset_new(dataset): p = subprocess.Popen("""file -iL `find %s -name '*.zip'` | grep "application/zip" | awk -F":" '{print $1}'""" %dataset.to_dirpath(), shell=True, stdout=subprocess.PIPE) stdout_value = p.communicate()[0] zipfiles = {} @@ -148,6 +156,9 @@ def unpack_zip_item(target_dataset, current_dataset, zip_item, silo, ident): if os.path.islink(filepath): filepath = os.readlink(filepath) + emb = target_dataset.metadata.get('embargoed') + emb_until = target_dataset.metadata.get('embargoed_until') + # -- Step 1 ----------------------------- unpacked_dir = unzip_file(filepath) @@ -181,9 +192,15 @@ def unpack_zip_item(target_dataset, current_dataset, zip_item, silo, ident): target_dataset.add_triple(target_dataset.uri, u"rdf:type", "oxds:Grouping") target_dataset.add_triple(target_dataset.uri, "dcterms:isVersionOf", file_uri) #TODO: Adding the following metadata again as moving directory deletes all this information. Need to find a better way - embargoed_until_date = (datetime.now() + timedelta(days=365*70)).isoformat() - target_dataset.add_triple(target_dataset.uri, u"oxds:isEmbargoed", 'True') - target_dataset.add_triple(target_dataset.uri, u"oxds:embargoedUntil", embargoed_until_date) + if emb: + target_dataset.add_triple(target_dataset.uri, u"oxds:isEmbargoed", 'True') + if emb_until: + target_dataset.add_triple(target_dataset.uri, u"oxds:embargoedUntil", emb_until) + else: + target_dataset.add_triple(target_dataset.uri, u"oxds:isEmbargoed", 'False') + #The embargo + #embargoed_until_date = (datetime.now() + timedelta(days=365*70)).isoformat() + #target_dataset.add_triple(target_dataset.uri, u"oxds:embargoedUntil", embargoed_until_date) target_dataset.add_triple(target_dataset.uri, u"dcterms:identifier", target_dataset.item_id) target_dataset.add_triple(target_dataset.uri, u"dcterms:mediator", ident) target_dataset.add_triple(target_dataset.uri, u"dcterms:publisher", ag.publisher) diff --git a/rdfdatabank/lib/utils.py b/rdfdatabank/lib/utils.py index 0c40d8d..7d8de48 100644 --- a/rdfdatabank/lib/utils.py +++ b/rdfdatabank/lib/utils.py @@ -1,5 +1,7 @@ # -*- coding: utf-8 -*- from datetime import datetime, timedelta +from dateutil.relativedelta import * +from dateutil.parser import parse from time import sleep from redis import Redis from redis.exceptions import ConnectionError @@ -14,6 +16,7 @@ #from rdflib.parser import StringInputSource from rdflib import Namespace, RDF, RDFS, URIRef, Literal, BNode + from uuid import uuid4 import re @@ -146,23 +149,31 @@ def is_embargoed_no_redis(silo, id, refresh=False): def create_new(silo, id, creator, title=None, embargoed=True, embargoed_until=None, embargo_days_from_now=None, **kw): item = silo.get_item(id, startversion="0") item.metadata['createdby'] = creator - item.metadata['embargoed'] = embargoed + item.metadata['embargoed_until'] = '' item.metadata['uuid'] = uuid4().hex item.add_namespace('oxds', "http://vocab.ox.ac.uk/dataset/schema#") item.add_triple(item.uri, u"rdf:type", "oxds:DataSet") - if embargoed: - if embargoed_until: - embargoed_until_date = embargoed_until - elif embargo_days_from_now: - embargoed_until_date = (datetime.now() + timedelta(days=embargo_days_from_now)).isoformat() - else: - embargoed_until_date = (datetime.now() + timedelta(days=365*70)).isoformat() - item.metadata['embargoed_until'] = embargoed_until_date + if embargoed==True or embargoed.lower() in ['true', '1'] : + item.metadata['embargoed'] = True item.add_triple(item.uri, u"oxds:isEmbargoed", 'True') - item.add_triple(item.uri, u"oxds:embargoedUntil", embargoed_until_date) + embargoed_until_date = None + if embargoed_until: + try: + embargoed_until_date = parse(embargoed_until).isoformat() + except: + embargoed_until_date = (datetime.now() + relativedelta(years=+70)).isoformat() + elif embargo_days_from_now and embargo_days_from_now.isdigit(): + embargoed_until_date = (datetime.now() + timedelta(days=int(embargo_days_from_now))).isoformat() + #TODO: Do we want the default embargo_until to be 70 years or indefinite. Going with indefinite + #else: + # embargoed_until_date = (datetime.now() + relativedelta(years=+70)).isoformat() + if embargoed_until_date: + item.metadata['embargoed_until'] = embargoed_until_date + item.add_triple(item.uri, u"oxds:embargoedUntil", embargoed_until_date) else: item.add_triple(item.uri, u"oxds:isEmbargoed", 'False') + item.metadata['embargoed'] = False item.add_triple(item.uri, u"dcterms:identifier", id) item.add_triple(item.uri, u"dcterms:mediator", creator) item.add_triple(item.uri, u"dcterms:publisher", ag.publisher) @@ -188,6 +199,14 @@ def get_readme_text(item, filename="README"): text = fn.read().decode("utf-8") return u"%s\n\n%s" % (filename, text) +def get_rdf_template(item_uri, item_id): + g = ConjunctiveGraph(identifier=item_uri) + g.bind('rdf', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#') + g.bind('dcterms', 'http://purl.org/dc/terms/') + g.add((URIRef(item_uri), URIRef('http://purl.org/dc/terms/identifier'), Literal(item_id))) + data2 = g.serialize(format='xml', encoding="utf-8") + '\n' + return data2 + #def test_rdf(text): def test_rdf(mfile): g = ConjunctiveGraph() diff --git a/rdfdatabank/templates/datasetview.html b/rdfdatabank/templates/datasetview.html index e1952a9..3e40b18 100644 --- a/rdfdatabank/templates/datasetview.html +++ b/rdfdatabank/templates/datasetview.html @@ -90,7 +90,7 @@

Information for version ${c.version} of the dataset

Embargo date: Aim is for ISO8601 dates to provide embargo trigger events. Currently unused, unvalidated and unparsed.

-
Change RDF Manifest:
+
Add metadata to the RDF Manifest:
<%include file="/rdf_manifest_form.html"/>
diff --git a/rdfdatabank/templates/part_list.html b/rdfdatabank/templates/part_list.html index a68c356..57bcebc 100644 --- a/rdfdatabank/templates/part_list.html +++ b/rdfdatabank/templates/part_list.html @@ -9,18 +9,22 @@ %> % if c.version: % for part in c.parts: -% if type(c.parts).__name__ == 'dict' and c.parts[part]: +% if not part.startswith('3=') and not part.startswith('4='): +% if type(c.parts).__name__ == 'dict' and c.parts[part]:
  • ${part} ${h.bytes_to_english(c.parts[part].st_size)}
  • -% else: +% else:
  • ${part}
  • +% endif % endif % endfor % else: % for part in c.parts: -% if type(c.parts).__name__ == 'dict' and c.parts[part]: +% if not part.startswith('3=') and not part.startswith('4='): +% if type(c.parts).__name__ == 'dict' and c.parts[part]:
  • ${part} ${h.bytes_to_english(c.parts[part].st_size)} - (remove)
  • -% else: +% else:
  • ${part} - (remove)
  • +% endif % endif % endfor % endif diff --git a/rdfdatabank/templates/part_list_display.html b/rdfdatabank/templates/part_list_display.html index 8630da2..64fd93f 100644 --- a/rdfdatabank/templates/part_list_display.html +++ b/rdfdatabank/templates/part_list_display.html @@ -11,11 +11,14 @@ else: ver = "" %> + % for part in c.parts: - % if type(c.parts).__name__ == 'dict' and c.parts[part]: -
  • ${part} ${h.bytes_to_english(c.parts[part].st_size)}
  • - % else: -
  • ${part}
  • + % if not part.startswith('3=') and not part.startswith('4='): + % if type(c.parts).__name__ == 'dict' and c.parts[part]: +
  • ${part} ${h.bytes_to_english(c.parts[part].st_size)}
  • + % else: +
  • ${part}
  • + % endif % endif % endfor diff --git a/rdfdatabank/templates/rdf_manifest_form.html b/rdfdatabank/templates/rdf_manifest_form.html index bc63ad6..dff68af 100644 --- a/rdfdatabank/templates/rdf_manifest_form.html +++ b/rdfdatabank/templates/rdf_manifest_form.html @@ -5,6 +5,6 @@ ${c.manifest}
    - +

    diff --git a/rdfdatabank/tests/TestSubmission.py b/rdfdatabank/tests/TestSubmission.py index 0258ceb..1908813 100644 --- a/rdfdatabank/tests/TestSubmission.py +++ b/rdfdatabank/tests/TestSubmission.py @@ -9,6 +9,7 @@ """ import os, os.path from datetime import datetime, timedelta +from dateutil.relativedelta import * import sys import unittest import logging @@ -78,11 +79,23 @@ def tearDown(self): return # Create empty test submission dataset - def createSubmissionDataset(self): + def createSubmissionDataset(self, embargoed=None, embargoed_until=None): # Create a new dataset, check response fields = \ [ ("id", "TestSubmission") ] + if embargoed != None: + if embargoed: + fields.append(('embargoed', 'True')) + else: + fields.append(('embargoed', 'False')) + if embargoed_until != None: + if embargoed_until == True: + fields.append(('embargoed_until', 'True')) + elif embargoed_until == False: + fields.append(('embargoed_until', 'False')) + else: + fields.append(('embargoed_until', embargoed_until)) files =[] (reqtype, reqdata) = SparqlQueryTestCase.encode_multipart_formdata(fields, files) (resp,respdata) = self.doHTTP_POST( @@ -287,7 +300,7 @@ def testDatasetCreation(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),10,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),9,'Graph length %i' %len(rdfgraph)) oxds = "http://vocab.ox.ac.uk/dataset/schema#" dcterms = "http://purl.org/dc/terms/" subj = URIRef(self.getRequestUri("datasets/TestSubmission")) @@ -298,8 +311,7 @@ def testDatasetCreation(self): self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') self.failUnless((subj,URIRef(oxds+"currentVersion"),'0') in rdfgraph, 'oxds:currentVersion') def testDatasetCreation2(self): @@ -322,7 +334,7 @@ def testDatasetCreation2(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),10,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),9,'Graph length %i' %len(rdfgraph)) oxds = "http://vocab.ox.ac.uk/dataset/schema#" dcterms = "http://purl.org/dc/terms/" subj = URIRef(self.getRequestUri("datasets/TestSubmission")) @@ -334,7 +346,6 @@ def testDatasetCreation2(self): self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(oxds+"currentVersion"),'0') in rdfgraph, 'oxds:currentVersion') def testDatasetRecreation(self): @@ -348,7 +359,7 @@ def testDatasetRecreation(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),10,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),9,'Graph length %i' %len(rdfgraph)) #Recreate the dataset, check response fields = \ [ ("id", "TestSubmission") @@ -374,7 +385,7 @@ def testDatasetRecreation(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),10,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),9,'Graph length %i' %len(rdfgraph)) def testDeleteDataset(self): """Delete dataset - DELETE /silo_name/dataset_name""" @@ -430,7 +441,7 @@ def testDatasetNaming(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),10,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),9,'Graph length %i' %len(rdfgraph)) elif status == 403: (resp, respdata) = self.doHTTP_GET( resource="datasets/%s"%name, @@ -471,254 +482,185 @@ def testDatasetStateInformation(self): self.assertEqual(len(parts['4=TestSubmission'].keys()), 13, "File stats for 4=TestSubmission") self.assertEqual(len(parts['manifest.rdf'].keys()), 13, "File stats for manifest.rdf") - def testFileUpload(self): - """Upload file to dataset - POST file to /silo_name/datasets/dataset_name""" - # Create a new dataset, check response + def testEmbargoOnCreation(self): + """Create dataset - POST id to /silo_name""" + #--------------------------------------------------------------- + # Create a new dataset, check response. No embargo information is passed. self.createSubmissionDataset() - #Access state information - (resp, respdata) = self.doHTTP_GET( - resource="states/TestSubmission", - expect_status=200, expect_reason="OK", expect_type="application/json") - # Upload zip file, check response - zipdata = self.uploadSubmissionZipfile() - # Access and check list of contents + # Access dataset, check response (resp, rdfdata) = self.doHTTP_GET( resource="datasets/TestSubmission", expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - subj = URIRef(self.getRequestUri("datasets/TestSubmission")) - base = self.getRequestUri("datasets/TestSubmission/") - dcterms = "http://purl.org/dc/terms/" - ore = "http://www.openarchives.org/ore/terms/" + self.assertEqual(len(rdfgraph),9,'Graph length %i' %len(rdfgraph)) oxds = "http://vocab.ox.ac.uk/dataset/schema#" + dcterms = "http://purl.org/dc/terms/" + subj = URIRef(self.getRequestUri("datasets/TestSubmission")) stype = URIRef(oxds+"DataSet") - self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) - self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') - self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"testdir.zip")) in rdfgraph) - self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') - self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') - self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') - self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') - self.failUnless((subj,URIRef(oxds+"currentVersion"),'1') in rdfgraph, 'oxds:currentVersion') - self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') - # Access and check zip file content - (resp, zipfile) = self.doHTTP_GET( - resource="datasets/TestSubmission/testdir.zip", - expect_status=200, expect_reason="OK", expect_type="application/zip") - self.assertEqual(zipdata, zipfile, "Difference between local and remote zipfile!") - #Access state information and check + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') + self.assertFalse((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"currentVersion"),'0') in rdfgraph, 'oxds:currentVersion') + # Access state info (resp, data) = self.doHTTP_GET( resource="states/TestSubmission", expect_status=200, expect_reason="OK", expect_type="application/json") state = data['state'] - parts = data['parts'] - self.assertEqual(len(state.keys()), 11, "States") - self.assertEqual(state['item_id'], "TestSubmission", "Submission item identifier") - self.assertEqual(len(state['versions']), 2, "Two versions") - self.assertEqual(state['versions'][0], '0', "Version 0") - self.assertEqual(state['versions'][1], '1', "Version 1") - self.assertEqual(state['currentversion'], '1', "Current version == 1") - self.assertEqual(state['rdffileformat'], 'xml', "RDF file type") - self.assertEqual(state['rdffilename'], 'manifest.rdf', "RDF file name") - self.assertEqual(state['files']['0'], ['manifest.rdf'], "List should contain just manifest.rdf") - self.assertEqual(len(state['files']['1']), 2, "List should contain manifest.rdf and testdir.zip") - self.assertEqual(len(state['metadata_files']['0']), 0, "metadata_files of version 0") - self.assertEqual(len(state['metadata_files']['1']), 0, "metadata_files of version 1") - self.assertEqual(len(state['subdir']['0']), 0, "Subdirectory count for version 0") - self.assertEqual(len(state['subdir']['1']), 0, "Subdirectory count for version 1") - self.assertEqual(state['metadata']['createdby'], RDFDatabankConfig.endpointuser, "Created by") self.assertEqual(state['metadata']['embargoed'], True, "Embargoed?") - self.assertEqual(len(parts.keys()), 4, "Parts") - self.assertEqual(len(parts['4=TestSubmission'].keys()), 13, "File stats for 4=TestSubmission") - self.assertEqual(len(parts['manifest.rdf'].keys()), 13, "File stats for manifest.rdf") - self.assertEqual(len(parts['testdir.zip'].keys()), 13, "File stats for testdir.zip") - - def testFileDelete(self): - """Delete file in dataset - DELETE /silo_name/datasets/dataset_name/file_name""" - # Create a new dataset, check response - self.createSubmissionDataset() - # Upload zip file, check response - zipdata = self.uploadSubmissionZipfile() - # Access and check list of contents + self.assertEqual(state['metadata']['embargoed_until'], '', "Embargoed?") + #--------------------------------------------------------------- + # Delete dataset, check response + resp = self.doHTTP_DELETE( + resource="datasets/TestSubmission", + expect_status=200, expect_reason="OK") + # Access dataset, test response indicating non-existent + (resp, respdata) = self.doHTTP_GET( + resource="datasets/TestSubmission", + expect_status=404, expect_reason="Not Found") + # Create a new dataset, check response. embargoed=None, embargo_until=True. + self.createSubmissionDataset(embargoed_until=True) + # Access dataset, check response (resp, rdfdata) = self.doHTTP_GET( resource="datasets/TestSubmission", expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") rdfgraph = Graph() rdfstream = StringIO(rdfdata) - rdfgraph.parse(rdfstream) - subj = URIRef(self.getRequestUri("datasets/TestSubmission")) + rdfgraph.parse(rdfstream) + self.assertEqual(len(rdfgraph),10,'Graph length %i' %len(rdfgraph)) oxds = "http://vocab.ox.ac.uk/dataset/schema#" - self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) - self.failUnless((subj,URIRef(oxds+"currentVersion"),"1") in rdfgraph, 'oxds:currentVersion') - # Access and check zip file content and version - (resp, zipfile) = self.doHTTP_GET( - resource="datasets/TestSubmission/testdir.zip", - expect_status=200, expect_reason="OK", expect_type="application/zip") - self.assertEqual(zipdata, zipfile, "Difference between local and remote zipfile!") - # Delete file, check response + subj = URIRef(self.getRequestUri("datasets/TestSubmission")) + stype = URIRef(oxds+"DataSet") + self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') + self.assertTrue((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"currentVersion"),'0') in rdfgraph, 'oxds:currentVersion') + # Access state info + (resp, data) = self.doHTTP_GET( + resource="states/TestSubmission", + expect_status=200, expect_reason="OK", expect_type="application/json") + state = data['state'] + d = (datetime.now() + relativedelta(years=+70)).isoformat() + d = d.split('T')[0] + self.assertEqual(state['metadata']['embargoed'], True, "Embargoed?") + self.assertTrue(d in state['metadata']['embargoed_until'], "embargoed_until %s?"%d) + #--------------------------------------------------------------- + # Delete dataset, check response resp = self.doHTTP_DELETE( - resource="datasets/TestSubmission/testdir.zip", + resource="datasets/TestSubmission", expect_status=200, expect_reason="OK") - # Access and check zip file does not exist - (resp, zipfile) = self.doHTTP_GET( - resource="datasets/TestSubmission/testdir.zip", + # Access dataset, test response indicating non-existent + (resp, respdata) = self.doHTTP_GET( + resource="datasets/TestSubmission", expect_status=404, expect_reason="Not Found") - # Access and check list of contents + # Create a new dataset, check response. embargoed=None, embargo_until=2012-08-12 + d = '2012-08-12' + self.createSubmissionDataset(embargoed_until=d) + # Access dataset, check response (resp, rdfdata) = self.doHTTP_GET( resource="datasets/TestSubmission", expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - subj = URIRef(self.getRequestUri("datasets/TestSubmission")) - dcterms = "http://purl.org/dc/terms/" - ore = "http://www.openarchives.org/ore/terms/" + self.assertEqual(len(rdfgraph),10,'Graph length %i' %len(rdfgraph)) oxds = "http://vocab.ox.ac.uk/dataset/schema#" + subj = URIRef(self.getRequestUri("datasets/TestSubmission")) stype = URIRef(oxds+"DataSet") - self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) - self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') - self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') - self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') - self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') - self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') - self.failUnless((subj,URIRef(oxds+"currentVersion"),'2') in rdfgraph, 'oxds:currentVersion') - self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') - #Access state information and check + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') + self.assertTrue((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"currentVersion"),'0') in rdfgraph, 'oxds:currentVersion') + # Access state info (resp, data) = self.doHTTP_GET( resource="states/TestSubmission", expect_status=200, expect_reason="OK", expect_type="application/json") state = data['state'] - parts = data['parts'] - self.assertEqual(len(state.keys()), 11, "States") - self.assertEqual(state['item_id'], "TestSubmission", "Submission item identifier") - self.assertEqual(len(state['versions']), 3, "Three versions") - self.assertEqual(state['versions'][0], '0', "Version 0") - self.assertEqual(state['versions'][1], '1', "Version 1") - self.assertEqual(state['versions'][2], '2', "Version 2") - self.assertEqual(state['currentversion'], '2', "Current version == 2") - self.assertEqual(state['rdffileformat'], 'xml', "RDF file type") - self.assertEqual(state['rdffilename'], 'manifest.rdf', "RDF file name") - self.assertEqual(len(state['files']['0']), 1, "List should contain just manifest.rdf") - self.assertEqual(len(state['files']['1']), 2, "List should contain manifest.rdf and testdir.zip") - self.assertEqual(len(state['files']['2']), 1, "List should contain just manifest.rdf") - self.assertEqual(len(state['metadata_files']['0']), 0, "metadata_files of version 0") - self.assertEqual(len(state['metadata_files']['1']), 0, "metadata_files of version 1") - self.assertEqual(len(state['metadata_files']['2']), 0, "metadata_files of version 2") - self.assertEqual(len(state['subdir']['0']), 0, "Subdirectory count for version 0") - self.assertEqual(len(state['subdir']['1']), 0, "Subdirectory count for version 1") - self.assertEqual(len(state['subdir']['2']), 0, "Subdirectory count for version 2") - self.assertEqual(state['metadata']['createdby'], RDFDatabankConfig.endpointuser, "Created by") self.assertEqual(state['metadata']['embargoed'], True, "Embargoed?") - self.assertEqual(len(parts.keys()), 3, "Parts") - self.assertEqual(len(parts['4=TestSubmission'].keys()), 13, "File stats for 4=TestSubmission") - self.assertEqual(len(parts['manifest.rdf'].keys()), 13, "File stats for manifest.rdf") - - def testFileUpdate(self): - """Update file in dataset - POST file to /silo_name/datasets/dataset_name (x 2)""" - # Create a new dataset, check response - self.createSubmissionDataset() - # Upload zip file, check response (uploads the file testdir.zip) - zipdata = self.uploadSubmissionZipfile() - # Access and check list of contents + self.assertTrue(d in state['metadata']['embargoed_until'], "embargoed_until %s?"%d) + #--------------------------------------------------------------- + # Delete dataset, check response + resp = self.doHTTP_DELETE( + resource="datasets/TestSubmission", + expect_status=200, expect_reason="OK") + # Access dataset, test response indicating non-existent + (resp, respdata) = self.doHTTP_GET( + resource="datasets/TestSubmission", + expect_status=404, expect_reason="Not Found") + # Create a new dataset, check response. embargoed=True, embargo_until=None. + self.createSubmissionDataset(embargoed=True) + # Access dataset, check response (resp, rdfdata) = self.doHTTP_GET( resource="datasets/TestSubmission", expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") rdfgraph = Graph() rdfstream = StringIO(rdfdata) - rdfgraph.parse(rdfstream) - subj = URIRef(self.getRequestUri("datasets/TestSubmission")) + rdfgraph.parse(rdfstream) + self.assertEqual(len(rdfgraph),9,'Graph length %i' %len(rdfgraph)) oxds = "http://vocab.ox.ac.uk/dataset/schema#" - self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) - self.failUnless((subj,URIRef(oxds+"currentVersion"),'1') in rdfgraph, 'oxds:currentVersion') - # Access and check zip file content and version - (resp, zipfile) = self.doHTTP_GET( - resource="datasets/TestSubmission/testdir.zip", - expect_status=200, expect_reason="OK", expect_type="application/zip") - self.assertEqual(zipdata, zipfile, "Difference between local and remote zipfile!") - # Upload zip file again, check response - zipdata = self.updateSubmissionZipfile(file_to_upload="testdir2.zip", filename="testdir.zip") - # Access and check list of contents + subj = URIRef(self.getRequestUri("datasets/TestSubmission")) + stype = URIRef(oxds+"DataSet") + self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') + self.assertFalse((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"currentVersion"),'0') in rdfgraph, 'oxds:currentVersion') + # Access state info + (resp, data) = self.doHTTP_GET( + resource="states/TestSubmission", + expect_status=200, expect_reason="OK", expect_type="application/json") + state = data['state'] + self.assertEqual(state['metadata']['embargoed'], True, "Embargoed?") + self.assertEqual(state['metadata']['embargoed_until'], '', "Embargoed?") + #--------------------------------------------------------------- + # Delete dataset, check response + resp = self.doHTTP_DELETE( + resource="datasets/TestSubmission", + expect_status=200, expect_reason="OK") + # Access dataset, test response indicating non-existent + (resp, respdata) = self.doHTTP_GET( + resource="datasets/TestSubmission", + expect_status=404, expect_reason="Not Found") + # Create a new dataset, check response. embargoed=True, embargo_until=True + self.createSubmissionDataset(embargoed=True, embargoed_until=True) + # Access dataset, check response (resp, rdfdata) = self.doHTTP_GET( resource="datasets/TestSubmission", expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - subj = URIRef(self.getRequestUri("datasets/TestSubmission")) - base = self.getRequestUri("datasets/TestSubmission/") - dcterms = "http://purl.org/dc/terms/" - ore = "http://www.openarchives.org/ore/terms/" + self.assertEqual(len(rdfgraph),10,'Graph length %i' %len(rdfgraph)) oxds = "http://vocab.ox.ac.uk/dataset/schema#" + dcterms = "http://purl.org/dc/terms/" + subj = URIRef(self.getRequestUri("datasets/TestSubmission")) stype = URIRef(oxds+"DataSet") - self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) - self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') - self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"testdir.zip")) in rdfgraph) - self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') - self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') - self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') - self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') - self.failUnless((subj,URIRef(oxds+"currentVersion"),'2') in rdfgraph, 'oxds:currentVersion') - self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') - # Access and check zip file content - (resp, zipfile) = self.doHTTP_GET( - resource="datasets/TestSubmission/testdir.zip", - expect_status=200, expect_reason="OK", expect_type="application/zip") - self.assertEqual(zipdata, zipfile, "Difference between local and remote zipfile!") - #Access state information and check + self.failUnless((subj,URIRef(oxds+"currentVersion"),'0') in rdfgraph, 'oxds:currentVersion') + # Access state info (resp, data) = self.doHTTP_GET( resource="states/TestSubmission", expect_status=200, expect_reason="OK", expect_type="application/json") state = data['state'] - parts = data['parts'] - self.assertEqual(len(state.keys()), 11, "States") - self.assertEqual(state['item_id'], "TestSubmission", "Submission item identifier") - self.assertEqual(len(state['versions']), 3, "Three versions") - self.assertEqual(state['versions'][0], '0', "Version 0") - self.assertEqual(state['versions'][1], '1', "Version 1") - self.assertEqual(state['versions'][2], '2', "Version 2") - self.assertEqual(state['currentversion'], '2', "Current version == 2") - self.assertEqual(state['rdffileformat'], 'xml', "RDF file type") - self.assertEqual(state['rdffilename'], 'manifest.rdf', "RDF file name") - self.assertEqual(len(state['files']['0']), 1, "List should contain just manifest.rdf") - self.assertEqual(len(state['files']['1']), 2, "List should contain manifest.rdf and testdir.zip") - self.assertEqual(len(state['files']['2']), 2, "List should contain manifest.rdf and testdir.zip") - self.assertEqual(len(state['metadata_files']['0']), 0, "metadata_files of version 0") - self.assertEqual(len(state['metadata_files']['1']), 0, "metadata_files of version 1") - self.assertEqual(len(state['metadata_files']['2']), 0, "metadata_files of version 2") - self.assertEqual(len(state['subdir']['0']), 0, "Subdirectory count for version 0") - self.assertEqual(len(state['subdir']['1']), 0, "Subdirectory count for version 1") - self.assertEqual(len(state['subdir']['2']), 0, "Subdirectory count for version 2") - self.assertEqual(state['metadata']['createdby'], RDFDatabankConfig.endpointuser, "Created by") + d = (datetime.now() + relativedelta(years=+70)).isoformat() + d = d.split('T')[0] self.assertEqual(state['metadata']['embargoed'], True, "Embargoed?") - self.assertEqual(len(parts.keys()), 4, "Parts") - self.assertEqual(len(parts['4=TestSubmission'].keys()), 13, "File stats for 4=TestSubmission") - self.assertEqual(len(parts['manifest.rdf'].keys()), 13, "File stats for manifest.rdf") - self.assertEqual(len(parts['testdir.zip'].keys()), 13, "File stats for testdir.zip") - - def testGetDatasetByVersion(self): - """Upload files to a dataset - POST file to /silo_name/datasets/dataset_name. Access each of the versions and the files in that version""" - #Definitions - subj = URIRef(self.getRequestUri("datasets/TestSubmission")) - base = self.getRequestUri("datasets/TestSubmission/") - dcterms = "http://purl.org/dc/terms/" - ore = "http://www.openarchives.org/ore/terms/" - oxds = "http://vocab.ox.ac.uk/dataset/schema#" - stype = URIRef(oxds+"DataSet") - #---------Version 0 - # Create a new dataset, check response - self.createSubmissionDataset() - # Access and check list of contents + self.assertTrue(d in state['metadata']['embargoed_until'], "embargoed_until %s?"%d) + #--------------------------------------------------------------- + # Delete dataset, check response + resp = self.doHTTP_DELETE( + resource="datasets/TestSubmission", + expect_status=200, expect_reason="OK") + # Access dataset, test response indicating non-existent + (resp, respdata) = self.doHTTP_GET( + resource="datasets/TestSubmission", + expect_status=404, expect_reason="Not Found") + # Create a new dataset, check response. embargoed=True, embargo_until=09-08-2012 + d = '09-08-2012' + self.createSubmissionDataset(embargoed=True, embargoed_until=d) + # Access dataset, check response (resp, rdfdata) = self.doHTTP_GET( resource="datasets/TestSubmission", expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") @@ -726,79 +668,135 @@ def testGetDatasetByVersion(self): rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) self.assertEqual(len(rdfgraph),10,'Graph length %i' %len(rdfgraph)) - #Access state information and check + oxds = "http://vocab.ox.ac.uk/dataset/schema#" + dcterms = "http://purl.org/dc/terms/" + subj = URIRef(self.getRequestUri("datasets/TestSubmission")) + stype = URIRef(oxds+"DataSet") + self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') + self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"currentVersion"),'0') in rdfgraph, 'oxds:currentVersion') + # Access state info (resp, data) = self.doHTTP_GET( resource="states/TestSubmission", expect_status=200, expect_reason="OK", expect_type="application/json") state = data['state'] - parts = data['parts'] - self.assertEqual(len(state.keys()), 11, "States") - self.assertEqual(len(parts.keys()), 3, "Parts") - #---------Version 1 - # Upload zip file, check response - zipdata = self.uploadSubmissionZipfile() - # Access and check list of contents + self.assertEqual(state['metadata']['embargoed'], True, "Embargoed?") + self.assertTrue('2012-09-08' in state['metadata']['embargoed_until'], "embargoed_until 2012-09-08?") + #--------------------------------------------------------------- + # Delete dataset, check response + resp = self.doHTTP_DELETE( + resource="datasets/TestSubmission", + expect_status=200, expect_reason="OK") + # Access dataset, test response indicating non-existent + (resp, respdata) = self.doHTTP_GET( + resource="datasets/TestSubmission", + expect_status=404, expect_reason="Not Found") + # Create a new dataset, check response. embargoed = False. + self.createSubmissionDataset(embargoed=False) + # Access dataset, check response (resp, rdfdata) = self.doHTTP_GET( resource="datasets/TestSubmission", expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) - # Access and check zip file content - (resp, zipfile) = self.doHTTP_GET( - resource="datasets/TestSubmission/testdir.zip", - expect_status=200, expect_reason="OK", expect_type="application/zip") - self.assertEqual(zipdata, zipfile, "Difference between local and remote zipfile!") - #Access state information and check + self.assertEqual(len(rdfgraph),9,'Graph length %i' %len(rdfgraph)) + oxds = "http://vocab.ox.ac.uk/dataset/schema#" + dcterms = "http://purl.org/dc/terms/" + subj = URIRef(self.getRequestUri("datasets/TestSubmission")) + stype = URIRef(oxds+"DataSet") + self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'False') in rdfgraph, 'oxds:isEmbargoed') + self.assertFalse((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"currentVersion"),'0') in rdfgraph, 'oxds:currentVersion') + # Access state info (resp, data) = self.doHTTP_GET( resource="states/TestSubmission", expect_status=200, expect_reason="OK", expect_type="application/json") state = data['state'] - parts = data['parts'] - self.assertEqual(len(state.keys()), 11, "States") - self.assertEqual(len(parts.keys()), 4, "Parts") - # Access and check list of contents of version 0 + self.assertEqual(state['metadata']['embargoed'], False, "Embargoed?") + self.assertEqual(state['metadata']['embargoed_until'], '', "Embargoed?") + #--------------------------------------------------------------- + # Delete dataset, check response + resp = self.doHTTP_DELETE( + resource="datasets/TestSubmission", + expect_status=200, expect_reason="OK") + # Access dataset, test response indicating non-existent + (resp, respdata) = self.doHTTP_GET( + resource="datasets/TestSubmission", + expect_status=404, expect_reason="Not Found") + # Create a new dataset, check response. embargoed = False, embargoed_until = True + self.createSubmissionDataset(embargoed=False, embargoed_until=True) + # Access dataset, check response (resp, rdfdata) = self.doHTTP_GET( - resource="datasets/TestSubmission/version0", + resource="datasets/TestSubmission", expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),10,'Graph length %i' %len(rdfgraph)) - #---------Version 2 - # Upload zip file, check response - zipdata2 = self.uploadSubmissionZipfile(file_to_upload="testdir2.zip") - # Access and check list of contents + self.assertEqual(len(rdfgraph),9,'Graph length %i' %len(rdfgraph)) + oxds = "http://vocab.ox.ac.uk/dataset/schema#" + dcterms = "http://purl.org/dc/terms/" + subj = URIRef(self.getRequestUri("datasets/TestSubmission")) + stype = URIRef(oxds+"DataSet") + self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'False') in rdfgraph, 'oxds:isEmbargoed') + self.assertFalse((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"currentVersion"),'0') in rdfgraph, 'oxds:currentVersion') + # Access state info + (resp, data) = self.doHTTP_GET( + resource="states/TestSubmission", + expect_status=200, expect_reason="OK", expect_type="application/json") + state = data['state'] + self.assertEqual(state['metadata']['embargoed'], False, "Embargoed?") + self.assertEqual(state['metadata']['embargoed_until'], '', "Embargoed?") + #--------------------------------------------------------------- + # Delete dataset, check response + resp = self.doHTTP_DELETE( + resource="datasets/TestSubmission", + expect_status=200, expect_reason="OK") + # Access dataset, test response indicating non-existent + (resp, respdata) = self.doHTTP_GET( + resource="datasets/TestSubmission", + expect_status=404, expect_reason="Not Found") + # Create a new dataset, check response. embargoed = False, embargoed_until = 12 sep 2013 + d = '12 Sep 2013' + self.createSubmissionDataset(embargoed=False, embargoed_until=d) + # Access dataset, check response (resp, rdfdata) = self.doHTTP_GET( resource="datasets/TestSubmission", expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),13,'Graph length %i' %len(rdfgraph)) - # Access and check zip file content - (resp, zipfile) = self.doHTTP_GET( - resource="datasets/TestSubmission/testdir.zip", - expect_status=200, expect_reason="OK", expect_type="application/zip") - self.assertEqual(zipdata, zipfile, "Difference between local and remote zipfile - testdir.zip!") - (resp, zipfile2) = self.doHTTP_GET( - resource="datasets/TestSubmission/testdir2.zip", - expect_status=200, expect_reason="OK", expect_type="application/zip") - self.assertEqual(zipdata2, zipfile2, "Difference between local and remote zipfile - testdir2.zip!") - #Access state information and check + self.assertEqual(len(rdfgraph),9,'Graph length %i' %len(rdfgraph)) + oxds = "http://vocab.ox.ac.uk/dataset/schema#" + dcterms = "http://purl.org/dc/terms/" + subj = URIRef(self.getRequestUri("datasets/TestSubmission")) + stype = URIRef(oxds+"DataSet") + self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'False') in rdfgraph, 'oxds:isEmbargoed') + self.assertFalse((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"currentVersion"),'0') in rdfgraph, 'oxds:currentVersion') + # Access state info (resp, data) = self.doHTTP_GET( resource="states/TestSubmission", expect_status=200, expect_reason="OK", expect_type="application/json") state = data['state'] - parts = data['parts'] - self.assertEqual(len(state.keys()), 11, "States") - self.assertEqual(len(parts.keys()), 5, "Parts") - #---------Version 3 - # Delete file, check response - resp = self.doHTTP_DELETE( - resource="datasets/TestSubmission/testdir.zip", - expect_status=200, expect_reason="OK") + self.assertEqual(state['metadata']['embargoed'], False, "Embargoed?") + self.assertEqual(state['metadata']['embargoed_until'], '', "Embargoed?") + + def testFileUpload(self): + """Upload file to dataset - POST file to /silo_name/datasets/dataset_name""" + # Create a new dataset, check response + self.createSubmissionDataset() + #Access state information + (resp, respdata) = self.doHTTP_GET( + resource="states/TestSubmission", + expect_status=200, expect_reason="OK", expect_type="application/json") + # Upload zip file, check response + zipdata = self.uploadSubmissionZipfile() # Access and check list of contents (resp, rdfdata) = self.doHTTP_GET( resource="datasets/TestSubmission", @@ -806,15 +804,28 @@ def testGetDatasetByVersion(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) + subj = URIRef(self.getRequestUri("datasets/TestSubmission")) + base = self.getRequestUri("datasets/TestSubmission/") + dcterms = "http://purl.org/dc/terms/" + ore = "http://www.openarchives.org/ore/terms/" + oxds = "http://vocab.ox.ac.uk/dataset/schema#" + stype = URIRef(oxds+"DataSet") + self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) + self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) + self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') + self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"testdir.zip")) in rdfgraph) + self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') + self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') + self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') + self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') + self.failUnless((subj,URIRef(oxds+"currentVersion"),'1') in rdfgraph, 'oxds:currentVersion') + self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') # Access and check zip file content (resp, zipfile) = self.doHTTP_GET( resource="datasets/TestSubmission/testdir.zip", - expect_status=404, expect_reason="Not Found") - (resp, zipfile2) = self.doHTTP_GET( - resource="datasets/TestSubmission/testdir2.zip", expect_status=200, expect_reason="OK", expect_type="application/zip") - self.assertEqual(zipdata2, zipfile2, "Difference between local and remote zipfile - testdir2.zip!") + self.assertEqual(zipdata, zipfile, "Difference between local and remote zipfile!") #Access state information and check (resp, data) = self.doHTTP_GET( resource="states/TestSubmission", @@ -822,43 +833,68 @@ def testGetDatasetByVersion(self): state = data['state'] parts = data['parts'] self.assertEqual(len(state.keys()), 11, "States") + self.assertEqual(state['item_id'], "TestSubmission", "Submission item identifier") + self.assertEqual(len(state['versions']), 2, "Two versions") + self.assertEqual(state['versions'][0], '0', "Version 0") + self.assertEqual(state['versions'][1], '1', "Version 1") + self.assertEqual(state['currentversion'], '1', "Current version == 1") + self.assertEqual(state['rdffileformat'], 'xml', "RDF file type") + self.assertEqual(state['rdffilename'], 'manifest.rdf', "RDF file name") + self.assertEqual(state['files']['0'], ['manifest.rdf'], "List should contain just manifest.rdf") + self.assertEqual(len(state['files']['1']), 2, "List should contain manifest.rdf and testdir.zip") + self.assertEqual(len(state['metadata_files']['0']), 0, "metadata_files of version 0") + self.assertEqual(len(state['metadata_files']['1']), 0, "metadata_files of version 1") + self.assertEqual(len(state['subdir']['0']), 0, "Subdirectory count for version 0") + self.assertEqual(len(state['subdir']['1']), 0, "Subdirectory count for version 1") + self.assertEqual(state['metadata']['createdby'], RDFDatabankConfig.endpointuser, "Created by") + self.assertEqual(state['metadata']['embargoed'], True, "Embargoed?") self.assertEqual(len(parts.keys()), 4, "Parts") - #---------Version 4 - # Update zip file, check response - zipdata3 = self.updateSubmissionZipfile(file_to_upload="testrdf4.zip", filename="testdir2.zip") + self.assertEqual(len(parts['4=TestSubmission'].keys()), 13, "File stats for 4=TestSubmission") + self.assertEqual(len(parts['manifest.rdf'].keys()), 13, "File stats for manifest.rdf") + self.assertEqual(len(parts['testdir.zip'].keys()), 13, "File stats for testdir.zip") + + def testFileDelete(self): + """Delete file in dataset - DELETE /silo_name/datasets/dataset_name/file_name""" + # Create a new dataset, check response + self.createSubmissionDataset() + # Upload zip file, check response + zipdata = self.uploadSubmissionZipfile() # Access and check list of contents (resp, rdfdata) = self.doHTTP_GET( resource="datasets/TestSubmission", expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") rdfgraph = Graph() rdfstream = StringIO(rdfdata) - rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) - # Access and check zip file content + rdfgraph.parse(rdfstream) + subj = URIRef(self.getRequestUri("datasets/TestSubmission")) + oxds = "http://vocab.ox.ac.uk/dataset/schema#" + self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) + self.failUnless((subj,URIRef(oxds+"currentVersion"),"1") in rdfgraph, 'oxds:currentVersion') + # Access and check zip file content and version (resp, zipfile) = self.doHTTP_GET( resource="datasets/TestSubmission/testdir.zip", - expect_status=404, expect_reason="Not Found") - (resp, zipfile2) = self.doHTTP_GET( - resource="datasets/TestSubmission/testdir2.zip", expect_status=200, expect_reason="OK", expect_type="application/zip") - self.assertEqual(zipdata3, zipfile2, "Difference between local and remote zipfile - testdir2.zip!") - #Access state information and check - (resp, data) = self.doHTTP_GET( - resource="states/TestSubmission", - expect_status=200, expect_reason="OK", expect_type="application/json") - state = data['state'] - parts = data['parts'] - self.assertEqual(len(state.keys()), 11, "States") - self.assertEqual(len(parts.keys()), 4, "Parts") - #=========Access each of the versions - #---------Version 0 - # Access and check list of contents of version 0 + self.assertEqual(zipdata, zipfile, "Difference between local and remote zipfile!") + # Delete file, check response + resp = self.doHTTP_DELETE( + resource="datasets/TestSubmission/testdir.zip", + expect_status=200, expect_reason="OK") + # Access and check zip file does not exist + (resp, zipfile) = self.doHTTP_GET( + resource="datasets/TestSubmission/testdir.zip", + expect_status=404, expect_reason="Not Found") + # Access and check list of contents (resp, rdfdata) = self.doHTTP_GET( - resource="datasets/TestSubmission/version0", + resource="datasets/TestSubmission", expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) + subj = URIRef(self.getRequestUri("datasets/TestSubmission")) + dcterms = "http://purl.org/dc/terms/" + ore = "http://www.openarchives.org/ore/terms/" + oxds = "http://vocab.ox.ac.uk/dataset/schema#" + stype = URIRef(oxds+"DataSet") self.assertEqual(len(rdfgraph),10,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') @@ -867,27 +903,76 @@ def testGetDatasetByVersion(self): self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') - self.failUnless((subj,URIRef(oxds+"currentVersion"),'0') in rdfgraph, 'oxds:currentVersion') + self.failUnless((subj,URIRef(oxds+"currentVersion"),'2') in rdfgraph, 'oxds:currentVersion') + self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') #Access state information and check (resp, data) = self.doHTTP_GET( - resource="states/TestSubmission/version0", + resource="states/TestSubmission", expect_status=200, expect_reason="OK", expect_type="application/json") state = data['state'] parts = data['parts'] self.assertEqual(len(state.keys()), 11, "States") - self.assertEqual(len(parts.keys()), 3, "Parts") - self.assertEqual(len(parts['4=TestSubmission'].keys()), 13, "File stats for 4=TestSubmission") - self.assertEqual(len(parts['manifest.rdf'].keys()), 13, "File stats for manifest.rdf") - #---------Version 1 - # Access and check list of contents of version 1 - (resp, rdfdata) = self.doHTTP_GET( - resource="datasets/TestSubmission/version1", - expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") + self.assertEqual(state['item_id'], "TestSubmission", "Submission item identifier") + self.assertEqual(len(state['versions']), 3, "Three versions") + self.assertEqual(state['versions'][0], '0', "Version 0") + self.assertEqual(state['versions'][1], '1', "Version 1") + self.assertEqual(state['versions'][2], '2', "Version 2") + self.assertEqual(state['currentversion'], '2', "Current version == 2") + self.assertEqual(state['rdffileformat'], 'xml', "RDF file type") + self.assertEqual(state['rdffilename'], 'manifest.rdf', "RDF file name") + self.assertEqual(len(state['files']['0']), 1, "List should contain just manifest.rdf") + self.assertEqual(len(state['files']['1']), 2, "List should contain manifest.rdf and testdir.zip") + self.assertEqual(len(state['files']['2']), 1, "List should contain just manifest.rdf") + self.assertEqual(len(state['metadata_files']['0']), 0, "metadata_files of version 0") + self.assertEqual(len(state['metadata_files']['1']), 0, "metadata_files of version 1") + self.assertEqual(len(state['metadata_files']['2']), 0, "metadata_files of version 2") + self.assertEqual(len(state['subdir']['0']), 0, "Subdirectory count for version 0") + self.assertEqual(len(state['subdir']['1']), 0, "Subdirectory count for version 1") + self.assertEqual(len(state['subdir']['2']), 0, "Subdirectory count for version 2") + self.assertEqual(state['metadata']['createdby'], RDFDatabankConfig.endpointuser, "Created by") + self.assertEqual(state['metadata']['embargoed'], True, "Embargoed?") + self.assertEqual(len(parts.keys()), 3, "Parts") + self.assertEqual(len(parts['4=TestSubmission'].keys()), 13, "File stats for 4=TestSubmission") + self.assertEqual(len(parts['manifest.rdf'].keys()), 13, "File stats for manifest.rdf") + + def testFileUpdate(self): + """Update file in dataset - POST file to /silo_name/datasets/dataset_name (x 2)""" + # Create a new dataset, check response + self.createSubmissionDataset() + # Upload zip file, check response (uploads the file testdir.zip) + zipdata = self.uploadSubmissionZipfile() + # Access and check list of contents + (resp, rdfdata) = self.doHTTP_GET( + resource="datasets/TestSubmission", + expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") + rdfgraph = Graph() + rdfstream = StringIO(rdfdata) + rdfgraph.parse(rdfstream) + subj = URIRef(self.getRequestUri("datasets/TestSubmission")) + oxds = "http://vocab.ox.ac.uk/dataset/schema#" + self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) + self.failUnless((subj,URIRef(oxds+"currentVersion"),'1') in rdfgraph, 'oxds:currentVersion') + # Access and check zip file content and version + (resp, zipfile) = self.doHTTP_GET( + resource="datasets/TestSubmission/testdir.zip", + expect_status=200, expect_reason="OK", expect_type="application/zip") + self.assertEqual(zipdata, zipfile, "Difference between local and remote zipfile!") + # Upload zip file again, check response + zipdata = self.updateSubmissionZipfile(file_to_upload="testdir2.zip", filename="testdir.zip") + # Access and check list of contents + (resp, rdfdata) = self.doHTTP_GET( + resource="datasets/TestSubmission", + expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) + subj = URIRef(self.getRequestUri("datasets/TestSubmission")) + base = self.getRequestUri("datasets/TestSubmission/") + dcterms = "http://purl.org/dc/terms/" + ore = "http://www.openarchives.org/ore/terms/" + oxds = "http://vocab.ox.ac.uk/dataset/schema#" + stype = URIRef(oxds+"DataSet") + self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"testdir.zip")) in rdfgraph) @@ -896,149 +981,372 @@ def testGetDatasetByVersion(self): self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') - self.failUnless((subj,URIRef(oxds+"currentVersion"),'1') in rdfgraph, 'oxds:currentVersion') - self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') + self.failUnless((subj,URIRef(oxds+"currentVersion"),'2') in rdfgraph, 'oxds:currentVersion') + self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') # Access and check zip file content (resp, zipfile) = self.doHTTP_GET( - resource="datasets/TestSubmission/testdir.zip/version1", + resource="datasets/TestSubmission/testdir.zip", expect_status=200, expect_reason="OK", expect_type="application/zip") - self.assertEqual(zipdata, zipfile, "Difference between local and remote zipfile - Version 1!") + self.assertEqual(zipdata, zipfile, "Difference between local and remote zipfile!") #Access state information and check (resp, data) = self.doHTTP_GET( - resource="states/TestSubmission/version1", + resource="states/TestSubmission", expect_status=200, expect_reason="OK", expect_type="application/json") state = data['state'] parts = data['parts'] self.assertEqual(len(state.keys()), 11, "States") + self.assertEqual(state['item_id'], "TestSubmission", "Submission item identifier") + self.assertEqual(len(state['versions']), 3, "Three versions") + self.assertEqual(state['versions'][0], '0', "Version 0") + self.assertEqual(state['versions'][1], '1', "Version 1") + self.assertEqual(state['versions'][2], '2', "Version 2") + self.assertEqual(state['currentversion'], '2', "Current version == 2") + self.assertEqual(state['rdffileformat'], 'xml', "RDF file type") + self.assertEqual(state['rdffilename'], 'manifest.rdf', "RDF file name") + self.assertEqual(len(state['files']['0']), 1, "List should contain just manifest.rdf") + self.assertEqual(len(state['files']['1']), 2, "List should contain manifest.rdf and testdir.zip") + self.assertEqual(len(state['files']['2']), 2, "List should contain manifest.rdf and testdir.zip") + self.assertEqual(len(state['metadata_files']['0']), 0, "metadata_files of version 0") + self.assertEqual(len(state['metadata_files']['1']), 0, "metadata_files of version 1") + self.assertEqual(len(state['metadata_files']['2']), 0, "metadata_files of version 2") + self.assertEqual(len(state['subdir']['0']), 0, "Subdirectory count for version 0") + self.assertEqual(len(state['subdir']['1']), 0, "Subdirectory count for version 1") + self.assertEqual(len(state['subdir']['2']), 0, "Subdirectory count for version 2") + self.assertEqual(state['metadata']['createdby'], RDFDatabankConfig.endpointuser, "Created by") + self.assertEqual(state['metadata']['embargoed'], True, "Embargoed?") self.assertEqual(len(parts.keys()), 4, "Parts") self.assertEqual(len(parts['4=TestSubmission'].keys()), 13, "File stats for 4=TestSubmission") self.assertEqual(len(parts['manifest.rdf'].keys()), 13, "File stats for manifest.rdf") self.assertEqual(len(parts['testdir.zip'].keys()), 13, "File stats for testdir.zip") + + def testGetDatasetByVersion(self): + """Upload files to a dataset - POST file to /silo_name/datasets/dataset_name. Access each of the versions and the files in that version""" + #Definitions + subj = URIRef(self.getRequestUri("datasets/TestSubmission")) + base = self.getRequestUri("datasets/TestSubmission/") + dcterms = "http://purl.org/dc/terms/" + ore = "http://www.openarchives.org/ore/terms/" + oxds = "http://vocab.ox.ac.uk/dataset/schema#" + stype = URIRef(oxds+"DataSet") + #---------Version 0 + # Create a new dataset, check response + self.createSubmissionDataset() + # Access and check list of contents + (resp, rdfdata) = self.doHTTP_GET( + resource="datasets/TestSubmission", + expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") + rdfgraph = Graph() + rdfstream = StringIO(rdfdata) + rdfgraph.parse(rdfstream) + self.assertEqual(len(rdfgraph),9,'Graph length %i' %len(rdfgraph)) + #Access state information and check + (resp, data) = self.doHTTP_GET( + resource="states/TestSubmission", + expect_status=200, expect_reason="OK", expect_type="application/json") + state = data['state'] + parts = data['parts'] + self.assertEqual(len(state.keys()), 11, "States") + self.assertEqual(len(parts.keys()), 3, "Parts") + #---------Version 1 + # Upload zip file, check response + zipdata = self.uploadSubmissionZipfile() + # Access and check list of contents + (resp, rdfdata) = self.doHTTP_GET( + resource="datasets/TestSubmission", + expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") + rdfgraph = Graph() + rdfstream = StringIO(rdfdata) + rdfgraph.parse(rdfstream) + self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) + # Access and check zip file content + (resp, zipfile) = self.doHTTP_GET( + resource="datasets/TestSubmission/testdir.zip", + expect_status=200, expect_reason="OK", expect_type="application/zip") + self.assertEqual(zipdata, zipfile, "Difference between local and remote zipfile!") + #Access state information and check + (resp, data) = self.doHTTP_GET( + resource="states/TestSubmission", + expect_status=200, expect_reason="OK", expect_type="application/json") + state = data['state'] + parts = data['parts'] + self.assertEqual(len(state.keys()), 11, "States") + self.assertEqual(len(parts.keys()), 4, "Parts") + # Access and check list of contents of version 0 + (resp, rdfdata) = self.doHTTP_GET( + resource="datasets/TestSubmission/version0", + expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") + rdfgraph = Graph() + rdfstream = StringIO(rdfdata) + rdfgraph.parse(rdfstream) + self.assertEqual(len(rdfgraph),9,'Graph length %i' %len(rdfgraph)) #---------Version 2 - # Access and check list of contents of version 2 + # Upload zip file, check response + zipdata2 = self.uploadSubmissionZipfile(file_to_upload="testdir2.zip") + # Access and check list of contents (resp, rdfdata) = self.doHTTP_GET( - resource="datasets/TestSubmission/version2", + resource="datasets/TestSubmission", expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),13,'Graph length %i' %len(rdfgraph)) - self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) - self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') - self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"testdir.zip")) in rdfgraph) - self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"testdir2.zip")) in rdfgraph) - self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') - self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') - self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') - self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') - self.failUnless((subj,URIRef(oxds+"currentVersion"),'2') in rdfgraph, 'oxds:currentVersion') - self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') + self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) # Access and check zip file content (resp, zipfile) = self.doHTTP_GET( - resource="datasets/TestSubmission/testdir.zip/version2", + resource="datasets/TestSubmission/testdir.zip", expect_status=200, expect_reason="OK", expect_type="application/zip") - self.assertEqual(zipdata, zipfile, "Difference between local and remote zipfile - Version 2!") + self.assertEqual(zipdata, zipfile, "Difference between local and remote zipfile - testdir.zip!") (resp, zipfile2) = self.doHTTP_GET( - resource="datasets/TestSubmission/testdir2.zip/version2", + resource="datasets/TestSubmission/testdir2.zip", expect_status=200, expect_reason="OK", expect_type="application/zip") - self.assertEqual(zipdata2, zipfile2, "Difference between local and remote zipfile - Version 2!") + self.assertEqual(zipdata2, zipfile2, "Difference between local and remote zipfile - testdir2.zip!") #Access state information and check (resp, data) = self.doHTTP_GET( - resource="states/TestSubmission/version2", + resource="states/TestSubmission", expect_status=200, expect_reason="OK", expect_type="application/json") state = data['state'] parts = data['parts'] self.assertEqual(len(state.keys()), 11, "States") self.assertEqual(len(parts.keys()), 5, "Parts") - self.assertEqual(len(parts['4=TestSubmission'].keys()), 13, "File stats for 4=TestSubmission") - self.assertEqual(len(parts['manifest.rdf'].keys()), 13, "File stats for manifest.rdf") - self.assertEqual(len(parts['testdir.zip'].keys()), 13, "File stats for testdir.zip") - self.assertEqual(len(parts['testdir2.zip'].keys()), 13, "File stats for testdir2.zip") #---------Version 3 - # Access and check list of contents of version 3 + # Delete file, check response + resp = self.doHTTP_DELETE( + resource="datasets/TestSubmission/testdir.zip", + expect_status=200, expect_reason="OK") + # Access and check list of contents (resp, rdfdata) = self.doHTTP_GET( - resource="datasets/TestSubmission/version3", + resource="datasets/TestSubmission", expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) - self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) - self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') - self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"testdir2.zip")) in rdfgraph) - self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') - self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') - self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') - self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') - self.failUnless((subj,URIRef(oxds+"currentVersion"),'3') in rdfgraph, 'oxds:currentVersion') - self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') + self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) # Access and check zip file content (resp, zipfile) = self.doHTTP_GET( - resource="datasets/TestSubmission/testdir2.zip/version3", - expect_status=200, expect_reason="OK", expect_type="application/zip") - self.assertEqual(zipdata2, zipfile, "Difference between local and remote zipfile - Version 3!") - (resp, zipfile) = self.doHTTP_GET( - resource="datasets/TestSubmission/testdir.zip/version3", + resource="datasets/TestSubmission/testdir.zip", expect_status=404, expect_reason="Not Found") + (resp, zipfile2) = self.doHTTP_GET( + resource="datasets/TestSubmission/testdir2.zip", + expect_status=200, expect_reason="OK", expect_type="application/zip") + self.assertEqual(zipdata2, zipfile2, "Difference between local and remote zipfile - testdir2.zip!") #Access state information and check (resp, data) = self.doHTTP_GET( - resource="states/TestSubmission/version3", + resource="states/TestSubmission", expect_status=200, expect_reason="OK", expect_type="application/json") state = data['state'] parts = data['parts'] self.assertEqual(len(state.keys()), 11, "States") self.assertEqual(len(parts.keys()), 4, "Parts") - self.assertEqual(len(parts['4=TestSubmission'].keys()), 13, "File stats for 4=TestSubmission") - self.assertEqual(len(parts['manifest.rdf'].keys()), 13, "File stats for manifest.rdf") - self.assertEqual(len(parts['testdir2.zip'].keys()), 13, "File stats for testdir2.zip") #---------Version 4 - # Access and check list of contents of version 4 + # Update zip file, check response + zipdata3 = self.updateSubmissionZipfile(file_to_upload="testrdf4.zip", filename="testdir2.zip") + # Access and check list of contents (resp, rdfdata) = self.doHTTP_GET( - resource="datasets/TestSubmission/version4", + resource="datasets/TestSubmission", expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) - self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) - self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') - self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"testdir2.zip")) in rdfgraph) - self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') - self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') - self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') - self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') - self.failUnless((subj,URIRef(oxds+"currentVersion"),'4') in rdfgraph, 'oxds:currentVersion') - self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') + self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) # Access and check zip file content (resp, zipfile) = self.doHTTP_GET( - resource="datasets/TestSubmission/testdir2.zip/version4", - expect_status=200, expect_reason="OK", expect_type="application/zip") - self.assertEqual(zipdata3, zipfile, "Difference between local and remote zipfile - Version 4!") - (resp, zipfile) = self.doHTTP_GET( - resource="datasets/TestSubmission/testdir.zip/version4", + resource="datasets/TestSubmission/testdir.zip", expect_status=404, expect_reason="Not Found") + (resp, zipfile2) = self.doHTTP_GET( + resource="datasets/TestSubmission/testdir2.zip", + expect_status=200, expect_reason="OK", expect_type="application/zip") + self.assertEqual(zipdata3, zipfile2, "Difference between local and remote zipfile - testdir2.zip!") #Access state information and check (resp, data) = self.doHTTP_GET( - resource="states/TestSubmission/version4", + resource="states/TestSubmission", expect_status=200, expect_reason="OK", expect_type="application/json") state = data['state'] parts = data['parts'] self.assertEqual(len(state.keys()), 11, "States") self.assertEqual(len(parts.keys()), 4, "Parts") - self.assertEqual(state['item_id'], "TestSubmission", "Submission item identifier") - self.assertEqual(len(state['versions']), 5, "Five versions") - self.assertEqual(state['versions'],['0', '1', '2', '3', '4'], "Versions") - self.assertEqual(state['currentversion'], '4', "Current version == 4") - self.assertEqual(state['rdffileformat'], 'xml', "RDF file type") - self.assertEqual(state['rdffilename'], 'manifest.rdf', "RDF file name") - self.assertEqual(state['files']['0'], ['manifest.rdf'], "List should contain just manifest.rdf") + #=========Access each of the versions + #---------Version 0 + # Access and check list of contents of version 0 + (resp, rdfdata) = self.doHTTP_GET( + resource="datasets/TestSubmission/version0", + expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") + rdfgraph = Graph() + rdfstream = StringIO(rdfdata) + rdfgraph.parse(rdfstream) + self.assertEqual(len(rdfgraph),9,'Graph length %i' %len(rdfgraph)) + self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) + self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') + self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') + self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') + self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') + self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') + self.failUnless((subj,URIRef(oxds+"currentVersion"),'0') in rdfgraph, 'oxds:currentVersion') + #Access state information and check + (resp, data) = self.doHTTP_GET( + resource="states/TestSubmission/version0", + expect_status=200, expect_reason="OK", expect_type="application/json") + state = data['state'] + parts = data['parts'] + self.assertEqual(len(state.keys()), 11, "States") + self.assertEqual(len(parts.keys()), 3, "Parts") + self.assertEqual(len(parts['4=TestSubmission'].keys()), 13, "File stats for 4=TestSubmission") + self.assertEqual(len(parts['manifest.rdf'].keys()), 13, "File stats for manifest.rdf") + #---------Version 1 + # Access and check list of contents of version 1 + (resp, rdfdata) = self.doHTTP_GET( + resource="datasets/TestSubmission/version1", + expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") + rdfgraph = Graph() + rdfstream = StringIO(rdfdata) + rdfgraph.parse(rdfstream) + self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) + self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) + self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') + self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"testdir.zip")) in rdfgraph) + self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') + self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') + self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') + self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') + self.failUnless((subj,URIRef(oxds+"currentVersion"),'1') in rdfgraph, 'oxds:currentVersion') + self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') + # Access and check zip file content + (resp, zipfile) = self.doHTTP_GET( + resource="datasets/TestSubmission/testdir.zip/version1", + expect_status=200, expect_reason="OK", expect_type="application/zip") + self.assertEqual(zipdata, zipfile, "Difference between local and remote zipfile - Version 1!") + #Access state information and check + (resp, data) = self.doHTTP_GET( + resource="states/TestSubmission/version1", + expect_status=200, expect_reason="OK", expect_type="application/json") + state = data['state'] + parts = data['parts'] + self.assertEqual(len(state.keys()), 11, "States") + self.assertEqual(len(parts.keys()), 4, "Parts") + self.assertEqual(len(parts['4=TestSubmission'].keys()), 13, "File stats for 4=TestSubmission") + self.assertEqual(len(parts['manifest.rdf'].keys()), 13, "File stats for manifest.rdf") + self.assertEqual(len(parts['testdir.zip'].keys()), 13, "File stats for testdir.zip") + #---------Version 2 + # Access and check list of contents of version 2 + (resp, rdfdata) = self.doHTTP_GET( + resource="datasets/TestSubmission/version2", + expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") + rdfgraph = Graph() + rdfstream = StringIO(rdfdata) + rdfgraph.parse(rdfstream) + self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) + self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) + self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') + self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"testdir.zip")) in rdfgraph) + self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"testdir2.zip")) in rdfgraph) + self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') + self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') + self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') + self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') + self.failUnless((subj,URIRef(oxds+"currentVersion"),'2') in rdfgraph, 'oxds:currentVersion') + self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') + # Access and check zip file content + (resp, zipfile) = self.doHTTP_GET( + resource="datasets/TestSubmission/testdir.zip/version2", + expect_status=200, expect_reason="OK", expect_type="application/zip") + self.assertEqual(zipdata, zipfile, "Difference between local and remote zipfile - Version 2!") + (resp, zipfile2) = self.doHTTP_GET( + resource="datasets/TestSubmission/testdir2.zip/version2", + expect_status=200, expect_reason="OK", expect_type="application/zip") + self.assertEqual(zipdata2, zipfile2, "Difference between local and remote zipfile - Version 2!") + #Access state information and check + (resp, data) = self.doHTTP_GET( + resource="states/TestSubmission/version2", + expect_status=200, expect_reason="OK", expect_type="application/json") + state = data['state'] + parts = data['parts'] + self.assertEqual(len(state.keys()), 11, "States") + self.assertEqual(len(parts.keys()), 5, "Parts") + self.assertEqual(len(parts['4=TestSubmission'].keys()), 13, "File stats for 4=TestSubmission") + self.assertEqual(len(parts['manifest.rdf'].keys()), 13, "File stats for manifest.rdf") + self.assertEqual(len(parts['testdir.zip'].keys()), 13, "File stats for testdir.zip") + self.assertEqual(len(parts['testdir2.zip'].keys()), 13, "File stats for testdir2.zip") + #---------Version 3 + # Access and check list of contents of version 3 + (resp, rdfdata) = self.doHTTP_GET( + resource="datasets/TestSubmission/version3", + expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") + rdfgraph = Graph() + rdfstream = StringIO(rdfdata) + rdfgraph.parse(rdfstream) + self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) + self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) + self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') + self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"testdir2.zip")) in rdfgraph) + self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') + self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') + self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') + self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') + self.failUnless((subj,URIRef(oxds+"currentVersion"),'3') in rdfgraph, 'oxds:currentVersion') + self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') + # Access and check zip file content + (resp, zipfile) = self.doHTTP_GET( + resource="datasets/TestSubmission/testdir2.zip/version3", + expect_status=200, expect_reason="OK", expect_type="application/zip") + self.assertEqual(zipdata2, zipfile, "Difference between local and remote zipfile - Version 3!") + (resp, zipfile) = self.doHTTP_GET( + resource="datasets/TestSubmission/testdir.zip/version3", + expect_status=404, expect_reason="Not Found") + #Access state information and check + (resp, data) = self.doHTTP_GET( + resource="states/TestSubmission/version3", + expect_status=200, expect_reason="OK", expect_type="application/json") + state = data['state'] + parts = data['parts'] + self.assertEqual(len(state.keys()), 11, "States") + self.assertEqual(len(parts.keys()), 4, "Parts") + self.assertEqual(len(parts['4=TestSubmission'].keys()), 13, "File stats for 4=TestSubmission") + self.assertEqual(len(parts['manifest.rdf'].keys()), 13, "File stats for manifest.rdf") + self.assertEqual(len(parts['testdir2.zip'].keys()), 13, "File stats for testdir2.zip") + #---------Version 4 + # Access and check list of contents of version 4 + (resp, rdfdata) = self.doHTTP_GET( + resource="datasets/TestSubmission/version4", + expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") + rdfgraph = Graph() + rdfstream = StringIO(rdfdata) + rdfgraph.parse(rdfstream) + self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) + self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) + self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') + self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"testdir2.zip")) in rdfgraph) + self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') + self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') + self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') + self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') + self.failUnless((subj,URIRef(oxds+"currentVersion"),'4') in rdfgraph, 'oxds:currentVersion') + self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') + # Access and check zip file content + (resp, zipfile) = self.doHTTP_GET( + resource="datasets/TestSubmission/testdir2.zip/version4", + expect_status=200, expect_reason="OK", expect_type="application/zip") + self.assertEqual(zipdata3, zipfile, "Difference between local and remote zipfile - Version 4!") + (resp, zipfile) = self.doHTTP_GET( + resource="datasets/TestSubmission/testdir.zip/version4", + expect_status=404, expect_reason="Not Found") + #Access state information and check + (resp, data) = self.doHTTP_GET( + resource="states/TestSubmission/version4", + expect_status=200, expect_reason="OK", expect_type="application/json") + state = data['state'] + parts = data['parts'] + self.assertEqual(len(state.keys()), 11, "States") + self.assertEqual(len(parts.keys()), 4, "Parts") + self.assertEqual(state['item_id'], "TestSubmission", "Submission item identifier") + self.assertEqual(len(state['versions']), 5, "Five versions") + self.assertEqual(state['versions'],['0', '1', '2', '3', '4'], "Versions") + self.assertEqual(state['currentversion'], '4', "Current version == 4") + self.assertEqual(state['rdffileformat'], 'xml', "RDF file type") + self.assertEqual(state['rdffilename'], 'manifest.rdf', "RDF file name") + self.assertEqual(state['files']['0'], ['manifest.rdf'], "List should contain just manifest.rdf") self.assertEqual(len(state['files']['1']), 2, "List should contain manifest.rdf and testdir.zip") self.assertEqual(len(state['files']['2']), 3, "List should contain manifest.rdf, testdir.zip and testdir2.zip") self.assertEqual(len(state['files']['3']), 2, "List should contain manifest.rdf and testdir2.zip") @@ -1091,7 +1399,7 @@ def testPostMetadataFile(self): address = "http://schemas.talis.com/2005/address/schema#" stype = URIRef(oxds+"DataSet") stype2 = URIRef(bibo+"DocumentPart") - self.assertEqual(len(rdfgraph),42,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),41,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') @@ -1099,7 +1407,6 @@ def testPostMetadataFile(self): self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:piblisher') self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(oxds+"currentVersion"),'1') in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') self.failUnless((subj,RDF.type,stype2) in rdfgraph, 'Testing submission type: '+subj+", "+stype2) @@ -1183,7 +1490,7 @@ def testMetadataFileUpdate(self): foaf = "http://xmlns.com/foaf/0.1/" address = "http://schemas.talis.com/2005/address/schema#" stype = URIRef(oxds+"DataSet") - self.assertEqual(len(rdfgraph),13,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') @@ -1191,7 +1498,6 @@ def testMetadataFileUpdate(self): self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:piblisher') self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(oxds+"currentVersion"),'1') in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') self.failUnless((subj,URIRef(dcterms+"title"),"Test dataset with merged metadata") in rdfgraph, 'dcterms:title') @@ -1219,7 +1525,7 @@ def testMetadataFileUpdate(self):
    Was worth a million such; and yet
    She lived long, till God gave her rest.

    """ - self.assertEqual(len(rdfgraph),32,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),31,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') @@ -1227,7 +1533,6 @@ def testMetadataFileUpdate(self): self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(oxds+"currentVersion"),'2') in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') self.failUnless((subj,URIRef(dcterms+"title"),'A Cat') in rdfgraph, 'dcterms:title') @@ -1239,8 +1544,6 @@ def testMetadataFileUpdate(self): self.failUnless((subj,URIRef(dcterms+"type"),"Poem") in rdfgraph, 'dcterms:type') self.failUnless((subj,URIRef(dcterms+"type"),URIRef("http://purl.org/dc/dcmitype/Text")) in rdfgraph, 'dcterms:type') self.failUnless((subj,URIRef(dcterms+"rightsHolder"),"Copyright Edward Thomas, 1979, reproduced under licence from Faber and Faber Ltd.") in rdfgraph, 'dcterms:rightsHolder') - #for s, p, o in rdfgraph.triples((None, RDF.value, None)): - # print s, p, o, type(o) self.failUnless((subj,RDF.value,Literal(doctext)) in rdfgraph, 'rdf:value') self.failUnless((subj,URIRef(dcterms+"source"),"Edward Thomas Collected Poems") in rdfgraph, 'dcterms:source') #self.failUnless((subj,URIRef(dcterms+"created"),"1979-01-01/1979-12-31") in rdfgraph, 'dcterms:created') @@ -1302,7 +1605,7 @@ def testMetadataFileDelete(self): dcterms = "http://purl.org/dc/terms/" oxds = "http://vocab.ox.ac.uk/dataset/schema#" stype = URIRef(oxds+"DataSet") - self.assertEqual(len(rdfgraph),10,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),9,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') @@ -1310,7 +1613,6 @@ def testMetadataFileDelete(self): self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(oxds+"currentVersion"),'0') in rdfgraph, 'oxds:currentVersion') def testPutCreateFile(self): @@ -1337,7 +1639,7 @@ def testPutCreateFile(self): ore = "http://www.openarchives.org/ore/terms/" oxds = "http://vocab.ox.ac.uk/dataset/schema#" stype = URIRef(oxds+"DataSet") - self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"testdir.zip")) in rdfgraph) @@ -1346,7 +1648,6 @@ def testPutCreateFile(self): self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(oxds+"currentVersion"),'1') in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') # Access and check zip file content @@ -1407,7 +1708,7 @@ def testPutUpdateFile(self): rdfgraph.parse(rdfstream) subj = URIRef(self.getRequestUri("datasets/TestSubmission")) oxds = "http://vocab.ox.ac.uk/dataset/schema#" - self.assertEqual(len(rdfgraph),13,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,URIRef(oxds+"currentVersion"),'2') in rdfgraph, 'oxds:currentVersion') # Access and check zip file content and version (resp, zipfile) = self.doHTTP_GET( @@ -1435,7 +1736,7 @@ def testPutUpdateFile(self): ore = "http://www.openarchives.org/ore/terms/" oxds = "http://vocab.ox.ac.uk/dataset/schema#" stype = URIRef(oxds+"DataSet") - self.assertEqual(len(rdfgraph),13,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"testdir.zip")) in rdfgraph) @@ -1445,7 +1746,6 @@ def testPutUpdateFile(self): self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(oxds+"currentVersion"),'3') in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') # Access and check zip file content @@ -1520,7 +1820,7 @@ def testPutMetadataFile(self): oxds = "http://vocab.ox.ac.uk/dataset/schema#" owl = "http://www.w3.org/2002/07/owl#" stype = URIRef(oxds+"DataSet") - self.assertEqual(len(rdfgraph),13,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') @@ -1528,7 +1828,6 @@ def testPutMetadataFile(self): self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(oxds+"currentVersion"),'1') in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') self.failUnless((subj,URIRef(dcterms+"title"),"Test dataset with merged metadata") in rdfgraph, 'dcterms:title') @@ -1544,7 +1843,7 @@ def testPutMetadataFile(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),13,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') @@ -1552,7 +1851,6 @@ def testPutMetadataFile(self): self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(oxds+"currentVersion"),'2') in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') self.failUnless((subj,URIRef(owl+"sameAs"),URIRef("http://example.org/testrdf/")) in rdfgraph, 'owl:sameAs') @@ -1614,7 +1912,7 @@ def testUnicodeMetadataFileUpdate(self): f = codecs.open('testdata/unicodedata/unicode01.txt', 'r', 'utf-8') doctext1 = f.read() f.close() - self.assertEqual(len(rdfgraph),14,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),13,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') @@ -1622,7 +1920,6 @@ def testUnicodeMetadataFileUpdate(self): self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:piblisher') self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(oxds+"currentVersion"),'1') in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') self.failUnless((subj,URIRef(dcterms+"title"),"General punctuation") in rdfgraph, 'dcterms:title') @@ -1651,7 +1948,7 @@ def testUnicodeMetadataFileUpdate(self): f = codecs.open('testdata/unicodedata/unicode02.txt', 'r', 'utf-8') doctext2 = f.read() f.close() - self.assertEqual(len(rdfgraph),15,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),14,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,URIRef(oxds+"currentVersion"),'2') in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(dcterms+"title"),"A table of (some) accents") in rdfgraph, 'dcterms:title') self.failUnless((subj,RDF.value,Literal(doctext2)) in rdfgraph, 'rdf:value') @@ -1673,7 +1970,7 @@ def testUnicodeMetadataFileUpdate(self): f = codecs.open('testdata/unicodedata/unicode03.txt', 'r', 'utf-8') doctext3 = f.read() f.close() - self.assertEqual(len(rdfgraph),16,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),15,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,URIRef(oxds+"currentVersion"),'3') in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(dcterms+"title"),"Combining diacritics") in rdfgraph, 'dcterms:title') self.failUnless((subj,RDF.value,Literal(doctext3)) in rdfgraph, 'rdf:value') @@ -1693,7 +1990,7 @@ def testUnicodeMetadataFileUpdate(self): f = codecs.open('testdata/unicodedata/unicode04.txt', 'r', 'utf-8') doctext4 = f.read() f.close() - self.assertEqual(len(rdfgraph),17,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),16,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,URIRef(oxds+"currentVersion"),'4') in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(dcterms+"title"),"Various symbols") in rdfgraph, 'dcterms:title') self.failUnless((subj,RDF.value,Literal(doctext4)) in rdfgraph, 'rdf:value') @@ -1713,7 +2010,7 @@ def testUnicodeMetadataFileUpdate(self): f = codecs.open('testdata/unicodedata/unicode05.txt', 'r', 'utf-8') doctext5 = f.read() f.close() - self.assertEqual(len(rdfgraph),18,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),17,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,URIRef(oxds+"currentVersion"),'5') in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(dcterms+"title"),"Some verses in Russian") in rdfgraph, 'dcterms:title') self.failUnless((subj,RDF.value,Literal(doctext5)) in rdfgraph, 'rdf:value') @@ -1735,7 +2032,7 @@ def testUnicodeMetadataFileUpdate(self): f = codecs.open('testdata/unicodedata/unicode06.txt', 'r', 'utf-8') doctext6 = f.read() f.close() - self.assertEqual(len(rdfgraph),19,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),18,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,URIRef(oxds+"currentVersion"),'6') in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(dcterms+"title"),"Some verses in ancient Greek") in rdfgraph, 'dcterms:title') self.failUnless((subj,RDF.value,Literal(doctext6)) in rdfgraph, 'rdf:value') @@ -1755,7 +2052,7 @@ def testUnicodeMetadataFileUpdate(self): f = codecs.open('testdata/unicodedata/unicode07.txt', 'r', 'utf-8') doctext7 = f.read() f.close() - self.assertEqual(len(rdfgraph),20,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),19,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,URIRef(oxds+"currentVersion"),'7') in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(dcterms+"title"),"Some verses in Sanskrit") in rdfgraph, 'dcterms:title') self.failUnless((subj,RDF.value,Literal(doctext7)) in rdfgraph, 'rdf:value') @@ -1777,7 +2074,7 @@ def testUnicodeMetadataFileUpdate(self): f = codecs.open('testdata/unicodedata/unicode08.txt', 'r', 'utf-8') doctext8= f.read() f.close() - self.assertEqual(len(rdfgraph),21,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),20,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,URIRef(oxds+"currentVersion"),'8') in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(dcterms+"title"),"Some Chinese") in rdfgraph, 'dcterms:title') self.failUnless((subj,RDF.value,Literal(doctext8)) in rdfgraph, 'rdf:value') @@ -1797,7 +2094,7 @@ def testUnicodeMetadataFileUpdate(self): f = codecs.open('testdata/unicodedata/unicode09.txt', 'r', 'utf-8') doctext9 = f.read() f.close() - self.assertEqual(len(rdfgraph),22,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),21,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,URIRef(oxds+"currentVersion"),'9') in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(dcterms+"title"),"A Tamil name") in rdfgraph, 'dcterms:title') self.failUnless((subj,RDF.value,Literal(doctext9)) in rdfgraph, 'rdf:value') @@ -1809,26 +2106,333 @@ def testUnicodeMetadataFileUpdate(self): #Access state information and check (resp, rdfdata) = self.doHTTP_GET( resource="datasets/TestSubmission", - expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") - fr = open('response.xml', 'w') - fr.write(rdfdata) - fr.close() - rdfgraph = Graph() - rdfgraph.parse('response.xml', format='xml') - doctext10 = None - f = codecs.open('testdata/unicodedata/unicode10.txt', 'r', 'utf-8') - doctext10= f.read() - f.close() - self.assertEqual(len(rdfgraph),23,'Graph length %i' %len(rdfgraph)) - self.failUnless((subj,URIRef(oxds+"currentVersion"),'10') in rdfgraph, 'oxds:currentVersion') - self.failUnless((subj,URIRef(dcterms+"title"),"Some Arabic") in rdfgraph, 'dcterms:title') - self.failUnless((subj,RDF.value,Literal(doctext10)) in rdfgraph, 'rdf:value') - os.remove('response.xml') - - def testDeleteEmbargo(self): - """Delete embargo information - POST embargo_change to /silo_name/datasets/dataset_name""" - # Create a new dataset, check response - self.createSubmissionDataset() + expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") + fr = open('response.xml', 'w') + fr.write(rdfdata) + fr.close() + rdfgraph = Graph() + rdfgraph.parse('response.xml', format='xml') + doctext10 = None + f = codecs.open('testdata/unicodedata/unicode10.txt', 'r', 'utf-8') + doctext10= f.read() + f.close() + self.assertEqual(len(rdfgraph),22,'Graph length %i' %len(rdfgraph)) + self.failUnless((subj,URIRef(oxds+"currentVersion"),'10') in rdfgraph, 'oxds:currentVersion') + self.failUnless((subj,URIRef(dcterms+"title"),"Some Arabic") in rdfgraph, 'dcterms:title') + self.failUnless((subj,RDF.value,Literal(doctext10)) in rdfgraph, 'rdf:value') + os.remove('response.xml') + + def testDeleteEmbargo(self): + """Delete embargo information - POST embargo_change to /silo_name/datasets/dataset_name""" + # Create a new dataset, check response + self.createSubmissionDataset() + #Access dataset and check content + (resp, rdfdata) = self.doHTTP_GET( + resource="datasets/TestSubmission", + expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") + rdfgraph = Graph() + rdfstream = StringIO(rdfdata) + rdfgraph.parse(rdfstream) + self.assertEqual(len(rdfgraph),9,'Graph length %i' %len(rdfgraph)) + oxds = "http://vocab.ox.ac.uk/dataset/schema#" + dcterms = "http://purl.org/dc/terms/" + subj = URIRef(self.getRequestUri("datasets/TestSubmission")) + stype = URIRef(oxds+"DataSet") + self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') + self.assertFalse((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + # Delete embargo, check response + fields = \ + [ ("embargo_change", 'true') + ] + files =[] + (reqtype, reqdata) = SparqlQueryTestCase.encode_multipart_formdata(fields, files) + (resp,respdata) = self.doHTTP_POST( + reqdata, reqtype, + resource="datasets/TestSubmission", + expect_status=204, expect_reason="Updated") + #Access dataset and check content + (resp, rdfdata) = self.doHTTP_GET( + resource="datasets/TestSubmission", + expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") + rdfgraph = Graph() + rdfstream = StringIO(rdfdata) + rdfgraph.parse(rdfstream) + self.assertEqual(len(rdfgraph),10,'Graph length %i' %len(rdfgraph)) + oxds = "http://vocab.ox.ac.uk/dataset/schema#" + dcterms = "http://purl.org/dc/terms/" + subj = URIRef(self.getRequestUri("datasets/TestSubmission")) + stype = URIRef(oxds+"DataSet") + self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'False') in rdfgraph, 'oxds:isEmbargoed') + self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') + self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') + self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') + self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') + self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') + self.failUnless((subj,URIRef(oxds+"currentVersion"),'1') in rdfgraph, 'oxds:currentVersion') + self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') + #Access state information and check + (resp, data) = self.doHTTP_GET( + resource="states/TestSubmission", + expect_status=200, expect_reason="OK", expect_type="application/json") + state = data['state'] + self.assertEqual(state['metadata']['embargoed'], False, "Embargoed?") + self.assertEqual(state['metadata']['embargoed_until'], "", "Should have no date for embargoed_until") + + def testChangeEmbargo(self): + """Modify embargo information - POST embargo_change, embargo, embargo_until to /silo_name/datasets/dataset_name""" + # Create a new dataset, check response + self.createSubmissionDataset() + #Access dataset and check content + (resp, rdfdata) = self.doHTTP_GET( + resource="datasets/TestSubmission", + expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") + rdfgraph = Graph() + rdfstream = StringIO(rdfdata) + rdfgraph.parse(rdfstream) + self.assertEqual(len(rdfgraph),9,'Graph length %i' %len(rdfgraph)) + oxds = "http://vocab.ox.ac.uk/dataset/schema#" + dcterms = "http://purl.org/dc/terms/" + subj = URIRef(self.getRequestUri("datasets/TestSubmission")) + stype = URIRef(oxds+"DataSet") + self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') + self.assertFalse((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + #Access state information and check + (resp, data) = self.doHTTP_GET( + resource="states/TestSubmission", + expect_status=200, expect_reason="OK", expect_type="application/json") + state = data['state'] + self.assertEqual(state['metadata']['embargoed'], True, "Embargoed?") + self.assertEqual(state['metadata']['embargoed_until'], '', "embargoed_until?") + #------------------------------------------------- + # Change embargo without embargo_until date - embargoed = True, check response + fields = \ + [ ("embargoed", 'true') + ] + files =[] + (reqtype, reqdata) = SparqlQueryTestCase.encode_multipart_formdata(fields, files) + (resp,respdata) = self.doHTTP_POST( + reqdata, reqtype, + resource="datasets/TestSubmission", + expect_status=204, expect_reason="Updated") + #Access dataset and check content + (resp, rdfdata) = self.doHTTP_GET( + resource="datasets/TestSubmission", + expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") + rdfgraph = Graph() + rdfstream = StringIO(rdfdata) + rdfgraph.parse(rdfstream) + self.assertEqual(len(rdfgraph),10,'Graph length %i' %len(rdfgraph)) + oxds = "http://vocab.ox.ac.uk/dataset/schema#" + dcterms = "http://purl.org/dc/terms/" + subj = URIRef(self.getRequestUri("datasets/TestSubmission")) + stype = URIRef(oxds+"DataSet") + self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') + self.assertFalse((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') + self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') + self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') + self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') + self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') + self.failUnless((subj,URIRef(oxds+"currentVersion"),'1') in rdfgraph, 'oxds:currentVersion') + self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') + #Access state information and check + (resp, data) = self.doHTTP_GET( + resource="states/TestSubmission", + expect_status=200, expect_reason="OK", expect_type="application/json") + state = data['state'] + self.assertEqual(state['metadata']['embargoed'], True, "Embargoed?") + self.assertEqual(state['metadata']['embargoed_until'], '', "embargoed_until?") + #------------------------------------------------- + #Change embargo - embargoed = true, embargoed_until = True + d = datetime.now().isoformat() + fields = \ + [ ("embargoed", 'true') + ,("embargoed_until", 'true') + ] + files =[] + (reqtype, reqdata) = SparqlQueryTestCase.encode_multipart_formdata(fields, files) + (resp,respdata) = self.doHTTP_POST( + reqdata, reqtype, + resource="datasets/TestSubmission", + expect_status=204, expect_reason="Updated") + #Access dataset and check content + (resp, rdfdata) = self.doHTTP_GET( + resource="datasets/TestSubmission", + expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") + rdfgraph = Graph() + rdfstream = StringIO(rdfdata) + rdfgraph.parse(rdfstream) + self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) + oxds = "http://vocab.ox.ac.uk/dataset/schema#" + dcterms = "http://purl.org/dc/terms/" + subj = URIRef(self.getRequestUri("datasets/TestSubmission")) + stype = URIRef(oxds+"DataSet") + self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') + self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') + self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') + self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') + self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') + self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') + self.failUnless((subj,URIRef(oxds+"currentVersion"),'2') in rdfgraph, 'oxds:currentVersion') + self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') + #Access state information and check + (resp, data) = self.doHTTP_GET( + resource="states/TestSubmission", + expect_status=200, expect_reason="OK", expect_type="application/json") + state = data['state'] + d = (datetime.now() + relativedelta(years=+70)).isoformat() + d = d.split('T')[0] + self.assertEqual(state['metadata']['embargoed'], True, "Embargoed?") + self.assertTrue(d in state['metadata']['embargoed_until'], "embargoed_until %s?"%d) + #------------------------------------------------- + #Change embargo - embargoed = true, embargoed_until = datetime + d = datetime.now() + delta = timedelta(days=365*4) + d2 = d + delta + d2 = d2.isoformat() + fields = \ + [ ("embargoed", 'true') + ,("embargoed_until", d2) + ] + files =[] + (reqtype, reqdata) = SparqlQueryTestCase.encode_multipart_formdata(fields, files) + (resp,respdata) = self.doHTTP_POST( + reqdata, reqtype, + resource="datasets/TestSubmission", + expect_status=204, expect_reason="Updated") + #Access dataset and check content + (resp, rdfdata) = self.doHTTP_GET( + resource="datasets/TestSubmission", + expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") + rdfgraph = Graph() + rdfstream = StringIO(rdfdata) + rdfgraph.parse(rdfstream) + self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) + oxds = "http://vocab.ox.ac.uk/dataset/schema#" + dcterms = "http://purl.org/dc/terms/" + subj = URIRef(self.getRequestUri("datasets/TestSubmission")) + stype = URIRef(oxds+"DataSet") + self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') + self.failUnless((subj,URIRef(oxds+"embargoedUntil"),d2) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') + self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') + self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') + self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') + self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') + self.failUnless((subj,URIRef(oxds+"currentVersion"),'3') in rdfgraph, 'oxds:currentVersion') + self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') + #Access state information and check + (resp, data) = self.doHTTP_GET( + resource="states/TestSubmission", + expect_status=200, expect_reason="OK", expect_type="application/json") + state = data['state'] + self.assertEqual(state['metadata']['embargoed'], True, "Embargoed?") + self.assertEqual(state['metadata']['embargoed_until'], d2, "embargoed_until?") + #------------------------------------------------- + #Change embargo - embargoed = true, embargoed_until = datetime, embargo_change = true + d2 = '09 August 2013' + fields = \ + [ ("embargo_change", 'true') + ,("embargoed", 'true') + ,("embargoed_until", d2) + ] + files =[] + (reqtype, reqdata) = SparqlQueryTestCase.encode_multipart_formdata(fields, files) + (resp,respdata) = self.doHTTP_POST( + reqdata, reqtype, + resource="datasets/TestSubmission", + expect_status=204, expect_reason="Updated") + #Access dataset and check content + (resp, rdfdata) = self.doHTTP_GET( + resource="datasets/TestSubmission", + expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") + rdfgraph = Graph() + rdfstream = StringIO(rdfdata) + rdfgraph.parse(rdfstream) + self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) + oxds = "http://vocab.ox.ac.uk/dataset/schema#" + dcterms = "http://purl.org/dc/terms/" + subj = URIRef(self.getRequestUri("datasets/TestSubmission")) + stype = URIRef(oxds+"DataSet") + self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') + self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') + self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') + self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') + self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') + self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') + self.failUnless((subj,URIRef(oxds+"currentVersion"),'4') in rdfgraph, 'oxds:currentVersion') + self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') + #Access state information and check + (resp, data) = self.doHTTP_GET( + resource="states/TestSubmission", + expect_status=200, expect_reason="OK", expect_type="application/json") + state = data['state'] + self.assertEqual(state['metadata']['embargoed'], True, "Embargoed?") + self.assertTrue('2013-08-09' in state['metadata']['embargoed_until'], "embargoed_until 2013-08-09?") + #------------------------------------------------- + # Change embargo - embargoed_until = true and check response + fields = \ + [ ("embargoed_until", 'true') + ] + files =[] + (reqtype, reqdata) = SparqlQueryTestCase.encode_multipart_formdata(fields, files) + (resp,respdata) = self.doHTTP_POST( + reqdata, reqtype, + resource="datasets/TestSubmission", + expect_status=400, expect_reason="Bad request") + #Access dataset and check content + (resp, rdfdata) = self.doHTTP_GET( + resource="datasets/TestSubmission", + expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") + rdfgraph = Graph() + rdfstream = StringIO(rdfdata) + rdfgraph.parse(rdfstream) + self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) + oxds = "http://vocab.ox.ac.uk/dataset/schema#" + dcterms = "http://purl.org/dc/terms/" + subj = URIRef(self.getRequestUri("datasets/TestSubmission")) + stype = URIRef(oxds+"DataSet") + self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') + self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') + self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') + self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') + self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') + self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') + self.failUnless((subj,URIRef(oxds+"currentVersion"),'4') in rdfgraph, 'oxds:currentVersion') + self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') + #Access state information and check + (resp, data) = self.doHTTP_GET( + resource="states/TestSubmission", + expect_status=200, expect_reason="OK", expect_type="application/json") + state = data['state'] + self.assertEqual(state['metadata']['embargoed'], True, "Embargoed?") + self.assertTrue('2013-08-09' in state['metadata']['embargoed_until'], "embargoed_until 2013-08-09?") + #------------------------------------------------- + # Change embargo - embargoed_until = date and check response + d5 = datetime.now() + delta = timedelta(days=3) + d5 = d5 + delta + d5 = d5.isoformat() + fields = \ + [ ("embargoed_until", d5) + ] + files =[] + (reqtype, reqdata) = SparqlQueryTestCase.encode_multipart_formdata(fields, files) + (resp,respdata) = self.doHTTP_POST( + reqdata, reqtype, + resource="datasets/TestSubmission", + expect_status=400, expect_reason="Bad request") #Access dataset and check content (resp, rdfdata) = self.doHTTP_GET( resource="datasets/TestSubmission", @@ -1836,7 +2440,7 @@ def testDeleteEmbargo(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),10,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) oxds = "http://vocab.ox.ac.uk/dataset/schema#" dcterms = "http://purl.org/dc/terms/" subj = URIRef(self.getRequestUri("datasets/TestSubmission")) @@ -1844,9 +2448,24 @@ def testDeleteEmbargo(self): self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') - # Delete embargo, check response + self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') + self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') + self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') + self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') + self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') + self.failUnless((subj,URIRef(oxds+"currentVersion"),'4') in rdfgraph, 'oxds:currentVersion') + self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') + #Access state information and check + (resp, data) = self.doHTTP_GET( + resource="states/TestSubmission", + expect_status=200, expect_reason="OK", expect_type="application/json") + state = data['state'] + self.assertEqual(state['metadata']['embargoed'], True, "Embargoed?") + self.assertTrue('2013-08-09' in state['metadata']['embargoed_until'], "embargoed_until 2013-08-09?") + #------------------------------------------------- + #Delete embargo fields = \ - [ ("embargo_change", 'true') + [ ("embargoed", 'false') ] files =[] (reqtype, reqdata) = SparqlQueryTestCase.encode_multipart_formdata(fields, files) @@ -1868,12 +2487,13 @@ def testDeleteEmbargo(self): stype = URIRef(oxds+"DataSet") self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'False') in rdfgraph, 'oxds:isEmbargoed') + self.assertFalse((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"currentVersion"),'1') in rdfgraph, 'oxds:currentVersion') + self.failUnless((subj,URIRef(oxds+"currentVersion"),'5') in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') #Access state information and check (resp, data) = self.doHTTP_GET( @@ -1881,12 +2501,19 @@ def testDeleteEmbargo(self): expect_status=200, expect_reason="OK", expect_type="application/json") state = data['state'] self.assertEqual(state['metadata']['embargoed'], False, "Embargoed?") - self.assertEqual(state['metadata']['embargoed_until'], "", "Should have no date for embargoed_until") - - def testChangeEmbargo(self): - """Modify embargo information - POST embargo_change, embargo, embargo_until to /silo_name/datasets/dataset_name""" - # Create a new dataset, check response - self.createSubmissionDataset() + self.assertEqual(state['metadata']['embargoed_until'], '', "Embargoed until?") + #------------------------------------------------- + #Delete embargo + fields = \ + [ ("embargoed", 'false') + ,("embargoed_until", 'true') + ] + files =[] + (reqtype, reqdata) = SparqlQueryTestCase.encode_multipart_formdata(fields, files) + (resp,respdata) = self.doHTTP_POST( + reqdata, reqtype, + resource="datasets/TestSubmission", + expect_status=204, expect_reason="Updated") #Access dataset and check content (resp, rdfdata) = self.doHTTP_GET( resource="datasets/TestSubmission", @@ -1900,17 +2527,31 @@ def testChangeEmbargo(self): subj = URIRef(self.getRequestUri("datasets/TestSubmission")) stype = URIRef(oxds+"DataSet") self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') - # Delete embargo, check response + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'False') in rdfgraph, 'oxds:isEmbargoed') + self.assertFalse((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') + self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') + self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') + self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') + self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') + self.failUnless((subj,URIRef(oxds+"currentVersion"),'6') in rdfgraph, 'oxds:currentVersion') + self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') + #Access state information and check + (resp, data) = self.doHTTP_GET( + resource="states/TestSubmission", + expect_status=200, expect_reason="OK", expect_type="application/json") + state = data['state'] + self.assertEqual(state['metadata']['embargoed'], False, "Embargoed?") + self.assertEqual(state['metadata']['embargoed_until'], '', "Embargoed until?") + #------------------------------------------------- + #Delete embargo d = datetime.now() - delta = timedelta(days=365*3) - d2 = d + delta - d2 = d2.isoformat() + delta = timedelta(days=4) + d3 = d + delta + d3 = d3.isoformat() fields = \ - [ ("embargo_change", 'true') - ,("embargoed", 'true') - ,("embargoed_until", d2) + [ ("embargoed", 'false') + ,("embargoed_until", d3) ] files =[] (reqtype, reqdata) = SparqlQueryTestCase.encode_multipart_formdata(fields, files) @@ -1925,28 +2566,28 @@ def testChangeEmbargo(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),10,'Graph length %i' %len(rdfgraph)) oxds = "http://vocab.ox.ac.uk/dataset/schema#" dcterms = "http://purl.org/dc/terms/" subj = URIRef(self.getRequestUri("datasets/TestSubmission")) stype = URIRef(oxds+"DataSet") self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),d2) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'False') in rdfgraph, 'oxds:isEmbargoed') + self.assertFalse((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"currentVersion"),'1') in rdfgraph, 'oxds:currentVersion') + self.failUnless((subj,URIRef(oxds+"currentVersion"),'7') in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') #Access state information and check (resp, data) = self.doHTTP_GET( resource="states/TestSubmission", expect_status=200, expect_reason="OK", expect_type="application/json") state = data['state'] - self.assertEqual(state['metadata']['embargoed'], True, "Embargoed?") - self.assertEqual(state['metadata']['embargoed_until'], d2, "embargoed_until?") + self.assertEqual(state['metadata']['embargoed'], False, "Embargoed?") + self.assertEqual(state['metadata']['embargoed_until'], '', "Embargoed until?") def testFileUnpack(self): """Unpack zip file to a new dataset - POST zip filename to /silo_name/items/dataset_name""" @@ -1984,7 +2625,7 @@ def testFileUnpack(self): ore = "http://www.openarchives.org/ore/terms/" oxds = "http://vocab.ox.ac.uk/dataset/schema#" stype = URIRef(oxds+"DataSet") - self.assertEqual(len(rdfgraph),13,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"testdir.zip")) in rdfgraph) @@ -1994,7 +2635,6 @@ def testFileUnpack(self): self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(oxds+"currentVersion"),"1") in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') # Access new dataset, check response @@ -2007,14 +2647,13 @@ def testFileUnpack(self): subj = URIRef(self.getRequestUri("datasets/TestSubmission-testdir")) stype = URIRef("http://vocab.ox.ac.uk/dataset/schema#Grouping") base = self.getRequestUri("datasets/TestSubmission-testdir/") - self.assertEqual(len(rdfgraph),17,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),16,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') self.failUnless((subj,URIRef(dcterms+"isVersionOf"),None) in rdfgraph, 'dcterms:isVersionOf') @@ -2066,7 +2705,7 @@ def testFileUnpack(self): def testSymlinkFileUnpack(self): """Unpack zip file uploaded in a previous version to a new dataset - POST zip filename to /silo_name/items/dataset_name""" # Create a new dataset, check response - self.createSubmissionDataset() + self.createSubmissionDataset(embargoed=False) # Upload zip file testdir.zip, check response zipdata = self.uploadSubmissionZipfile(file_to_upload="testdir2.zip") # Upload zip file test, check response @@ -2101,7 +2740,7 @@ def testSymlinkFileUnpack(self): ore = "http://www.openarchives.org/ore/terms/" oxds = "http://vocab.ox.ac.uk/dataset/schema#" stype = URIRef(oxds+"DataSet") - self.assertEqual(len(rdfgraph),14,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),13,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"testdir.zip")) in rdfgraph) @@ -2111,8 +2750,7 @@ def testSymlinkFileUnpack(self): self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'False') in rdfgraph, 'oxds:isEmbargoed') self.failUnless((subj,URIRef(oxds+"currentVersion"),"2") in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') # Access new dataset, check response @@ -2125,14 +2763,13 @@ def testSymlinkFileUnpack(self): subj = URIRef(self.getRequestUri("datasets/TestSubmission-testdir")) stype = URIRef("http://vocab.ox.ac.uk/dataset/schema#Grouping") base = self.getRequestUri("datasets/TestSubmission-testdir/") - self.assertEqual(len(rdfgraph),17,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),16,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') self.failUnless((subj,URIRef(dcterms+"isVersionOf"),None) in rdfgraph, 'dcterms:isVersionOf') @@ -2206,7 +2843,7 @@ def testFileUploadToUnpackedDataset(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),13,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) # Access new dataset TestSubmission-testdir, check response (resp, rdfdata) = self.doHTTP_GET( resource="datasets/TestSubmission-testdir", @@ -2220,14 +2857,13 @@ def testFileUploadToUnpackedDataset(self): dcterms = "http://purl.org/dc/terms/" ore = "http://www.openarchives.org/ore/terms/" oxds = "http://vocab.ox.ac.uk/dataset/schema#" - self.assertEqual(len(rdfgraph),17,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),16,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') self.failUnless((subj,URIRef(dcterms+"isVersionOf"),None) in rdfgraph, 'dcterms:isVersionOf') @@ -2263,14 +2899,13 @@ def testFileUploadToUnpackedDataset(self): subj = URIRef(self.getRequestUri("datasets/TestSubmission-testdir")) stype = URIRef("http://vocab.ox.ac.uk/dataset/schema#Grouping") base = self.getRequestUri("datasets/TestSubmission-testdir/") - self.assertEqual(len(rdfgraph),18,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),17,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') self.failUnless((subj,URIRef(dcterms+"isVersionOf"),None) in rdfgraph, 'dcterms:isVersionOf') @@ -2330,7 +2965,7 @@ def testUpdateUnpackedDataset(self): zipdata = self.uploadSubmissionZipfile() # Upload second zip file, check response zipdata = self.uploadSubmissionZipfile(file_to_upload="testdir2.zip") - # Unpack ZIP file into a new dataset, check response + # Unpack ZIP file into a new dataset, check response - version 1 fields = \ [ ("filename", "testdir.zip") ] @@ -2350,7 +2985,7 @@ def testUpdateUnpackedDataset(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),14,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),13,'Graph length %i' %len(rdfgraph)) # Access and check list of contents in TestSubmission-testdir (resp, rdfdata) = self.doHTTP_GET( resource="datasets/TestSubmission-testdir", @@ -2364,14 +2999,13 @@ def testUpdateUnpackedDataset(self): dcterms = "http://purl.org/dc/terms/" ore = "http://www.openarchives.org/ore/terms/" oxds = "http://vocab.ox.ac.uk/dataset/schema#" - self.assertEqual(len(rdfgraph),17,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),16,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') self.failUnless((subj,URIRef(dcterms+"isVersionOf"),None) in rdfgraph, 'dcterms:isVersionOf') @@ -2381,6 +3015,58 @@ def testUpdateUnpackedDataset(self): self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"directory/file2.a")) in rdfgraph) self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"test-csv.csv")) in rdfgraph) self.failUnless((subj,URIRef(oxds+"currentVersion"),"1") in rdfgraph, 'oxds:currentVersion') + #------------------------------------------------- + #Change embargo - embargoed = true, embargoed_until = datetime + d = datetime.now() + delta = timedelta(days=365*4) + d2 = d + delta + d2 = d2.isoformat() + fields = \ + [ ("embargoed", 'true') + ,("embargoed_until", d2) + ] + files =[] + (reqtype, reqdata) = SparqlQueryTestCase.encode_multipart_formdata(fields, files) + (resp,respdata) = self.doHTTP_POST( + reqdata, reqtype, + resource="datasets/TestSubmission-testdir", + expect_status=204, expect_reason="Updated") + #Access dataset and check content + (resp, rdfdata) = self.doHTTP_GET( + resource="datasets/TestSubmission-testdir", + expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") + rdfgraph = Graph() + rdfstream = StringIO(rdfdata) + rdfgraph.parse(rdfstream) + self.assertEqual(len(rdfgraph),17,'Graph length %i' %len(rdfgraph)) + oxds = "http://vocab.ox.ac.uk/dataset/schema#" + dcterms = "http://purl.org/dc/terms/" + subj = URIRef(self.getRequestUri("datasets/TestSubmission-testdir")) + stype = URIRef(oxds+"Grouping") + self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') + self.failUnless((subj,URIRef(oxds+"embargoedUntil"),d2) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') + self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') + self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') + self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') + self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') + self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') + self.failUnless((subj,URIRef(dcterms+"isVersionOf"),None) in rdfgraph, 'dcterms:isVersionOf') + self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"directory")) in rdfgraph) + self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"directory/file1.a")) in rdfgraph) + self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"directory/file1.b")) in rdfgraph) + self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"directory/file2.a")) in rdfgraph) + self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"test-csv.csv")) in rdfgraph) + self.failUnless((subj,URIRef(oxds+"currentVersion"),"2") in rdfgraph, 'oxds:currentVersion') + #Access state information and check + (resp, data) = self.doHTTP_GET( + resource="states/TestSubmission-testdir", + expect_status=200, expect_reason="OK", expect_type="application/json") + state = data['state'] + self.assertEqual(state['metadata']['embargoed'], True, "Embargoed?") + self.assertEqual(state['metadata']['embargoed_until'], d2, "embargoed_until?") + #------------------------------------------------- # Unpack second ZIP file into dataset TestSubmission-testdir, check response fields = \ [ ("filename", "testdir2.zip"), @@ -2405,7 +3091,7 @@ def testUpdateUnpackedDataset(self): ore = "http://www.openarchives.org/ore/terms/" oxds = "http://vocab.ox.ac.uk/dataset/schema#" stype = URIRef(oxds+"DataSet") - self.assertEqual(len(rdfgraph),15,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),14,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"testdir.zip")) in rdfgraph) @@ -2416,8 +3102,7 @@ def testUpdateUnpackedDataset(self): self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') self.failUnless((subj,URIRef(oxds+"currentVersion"),"2") in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') # Access dataset TestSubmission-testdir, check response @@ -2438,8 +3123,8 @@ def testUpdateUnpackedDataset(self): self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') + self.failUnless((subj,URIRef(oxds+"embargoedUntil"),d2) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dcterms+"title"),"Test dataset with merged metadata") in rdfgraph, 'dcterms:title') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') @@ -2453,31 +3138,33 @@ def testUpdateUnpackedDataset(self): self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"directory2/file2.a")) in rdfgraph) self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"directory2/file2.b")) in rdfgraph) self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"test-csv.csv")) in rdfgraph) - self.failUnless((subj,URIRef(oxds+"currentVersion"),"2") in rdfgraph, 'oxds:currentVersion') + self.failUnless((subj,URIRef(oxds+"currentVersion"),"3") in rdfgraph, 'oxds:currentVersion') #Access state information of TestSubmission-testdir (resp, data) = self.doHTTP_GET( resource="states/TestSubmission-testdir", expect_status=200, expect_reason="OK", expect_type="application/json") state = data['state'] parts = data['parts'] + self.assertEqual(state['metadata']['embargoed'], True, "Embargoed?") + self.assertEqual(state['metadata']['embargoed_until'], d2, "embargoed_until?") self.assertEqual(len(state.keys()), 11, "States") self.assertEqual(state['item_id'], "TestSubmission-testdir", "Submission item identifier") - self.assertEqual(len(state['versions']), 3, "Three versions") - self.assertEqual(state['versions'][0], '0', "Version 0") - self.assertEqual(state['versions'][1], '1', "Version 1") - self.assertEqual(state['versions'][2], '2', "Version 2") - self.assertEqual(state['currentversion'], '2', "Current version == 2") + self.assertEqual(len(state['versions']), 4, "Four versions") + self.assertEqual(state['currentversion'], '3', "Current version == 2") self.assertEqual(state['rdffileformat'], 'xml', "RDF file type") self.assertEqual(state['rdffilename'], 'manifest.rdf', "RDF file name") self.assertEqual(len(state['files']['0']), 1, "List should contain just manifest.rdf") self.assertEqual(len(state['files']['1']), 3, "List should contain manifest.rdf, directory and test-csv.csv") - self.assertEqual(len(state['files']['2']), 4, "List should contain manifest.rdf, directory1, directory2 and test-csv.csv") + self.assertEqual(len(state['files']['2']), 3, "List should contain manifest.rdf, directory and test-csv.csv") + self.assertEqual(len(state['files']['3']), 4, "List should contain manifest.rdf, directory1, directory2 and test-csv.csv") self.assertEqual(len(state['metadata_files']['0']), 0, "metadata_files of version 0") self.assertEqual(len(state['metadata_files']['1']), 0, "metadata_files of version 1") self.assertEqual(len(state['metadata_files']['2']), 0, "metadata_files of version 2") + self.assertEqual(len(state['metadata_files']['3']), 0, "metadata_files of version 3") self.assertEqual(state['subdir']['0'], [], "Subdirectory count for version 0") self.assertEqual(state['subdir']['1'], ['directory'], "Subdirectory for version 1") - self.assertEqual(len(state['subdir']['2']), 2, "Subdirectory for version 2 should be directory1 and directory2") + self.assertEqual(state['subdir']['2'], ['directory'], "Subdirectory for version 2") + self.assertEqual(len(state['subdir']['3']), 2, "Subdirectory for version 2 should be directory1 and directory2") self.assertEqual(state['metadata']['createdby'], RDFDatabankConfig.endpointuser, "Created by") self.assertEqual(state['metadata']['embargoed'], True, "Embargoed?") self.assertEqual(len(parts.keys()), 6, "Parts") @@ -2493,14 +3180,13 @@ def testUpdateUnpackedDataset(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),17,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),16,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') self.failUnless((subj,URIRef(dcterms+"isVersionOf"),None) in rdfgraph, 'dcterms:isVersionOf') @@ -2516,6 +3202,8 @@ def testUpdateUnpackedDataset(self): expect_status=200, expect_reason="OK", expect_type="application/json") state = data['state'] parts = data['parts'] + self.assertEqual(state['metadata']['embargoed'], True, "Embargoed?") + self.assertEqual(state['metadata']['embargoed_until'], d2, "embargoed_until?") self.assertEqual(len(state.keys()), 11, "States") self.assertEqual(len(parts.keys()), 5, "Parts") self.assertEqual(len(parts['4=TestSubmission-testdir'].keys()), 13, "File stats for 4=TestSubmission-testdir") @@ -2529,14 +3217,13 @@ def testUpdateUnpackedDataset(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),10,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),9,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype1) in rdfgraph, 'Testing submission type: '+subj+", "+stype1) self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(oxds+"currentVersion"),"0") in rdfgraph, 'oxds:currentVersion') #Access state information of TestSubmission-testdir version 0 @@ -2545,6 +3232,8 @@ def testUpdateUnpackedDataset(self): expect_status=200, expect_reason="OK", expect_type="application/json") state = data['state'] parts = data['parts'] + self.assertEqual(state['metadata']['embargoed'], True, "Embargoed?") + self.assertEqual(state['metadata']['embargoed_until'], d2, "embargoed_until?") self.assertEqual(len(state.keys()), 11, "States") self.assertEqual(len(parts.keys()), 3, "Parts") self.assertEqual(len(parts['4=TestSubmission-testdir'].keys()), 13, "File stats for 4=TestSubmission-testdir") @@ -2556,52 +3245,53 @@ def testUpdateUnpackedDataset(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),22,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),17,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') + self.failUnless((subj,URIRef(oxds+"embargoedUntil"),d2) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') - self.failUnless((subj,URIRef(dcterms+"title"),"Test dataset with merged metadata") in rdfgraph, 'dcterms:title') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') self.failUnless((subj,URIRef(dcterms+"isVersionOf"),None) in rdfgraph, 'dcterms:isVersionOf') - self.failUnless((subj,URIRef(owl+"sameAs"),URIRef("http://example.org/testdir2/")) in rdfgraph, 'owl:sameAs') - self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"directory1")) in rdfgraph) - self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"directory1/file1.a")) in rdfgraph) - self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"directory1/file1.b")) in rdfgraph) - self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"directory1/file1.c")) in rdfgraph) - self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"directory2")) in rdfgraph) - self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"directory2/file2.a")) in rdfgraph) - self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"directory2/file2.b")) in rdfgraph) + self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"directory")) in rdfgraph) + self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"directory/file1.a")) in rdfgraph) + self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"directory/file1.b")) in rdfgraph) + self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"directory/file2.a")) in rdfgraph) self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"test-csv.csv")) in rdfgraph) self.failUnless((subj,URIRef(oxds+"currentVersion"),"2") in rdfgraph, 'oxds:currentVersion') - #Access state information of TestSubmission-testdir version 2 + #Access state information of TestSubmission-testdir version 3 (resp, data) = self.doHTTP_GET( - resource="states/TestSubmission-testdir/version2", + resource="states/TestSubmission-testdir/version3", expect_status=200, expect_reason="OK", expect_type="application/json") state = data['state'] parts = data['parts'] + self.assertEqual(state['metadata']['embargoed'], True, "Embargoed?") + self.assertEqual(state['metadata']['embargoed_until'], d2, "embargoed_until?") self.assertEqual(len(state.keys()), 11, "States") self.assertEqual(state['item_id'], "TestSubmission-testdir", "Submission item identifier") - self.assertEqual(len(state['versions']), 3, "Three versions") + self.assertEqual(len(state['versions']), 4, "Four versions") self.assertEqual(state['versions'][0], '0', "Version 0") self.assertEqual(state['versions'][1], '1', "Version 1") self.assertEqual(state['versions'][2], '2', "Version 2") - self.assertEqual(state['currentversion'], '2', "Current version == 2") + self.assertEqual(state['versions'][3], '3', "Version 3") + self.assertEqual(state['currentversion'], '3', "Current version == 3") self.assertEqual(state['rdffileformat'], 'xml', "RDF file type") self.assertEqual(state['rdffilename'], 'manifest.rdf', "RDF file name") self.assertEqual(len(state['files']['0']), 1, "List should contain just manifest.rdf") self.assertEqual(len(state['files']['1']), 3, "List should contain manifest.rdf, directory and test-csv.csv") - self.assertEqual(len(state['files']['2']), 4, "List should contain manifest.rdf, directory1, directory2 and test-csv.csv") + self.assertEqual(len(state['files']['2']), 3, "List should contain manifest.rdf, directory and test-csv.csv") + self.assertEqual(len(state['files']['3']), 4, "List should contain manifest.rdf, directory1, directory2 and test-csv.csv") self.assertEqual(len(state['metadata_files']['0']), 0, "metadata_files of version 0") self.assertEqual(len(state['metadata_files']['1']), 0, "metadata_files of version 1") self.assertEqual(len(state['metadata_files']['2']), 0, "metadata_files of version 2") + self.assertEqual(len(state['metadata_files']['3']), 0, "metadata_files of version 3") self.assertEqual(state['subdir']['0'], [], "Subdirectory count for version 0") self.assertEqual(state['subdir']['1'], ['directory'], "Subdirectory for version 1") - self.assertEqual(len(state['subdir']['2']), 2, "Subdirectory for version 2 should be directory1 and directory2") + self.assertEqual(state['subdir']['2'], ['directory'], "Subdirectory for version 2") + self.assertEqual(len(state['subdir']['3']), 2, "Subdirectory for version 2 should be directory1 and directory2") self.assertEqual(state['metadata']['createdby'], RDFDatabankConfig.endpointuser, "Created by") self.assertEqual(state['metadata']['embargoed'], True, "Embargoed?") self.assertEqual(len(parts.keys()), 6, "Parts") @@ -2668,7 +3358,7 @@ def testMetadataMerging(self): ore = "http://www.openarchives.org/ore/terms/" oxds = "http://vocab.ox.ac.uk/dataset/schema#" stype = URIRef(oxds+"DataSet") - self.assertEqual(len(rdfgraph),13,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"testrdf.zip")) in rdfgraph) @@ -2678,7 +3368,6 @@ def testMetadataMerging(self): self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(oxds+"currentVersion"),'1') in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') # Access and check list of contents in child dataset - TestSubmission-testrdf @@ -2694,7 +3383,7 @@ def testMetadataMerging(self): base = self.getRequestUri("datasets/TestSubmission-testrdf/") owl = "http://www.w3.org/2002/07/owl#" stype = URIRef(oxds+"Grouping") - self.assertEqual(len(rdfgraph),21,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),20,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(owl+"sameAs"),URIRef("http://example.org/testrdf/")) in rdfgraph, 'owl:sameAs') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') @@ -2711,7 +3400,6 @@ def testMetadataMerging(self): self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(oxds+"currentVersion"),'1') in rdfgraph, 'oxds:currentVersion') #Get the file arabic.txt @@ -2787,7 +3475,7 @@ def testMetadataInDirectoryMerging(self): ore = "http://www.openarchives.org/ore/terms/" oxds = "http://vocab.ox.ac.uk/dataset/schema#" stype = URIRef(oxds+"DataSet") - self.assertEqual(len(rdfgraph),13,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"testrdf2.zip")) in rdfgraph) @@ -2796,8 +3484,7 @@ def testMetadataInDirectoryMerging(self): self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') self.failUnless((subj,URIRef(oxds+"currentVersion"),'1') in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') # Access and check list of contents in child dataset - TestSubmission-testrdf @@ -2811,7 +3498,7 @@ def testMetadataInDirectoryMerging(self): base = self.getRequestUri("datasets/TestSubmission-testrdf2/") owl = "http://www.w3.org/2002/07/owl#" stype = URIRef(oxds+"Grouping") - self.assertEqual(len(rdfgraph),20,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),19,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(owl+"sameAs"),URIRef("http://example.org/testrdf/")) in rdfgraph, 'owl:sameAs') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') @@ -2828,7 +3515,6 @@ def testMetadataInDirectoryMerging(self): self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(oxds+"currentVersion"),'1') in rdfgraph, 'oxds:currentVersion') # Delete the dataset TestSubmission-testrdf2 @@ -2890,7 +3576,7 @@ def testReferencedMetadataMerging(self): owl = "http://www.w3.org/2002/07/owl#" dc = "http://purl.org/dc/elements/1.1/" stype = URIRef(oxds+"DataSet") - self.assertEqual(len(rdfgraph),13,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"testrdf3.zip")) in rdfgraph) @@ -2899,8 +3585,7 @@ def testReferencedMetadataMerging(self): self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') self.failUnless((subj,URIRef(oxds+"currentVersion"),'1') in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') # Access and check list of contents in child dataset - TestSubmission-testrdf3 @@ -2913,11 +3598,11 @@ def testReferencedMetadataMerging(self): rdfgraph = Graph() rdfgraph.parse('response.xml', format='xml') subj = URIRef(self.getRequestUri("datasets/TestSubmission-testrdf3")) - subj2 = URIRef(self.getRequestUri("datasets/TestSubmission-testrdf3/directory/hebrew.txt")) + subj2 = URIRef(self.getRequestUri("datasets/TestSubmission-testrdf3/testrdf3/directory/hebrew.txt")) base = self.getRequestUri("datasets/TestSubmission-testrdf3/") stype = URIRef(oxds+"Grouping") stype2 = URIRef(oxds+"item") - self.assertEqual(len(rdfgraph),28,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),31,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') self.failUnless((subj,URIRef(dcterms+"isVersionOf"),None) in rdfgraph, 'dcterms:isVersionOf') @@ -2938,7 +3623,6 @@ def testReferencedMetadataMerging(self): self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(oxds+"currentVersion"),'1') in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(owl+"sameAs"),URIRef("http://example.org/2aFiles/")) in rdfgraph, 'owl:sameAs') @@ -2946,9 +3630,9 @@ def testReferencedMetadataMerging(self): self.failUnless((subj,URIRef(dc+"description"),"file1.b is another file") in rdfgraph, 'dc:description') self.failUnless((subj,URIRef(dc+"description"),"This is a archived test item 2a ") in rdfgraph, 'dc:description') - #self.failUnless((subj2,RDF.type,stype2) in rdfgraph, 'Testing submission type: '+subj2+", "+stype2) - #self.failUnless((subj2,URIRef(dcterms+"title"),"Hebrew text") in rdfgraph, 'dcterms:title') - #self.failUnless((subj2,URIRef(dcterms+"source"),"http://genizah.bodleian.ox.ac.uk/") in rdfgraph, 'dcterms:source') + self.failUnless((subj2,RDF.type,stype2) in rdfgraph, 'Testing submission type: %s, %s'%(subj2, stype2)) + self.failUnless((subj2,URIRef(dcterms+"title"),"Hebrew text") in rdfgraph, 'dcterms:title') + self.failUnless((subj2,URIRef(dcterms+"source"),"http://genizah.bodleian.ox.ac.uk/") in rdfgraph, 'dcterms:source') #Get the file hebrew.txt (resp, hebrew_data) = self.doHTTP_GET( resource="datasets/TestSubmission-testrdf3/testrdf3/directory/hebrew.txt", @@ -3011,7 +3695,7 @@ def testReferencedMetadataMerging2(self): ore = "http://www.openarchives.org/ore/terms/" oxds = "http://vocab.ox.ac.uk/dataset/schema#" stype = URIRef(oxds+"DataSet") - self.assertEqual(len(rdfgraph),13,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"testrdf4.zip")) in rdfgraph) @@ -3021,7 +3705,6 @@ def testReferencedMetadataMerging2(self): self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(oxds+"currentVersion"),'1') in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') # Access and check list of contents in child dataset - TestSubmission-testrdf3 @@ -3039,7 +3722,7 @@ def testReferencedMetadataMerging2(self): dc = "http://purl.org/dc/elements/1.1/" stype = URIRef(oxds+"Grouping") stype2 = URIRef(oxds+"item") - self.assertEqual(len(rdfgraph),29,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),28,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') self.failUnless((subj,URIRef(dcterms+"isVersionOf"),None) in rdfgraph, 'dcterms:isVersionOf') @@ -3057,7 +3740,6 @@ def testReferencedMetadataMerging2(self): self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(oxds+"currentVersion"),'1') in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(dc+"description"),"This is a archived test item 2a ") in rdfgraph, 'dc:description') @@ -3065,8 +3747,6 @@ def testReferencedMetadataMerging2(self): self.failUnless((subj,URIRef(dcterms+"title"),"Test item 2a") in rdfgraph, 'dcterms:title') #self.failUnless((subj,URIRef(owl+"sameAs"),URIRef("2aFiles")) in rdfgraph, 'dcterms:title') - for s, p, o in rdfgraph.triples((None, RDF.type, None)): - print s, p, o, type(o) self.failUnless((subj2,RDF.type,stype2) in rdfgraph, 'Testing submission type: %s, %s'%(str(subj2), str(stype2))) self.failUnless((subj2,URIRef(dc+"description"),"This is a archived test item 1a ") in rdfgraph, 'dc:description') self.failUnless((subj2,URIRef(dcterms+"title"),"Test item 1a") in rdfgraph, 'dcterms:title') @@ -3129,6 +3809,7 @@ def getTestSuite(select="unit"): , "testDeleteDataset" , "testDatasetNaming" , "testDatasetStateInformation" + , "testEmbargoOnCreation" , "testFileUpload" , "testFileDelete" , "testFileUpdate" diff --git a/rdfdatabank/tests/TestSubmission_load.py b/rdfdatabank/tests/TestSubmission_load.py new file mode 100644 index 0000000..ed95c56 --- /dev/null +++ b/rdfdatabank/tests/TestSubmission_load.py @@ -0,0 +1,319 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# $Id: $ +""" +Databank submission test cases + +$Rev: $ +""" +import os, os.path +from datetime import datetime, timedelta +import sys +import unittest +import logging +import httplib +import urllib +import codecs +try: + # Running Python 2.5 with simplejson? + import simplejson as json +except ImportError: + import json + +#My system is running rdflib version 2.4.2. So adding rdflib v3.0 to sys path +#rdflib_path = os.path.join(os.getcwd(), 'rdflib') +#sys.path.insert(0, rdflib_path) +#import rdflib +#from rdflib.namespace import RDF +#from rdflib.graph import Graph +#from rdflib.plugins.memory import Memory +#from rdflib import URIRef +#from rdflib import Literal +#rdflib.plugin.register('sparql',rdflib.query.Processor,'rdfextras.sparql.processor','Processor') +#rdflib.plugin.register('sparql', rdflib.query.Result, +# 'rdfextras.sparql.query', 'SPARQLQueryResult') + +from StringIO import StringIO + +from rdflib import RDF, URIRef, Literal +from rdflib.Graph import ConjunctiveGraph as Graph + +#from time import sleep +#import subprocess + +if __name__ == "__main__": + # For testing: + # add main library directory to python path if running stand-alone + sys.path.append("..") + +#from MiscLib import TestUtils +from testlib import TestUtils +from testlib import SparqlQueryTestCase + +#from RDFDatabankConfigProd import RDFDatabankConfig as RC +from RDFDatabankConfig import RDFDatabankConfig as RC + +RDFDatabankConfig = RC() +logger = logging.getLogger('TestSubmission') + +class TestSubmission(SparqlQueryTestCase.SparqlQueryTestCase): + """ + Test simple dataset submissions to RDFDatabank + """ + def setUp(self): + self.setRequestEndPoint( + endpointhost=RDFDatabankConfig.endpointhost, # Via SSH tunnel + endpointpath=RDFDatabankConfig.endpointpath) + self.setRequestUserPass( + endpointuser=RDFDatabankConfig.endpointuser, + endpointpass=RDFDatabankConfig.endpointpass) + self.setRequestUriRoot( + manifesturiroot=RDFDatabankConfig.granary_uri_root) + self.setRequestUserPass( + endpointuser=RDFDatabankConfig.endpointuser, + endpointpass=RDFDatabankConfig.endpointpass) + resp = self.doHTTP_DELETE( + resource="datasets/TestSubmission", + expect_status="*", expect_reason="*") + return + + def tearDown(self): + return + + # Create empty test submission dataset + def createSubmissionDataset(self, dataset_id='TestSubmission'): + # Create a new dataset, check response + fields = \ + [ ("id", dataset_id) + ] + files =[] + (reqtype, reqdata) = SparqlQueryTestCase.encode_multipart_formdata(fields, files) + (resp,respdata) = self.doHTTP_POST( + reqdata, reqtype, + resource="datasets/", + expect_status=201, expect_reason="Created") + LHobtained = resp.getheader('Content-Location', None) + LHexpected = "%sdatasets/%s"%(self._endpointpath, dataset_id) + self.assertEquals(LHobtained, LHexpected, 'Content-Location not correct') + return + + def uploadSubmissionZipfile(self, dataset_id='TestSubmission', file_to_upload="testdir.zip", filename=None): + # Submit ZIP file, check response + fields = [] + if filename: + fields = \ + [ ("filename", filename) + ] + else: + filename = file_to_upload + zipdata = open("testdata/%s"%file_to_upload).read() + files = \ + [ ("file", file_to_upload, zipdata, "application/zip") + ] + (reqtype, reqdata) = SparqlQueryTestCase.encode_multipart_formdata(fields, files) + (resp,respdata) = self.doHTTP_POST( + reqdata, reqtype, + resource="datasets/%s/"%dataset_id, + expect_status=201, expect_reason="Created") + LHobtained = resp.getheader('Content-Location', None) + LHexpected = "%sdatasets/%s/%s"%(self._endpointpath, dataset_id, filename) + self.assertEquals(LHobtained, LHexpected, 'Content-Location not correct') + return zipdata + + def updateSubmissionZipfile(self, dataset_id='TestSubmission', file_to_upload="testdir.zip", filename=None): + # Submit ZIP file, check response + fields = [] + if filename: + fields = \ + [ ("filename", filename) + ] + zipdata = open("testdata/%s"%file_to_upload).read() + files = \ + [ ("file", file_to_upload, zipdata, "application/zip") + ] + (reqtype, reqdata) = SparqlQueryTestCase.encode_multipart_formdata(fields, files) + (resp,respdata)= self.doHTTP_POST( + reqdata, reqtype, + resource="datasets/%s/"%dataset_id, + expect_status=204, expect_reason="No Content") + return zipdata + + # Actual tests follow + def test01CreateSilo(self): + """List all silos your account has access to - GET /admin. If the silo 'sandbox' does not exist, create it""" + self.setRequestUserPass( + endpointuser=RDFDatabankConfig.endpointadminuser, + endpointpass=RDFDatabankConfig.endpointadminpass) + # Access list silos, check response + (resp, data) = self.doHTTP_GET( + endpointpath="/", + resource="admin/", + expect_status=200, expect_reason="OK", expect_type="application/JSON") + silo_name = RDFDatabankConfig.endpointpath.strip('/') + silolist = data + if not silo_name in silolist: + #Create new silo + owner_list = [RDFDatabankConfig.endpointadminuser] + if not RDFDatabankConfig.endpointuser in owner_list: + owner_list.append(RDFDatabankConfig.endpointuser) + owner_list = ",".join(owner_list) + fields = \ + [ ("silo", silo_name), + ("title", "Sandbox silo"), + ("description", "Sandbox silo for testing"), + ("notes", "Created by test"), + ("owners", owner_list), + ("disk_allocation", "100000") + ] + files =[] + (reqtype, reqdata) = SparqlQueryTestCase.encode_multipart_formdata(fields, files) + (resp,respdata) = self.doHTTP_POST( + reqdata, reqtype, resource="admin/", endpointpath="/", + expect_status=201, expect_reason="Created") + LHobtained = resp.getheader('Content-Location', None) + LHexpected = "/%s"%silo_name + self.assertEquals(LHobtained, LHexpected, 'Content-Location not correct') + # Access list silos, check response + (resp, data) = self.doHTTP_GET( + endpointpath="/", + resource="admin/", + expect_status=200, expect_reason="OK", expect_type="application/json") + newsilolist = data + self.failUnless(len(newsilolist)>0, "No silos returned") + self.assertEquals(len(newsilolist), len(silolist)+1, "One additional silo should have been returned") + for s in silolist: self.failUnless(s in newsilolist, "Silo "+s+" in original list, not in new list") + self.failUnless(silo_name in newsilolist, "Silo '%s' not in new list"%silo_name) + return + + def testFileUploadBulk(self): + for i in range(0, 10000): + """Upload file to dataset - POST file to /silo_name/datasets/dataset_name""" + # Create a new dataset, check response + start = datetime.now() + dataset_id='TestSubmission%d'%i + f = open('test_times.log', 'a') + f.write('%s: Creating and uploading file to dataset %s \n'%(start.isoformat(), dataset_id)) + f.close() + self.createSubmissionDataset(dataset_id=dataset_id) + #Access state information + (resp, respdata) = self.doHTTP_GET( + resource="states/%s"%dataset_id, + expect_status=200, expect_reason="OK", expect_type="application/json") + # Upload zip file, check response + zipdata = self.uploadSubmissionZipfile(dataset_id=dataset_id, file_to_upload='rdfdatabank.zip', filename='testdir.zip') + end = datetime.now() + delta = end - start + time_used = delta.days * 86400 + delta.seconds + f = open('test_times.log', 'a') + f.write(' Time taken: %s \n\n'%str(time_used)) + f.close() + # Access and check list of contents + (resp, rdfdata) = self.doHTTP_GET( + resource="datasets/%s"%dataset_id, + expect_status=200, expect_reason="OK", expect_type="application/rdf+xml") + rdfgraph = Graph() + rdfstream = StringIO(rdfdata) + rdfgraph.parse(rdfstream) + subj = URIRef(self.getRequestUri("datasets/%s"%dataset_id)) + base = self.getRequestUri("datasets/%s/"%dataset_id) + dcterms = "http://purl.org/dc/terms/" + ore = "http://www.openarchives.org/ore/terms/" + oxds = "http://vocab.ox.ac.uk/dataset/schema#" + stype = URIRef(oxds+"DataSet") + self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) + self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) + self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') + self.failUnless((subj,URIRef(ore+"aggregates"),URIRef(base+"testdir.zip")) in rdfgraph) + self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') + self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') + self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') + self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') + self.failUnless((subj,URIRef(oxds+"currentVersion"),'1') in rdfgraph, 'oxds:currentVersion') + self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') + # Access and check zip file content + (resp, zipfile) = self.doHTTP_GET( + resource="datasets/%s/testdir.zip"%dataset_id, + expect_status=200, expect_reason="OK", expect_type="application/zip") + self.assertEqual(zipdata, zipfile, "Difference between local and remote zipfile!") + #Access state information and check + (resp, data) = self.doHTTP_GET( + resource="states/%s"%dataset_id, + expect_status=200, expect_reason="OK", expect_type="application/json") + state = data['state'] + parts = data['parts'] + self.assertEqual(len(state.keys()), 11, "States") + self.assertEqual(state['item_id'], dataset_id, "Submission item identifier") + self.assertEqual(len(state['versions']), 2, "Two versions") + self.assertEqual(state['versions'][0], '0', "Version 0") + self.assertEqual(state['versions'][1], '1', "Version 1") + self.assertEqual(state['currentversion'], '1', "Current version == 1") + self.assertEqual(state['rdffileformat'], 'xml', "RDF file type") + self.assertEqual(state['rdffilename'], 'manifest.rdf', "RDF file name") + self.assertEqual(state['files']['0'], ['manifest.rdf'], "List should contain just manifest.rdf") + self.assertEqual(len(state['files']['1']), 2, "List should contain manifest.rdf and testdir.zip") + self.assertEqual(len(state['metadata_files']['0']), 0, "metadata_files of version 0") + self.assertEqual(len(state['metadata_files']['1']), 0, "metadata_files of version 1") + self.assertEqual(len(state['subdir']['0']), 0, "Subdirectory count for version 0") + self.assertEqual(len(state['subdir']['1']), 0, "Subdirectory count for version 1") + self.assertEqual(state['metadata']['createdby'], RDFDatabankConfig.endpointuser, "Created by") + self.assertEqual(state['metadata']['embargoed'], True, "Embargoed?") + self.assertEqual(state['metadata']['embargoed_until'], '', "Embargoed until?") + self.assertEqual(len(parts.keys()), 4, "Parts") + self.assertEqual(len(parts['4=%s'%dataset_id].keys()), 13, "File stats for 4=%s"%dataset_id) + self.assertEqual(len(parts['manifest.rdf'].keys()), 13, "File stats for manifest.rdf") + self.assertEqual(len(parts['testdir.zip'].keys()), 13, "File stats for testdir.zip") + + # Sentinel/placeholder tests + + def testUnits(self): + assert (True) + + def testComponents(self): + assert (True) + + def testIntegration(self): + assert (True) + + def testPending(self): + #Need to have performance tests and analyse performance + #Need to set the permission of file being uploaded + #assert (False), "Pending tests follow" + assert (True) + +# Assemble test suite + +def getTestSuite(select="unit"): + """ + Get test suite + + select is one of the following: + "unit" return suite of unit tests only + "component" return suite of unit and component tests + "all" return suite of unit, component and integration tests + "pending" return suite of pending tests + name a single named test to be run + """ + testdict = { + "unit": + [ "testUnits" + , "test01CreateSilo" + , "testFileUploadBulk" + ], + "component": + [ "testComponents" + ], + "integration": + [ "testIntegration" + ], + "pending": + [ "testPending" + ] + } + return TestUtils.getTestSuite(TestSubmission, testdict, select=select) + +if __name__ == "__main__": + TestUtils.runTests("TestSubmission.log", getTestSuite, sys.argv) + +# End. diff --git a/rdfdatabank/tests/TestSubmission_submitter.py b/rdfdatabank/tests/TestSubmission_submitter.py index 0ab35cd..8f55124 100644 --- a/rdfdatabank/tests/TestSubmission_submitter.py +++ b/rdfdatabank/tests/TestSubmission_submitter.py @@ -10,6 +10,7 @@ """ import os, os.path import datetime +from dateutil.relativedelta import * import sys import unittest import logging @@ -42,6 +43,7 @@ from testlib import SparqlQueryTestCase from RDFDatabankConfig import RDFDatabankConfig +#from RDFDatabankConfigProd import RDFDatabankConfig logger = logging.getLogger('TestSubmission') @@ -71,9 +73,12 @@ def tearDown(self): # Create empty test submission dataset def createSubmissionDataset(self): + d = (datetime.datetime.now() + datetime.timedelta(days=365*4)).isoformat() # Create a new dataset, check response fields = \ - [ ("id", "TestSubmission") + [ ("id", "TestSubmission"), + ('embargoed', 'True'), + ('embargoed_until', d) ] files =[] (reqtype, reqdata) = SparqlQueryTestCase.encode_multipart_formdata(fields, files) @@ -84,7 +89,7 @@ def createSubmissionDataset(self): LHobtained = resp.getheader('Content-Location', None) LHexpected = "%sdatasets/TestSubmission"%self._endpointpath self.assertEquals(LHobtained, LHexpected, 'Content-Location not correct') - return + return d def uploadSubmissionZipfile(self, file_to_upload="testdir.zip"): # Submit ZIP file, check response @@ -680,7 +685,7 @@ def testDatasetNotPresent(self): def testDatasetCreation(self): """Create dataset - POST id to /silo_name""" # Create a new dataset as submitter, check response - self.createSubmissionDataset() + d = self.createSubmissionDataset() # Access dataset, check response (resp, rdfdata) = self.doHTTP_GET( resource="datasets/TestSubmission", @@ -700,8 +705,8 @@ def testDatasetCreation(self): self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"license"),None) in rdfgraph, 'dcterms:license') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') + self.failUnless((subj,URIRef(oxds+"embargoedUntil"),d) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(oxds+"currentVersion"),'0') in rdfgraph, 'oxds:currentVersion') #Admin user of this silo - Create a new dataset, check response @@ -731,7 +736,7 @@ def testDatasetCreation(self): rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) subj = URIRef(self.getRequestUri("datasets/TestSubmission2")) - self.assertEqual(len(rdfgraph), 10,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph), 9,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,URIRef(dcterms+"mediator"),RDFDatabankConfig.endpointadminuser) in rdfgraph, 'dcterms:mediator') #manager user of this silo - Create a new dataset, check response @@ -761,7 +766,7 @@ def testDatasetCreation(self): rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) subj = URIRef(self.getRequestUri("datasets/TestSubmission3")) - self.assertEqual(len(rdfgraph),10,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),9,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,URIRef(dcterms+"mediator"),RDFDatabankConfig.endpointmanageruser) in rdfgraph, 'dcterms:mediator') #General user - Create a new dataset, check response @@ -882,7 +887,7 @@ def testDatasetCreation2(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),10,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),9,'Graph length %i' %len(rdfgraph)) oxds = "http://vocab.ox.ac.uk/dataset/schema#" dcterms = "http://purl.org/dc/terms/" subj = URIRef(self.getRequestUri("datasets/TestSubmission")) @@ -894,16 +899,17 @@ def testDatasetCreation2(self): self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"license"),None) in rdfgraph, 'dcterms:license') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') self.failUnless((subj,URIRef(oxds+"currentVersion"),'0') in rdfgraph, 'oxds:currentVersion') - #Admin user of this silo - Create a new dataset, check response self.setRequestUserPass( endpointuser=RDFDatabankConfig.endpointadminuser, endpointpass=RDFDatabankConfig.endpointadminpass) + d = (datetime.datetime.now() + datetime.timedelta(days=365*4)).isoformat() fields = \ - [ ("id", "TestSubmission2") + [ ("id", "TestSubmission2"), + ('embargoed', 'True'), + ('embargoed_until', d) ] files =[] (reqtype, reqdata) = SparqlQueryTestCase.encode_multipart_formdata(fields, files) @@ -933,7 +939,9 @@ def testDatasetCreation2(self): endpointuser=RDFDatabankConfig.endpointmanageruser, endpointpass=RDFDatabankConfig.endpointmanagerpass) fields = \ - [ ("id", "TestSubmission3") + [ ("id", "TestSubmission3"), + ('embargoed', 'True'), + ('embargoed_until', d) ] files =[] (reqtype, reqdata) = SparqlQueryTestCase.encode_multipart_formdata(fields, files) @@ -1421,7 +1429,7 @@ def testDatasetNaming(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),10,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),9,'Graph length %i' %len(rdfgraph)) elif status == 403 or status == 400: (resp, respdata) = self.doHTTP_GET( resource="datasets/%s"%name, @@ -1439,7 +1447,7 @@ def testDatasetNaming(self): def testDatasetStateInformation(self): """Get state information of dataset - GET /silo_name/states/dataset_name.""" # Create a new dataset by submitter, check response - self.createSubmissionDataset() + d = self.createSubmissionDataset() # Access state info (resp, data) = self.doHTTP_GET( resource="states/TestSubmission", @@ -1458,6 +1466,7 @@ def testDatasetStateInformation(self): self.assertEqual(len(state['subdir']['0']), 0, "Subdirectory count for version 0") self.assertEqual(state['metadata']['createdby'], RDFDatabankConfig.endpointsubmitteruser, "Created by") self.assertEqual(state['metadata']['embargoed'], True, "Embargoed?") + self.assertEqual(state['metadata']['embargoed_until'], d, "Embargoed until?") # date # version_dates self.assertEqual(len(parts.keys()), 3, "Parts") @@ -1529,7 +1538,7 @@ def testDatasetStateInformation(self): def testFileUpload(self): """Upload file to dataset - POST file to /silo_name/datasets/dataset_name""" # Create a new dataset, check response - self.createSubmissionDataset() + d = self.createSubmissionDataset() #Access state information (resp, respdata) = self.doHTTP_GET( resource="states/TestSubmission", @@ -1558,8 +1567,8 @@ def testFileUpload(self): self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"license"),None) in rdfgraph, 'dcterms:license') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') + self.failUnless((subj,URIRef(oxds+"embargoedUntil"),d) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(oxds+"currentVersion"),'1') in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') # Access and check zip file content @@ -1741,7 +1750,7 @@ def testFileUpload(self): def testFileDelete(self): """Delete file in dataset - DELETE /silo_name/datasets/dataset_name/file_name""" # Create a new dataset, check response - self.createSubmissionDataset() + d = self.createSubmissionDataset() # Upload zip file, check response zipdata = self.uploadSubmissionZipfile() # Access and check list of contents @@ -1788,8 +1797,8 @@ def testFileDelete(self): self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"license"),None) in rdfgraph, 'dcterms:license') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') + self.failUnless((subj,URIRef(oxds+"embargoedUntil"),d) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(oxds+"currentVersion"),'2') in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') #Access state information and check @@ -1954,7 +1963,7 @@ def testFileDelete(self): def testFileUpdate(self): """Update file in dataset - POST file to /silo_name/datasets/dataset_name (x 2)""" # Create a new dataset, check response - self.createSubmissionDataset() + d = self.createSubmissionDataset() # Upload zip file, check response (uploads the file testdir.zip) zipdata = self.uploadSubmissionZipfile() # Access and check list of contents @@ -1997,8 +2006,8 @@ def testFileUpdate(self): self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"license"),None) in rdfgraph, 'dcterms:license') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') + self.failUnless((subj,URIRef(oxds+"embargoedUntil"),d) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(oxds+"currentVersion"),'2') in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') # Access and check zip file content @@ -2191,7 +2200,7 @@ def testGetDatasetByVersionByURI(self): stype = URIRef(oxds+"DataSet") #---------Version 0 # Create a new dataset, check response - self.createSubmissionDataset() + d = self.createSubmissionDataset() # Access and check list of contents (resp, rdfdata) = self.doHTTP_GET( resource="datasets/TestSubmission", @@ -2341,8 +2350,8 @@ def testGetDatasetByVersionByURI(self): self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"license"),None) in rdfgraph, 'dcterms:license') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') + self.failUnless((subj,URIRef(oxds+"embargoedUntil"),d) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(oxds+"currentVersion"),'0') in rdfgraph, 'oxds:currentVersion') #Access state information and check (resp, data) = self.doHTTP_GET( @@ -2371,8 +2380,8 @@ def testGetDatasetByVersionByURI(self): self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"license"),None) in rdfgraph, 'dcterms:license') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') + self.failUnless((subj,URIRef(oxds+"embargoedUntil"),d) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(oxds+"currentVersion"),'1') in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') # Access and check zip file content @@ -2409,8 +2418,8 @@ def testGetDatasetByVersionByURI(self): self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"license"),None) in rdfgraph, 'dcterms:license') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') + self.failUnless((subj,URIRef(oxds+"embargoedUntil"),d) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(oxds+"currentVersion"),'2') in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') # Access and check zip file content @@ -4893,7 +4902,19 @@ def testUnicodeMetadataFileUpdate(self): def testChangeEmbargo(self): """Change embargo information - POST embargo_change to /silo_name/datasets/dataset_name""" # Create a new dataset, check response - self.createSubmissionDataset() + #self.createSubmissionDataset() + fields = \ + [ ("id", "TestSubmission") + ] + files =[] + (reqtype, reqdata) = SparqlQueryTestCase.encode_multipart_formdata(fields, files) + (resp,respdata) = self.doHTTP_POST( + reqdata, reqtype, + resource="datasets/", + expect_status=201, expect_reason="Created") + LHobtained = resp.getheader('Content-Location', None) + LHexpected = "%sdatasets/TestSubmission"%self._endpointpath + self.assertEquals(LHobtained, LHexpected, 'Content-Location not correct') #Access dataset and check content (resp, rdfdata) = self.doHTTP_GET( resource="datasets/TestSubmission", @@ -4901,7 +4922,7 @@ def testChangeEmbargo(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),10,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),9,'Graph length %i' %len(rdfgraph)) oxds = "http://vocab.ox.ac.uk/dataset/schema#" dcterms = "http://purl.org/dc/terms/" subj = URIRef(self.getRequestUri("datasets/TestSubmission")) @@ -4910,15 +4931,13 @@ def testChangeEmbargo(self): base = self.getRequestUri("datasets/TestSubmission/") self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') #Access state information and check (resp, data) = self.doHTTP_GET( resource="states/TestSubmission", expect_status=200, expect_reason="OK", expect_type="application/json") - embargoed_until_date = (datetime.date.today() + datetime.timedelta(days=365*70)).isoformat() state = data['state'] self.assertEqual(state['metadata']['embargoed'], True, "Embargoed?") - self.failUnless(embargoed_until_date in state['metadata']['embargoed_until'], "Default 70 year embargo failed") + self.assertEqual(state['metadata']['embargoed_until'], '', "embargoed_until indefinite - default embargo failed") # Upload zip file, check response zipdata = self.uploadSubmissionZipfile(file_to_upload="testdir.zip") #Access dataset and check content @@ -4928,10 +4947,9 @@ def testChangeEmbargo(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') @@ -4956,7 +4974,7 @@ def testChangeEmbargo(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) (resp, zipfile) = self.doHTTP_GET( resource="datasets/TestSubmission/testdir.zip", expect_status=200, expect_reason="OK", expect_type="application/zip") @@ -4971,7 +4989,7 @@ def testChangeEmbargo(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) (resp, zipfile) = self.doHTTP_GET( resource="datasets/TestSubmission/testdir.zip", expect_status=200, expect_reason="OK", expect_type="application/zip") @@ -4986,7 +5004,7 @@ def testChangeEmbargo(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) (resp, zipfile) = self.doHTTP_GET( resource="datasets/TestSubmission/testdir.zip", expect_status=403, expect_reason="Forbidden", expect_type="application/zip") @@ -5000,7 +5018,7 @@ def testChangeEmbargo(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) (resp, zipfile) = self.doHTTP_GET( resource="datasets/TestSubmission/testdir.zip", expect_status=302, expect_reason="Found", expect_type="application/zip") @@ -5016,7 +5034,7 @@ def testChangeEmbargo(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) (resp, zipfile) = self.doHTTP_GET( resource="datasets/TestSubmission/testdir.zip", expect_status=403, expect_reason="Forbidden", expect_type="application/zip") @@ -5030,7 +5048,7 @@ def testChangeEmbargo(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) (resp, zipfile) = self.doHTTP_GET( resource="datasets/TestSubmission/testdir.zip", expect_status=403, expect_reason="Forbidden", expect_type="application/zip") @@ -5044,12 +5062,13 @@ def testChangeEmbargo(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) (resp, zipfile) = self.doHTTP_GET( resource="datasets/TestSubmission/testdir.zip", expect_status=403, expect_reason="Forbidden", expect_type="application/zip") # Delete embargo, check response + embargoed_until_date = datetime.datetime.now().isoformat() self.setRequestUserPass( endpointuser=RDFDatabankConfig.endpointsubmitteruser, endpointpass=RDFDatabankConfig.endpointsubmitterpass) @@ -5209,10 +5228,10 @@ def testChangeEmbargo(self): self.setRequestUserPass( endpointuser=RDFDatabankConfig.endpointadminuser, endpointpass=RDFDatabankConfig.endpointadminpass) - d = (datetime.datetime.now() + datetime.timedelta(days=365*10)).isoformat() + d1 = (datetime.datetime.now() + datetime.timedelta(days=365*10)).isoformat() fields = \ [ ("embargoed", 'true') - ,("embargoed_until", d) + ,("embargoed_until", d1) ] files =[] (reqtype, reqdata) = SparqlQueryTestCase.encode_multipart_formdata(fields, files) @@ -5241,7 +5260,7 @@ def testChangeEmbargo(self): expect_status=200, expect_reason="OK", expect_type="application/json") state = data['state'] self.assertEqual(state['metadata']['embargoed'], True, "Embargoed?") - self.failUnless(d in state['metadata']['embargoed_until'], "embargoed_until date?") + self.failUnless(d1 in state['metadata']['embargoed_until'], "embargoed_until date?") # Access and check zip file content (resp, zipfile) = self.doHTTP_GET( resource="datasets/TestSubmission/testdir.zip", @@ -5859,14 +5878,13 @@ def testChangeEmbargo(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) oxds = "http://vocab.ox.ac.uk/dataset/schema#" dcterms = "http://purl.org/dc/terms/" subj = URIRef(self.getRequestUri("datasets/TestSubmission")) stype = URIRef(oxds+"DataSet") self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') @@ -5882,7 +5900,7 @@ def testChangeEmbargo(self): expect_status=200, expect_reason="OK", expect_type="application/json") state = data['state'] self.assertEqual(state['metadata']['embargoed'], True, "Embargoed?") - self.failUnless(embargoed_until_date in state['metadata']['embargoed_until'], "Updating embargoed_until date") + self.assertEqual(state['metadata']['embargoed_until'], '', "Embargoed?") # Access and check zip file content by submitter (resp, zipfile) = self.doHTTP_GET( resource="datasets/TestSubmission/testdir.zip", @@ -5898,7 +5916,7 @@ def testChangeEmbargo(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) (resp, zipfile) = self.doHTTP_GET( resource="datasets/TestSubmission/testdir.zip", expect_status=200, expect_reason="OK", expect_type="application/zip") @@ -5913,7 +5931,7 @@ def testChangeEmbargo(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) (resp, zipfile) = self.doHTTP_GET( resource="datasets/TestSubmission/testdir.zip", expect_status=200, expect_reason="OK", expect_type="application/zip") @@ -5928,7 +5946,7 @@ def testChangeEmbargo(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) (resp, zipfile) = self.doHTTP_GET( resource="datasets/TestSubmission/testdir.zip", expect_status=403, expect_reason="Forbidden", expect_type="application/zip") @@ -5942,7 +5960,7 @@ def testChangeEmbargo(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) (resp, zipfile) = self.doHTTP_GET( resource="datasets/TestSubmission/testdir.zip", expect_status=302, expect_reason="Found", expect_type="application/zip") @@ -5958,7 +5976,7 @@ def testChangeEmbargo(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) (resp, zipfile) = self.doHTTP_GET( resource="datasets/TestSubmission/testdir.zip", expect_status=403, expect_reason="Forbidden", expect_type="application/zip") @@ -5972,7 +5990,7 @@ def testChangeEmbargo(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) (resp, zipfile) = self.doHTTP_GET( resource="datasets/TestSubmission/testdir.zip", expect_status=403, expect_reason="Forbidden", expect_type="application/zip") @@ -5986,7 +6004,7 @@ def testChangeEmbargo(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),12,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),11,'Graph length %i' %len(rdfgraph)) (resp, zipfile) = self.doHTTP_GET( resource="datasets/TestSubmission/testdir.zip", expect_status=403, expect_reason="Forbidden", expect_type="application/zip") @@ -6045,8 +6063,8 @@ def testFileUnpack(self): self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"license"),None) in rdfgraph, 'dcterms:license') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') + self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:isEmbargoed') self.failUnless((subj,URIRef(oxds+"currentVersion"),"4") in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') self.failUnless((URIRef(base+"testdir.zip"),URIRef(dcterms+"hasVersion"),subj2) in rdfgraph, 'ore:aggregates testrdf.zip') @@ -6060,15 +6078,14 @@ def testFileUnpack(self): subj = URIRef(self.getRequestUri("datasets/TestSubmission-testdir")) stype = URIRef("http://vocab.ox.ac.uk/dataset/schema#Grouping") base = self.getRequestUri("datasets/TestSubmission-testdir/") - self.assertEqual(len(rdfgraph),17,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),16,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"license"),None) in rdfgraph, 'dcterms:license') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') self.failUnless((subj,URIRef(dcterms+"isVersionOf"),None) in rdfgraph, 'dcterms:isVersionOf') @@ -6106,6 +6123,7 @@ def testFileUnpack(self): self.assertEqual(state['subdir']['1'], ['directory'], "Subdirectory for version 1") self.assertEqual(state['metadata']['createdby'], RDFDatabankConfig.endpointsubmitteruser, "Created by") self.assertEqual(state['metadata']['embargoed'], True, "Embargoed?") + self.assertEqual(state['metadata']['embargoed_until'], '', "Embargoed?") self.assertEqual(len(parts.keys()), 5, "Parts") self.assertEqual(len(parts['4=TestSubmission-testdir'].keys()), 13, "File stats for 4=TestSubmission-testdir") self.assertEqual(len(parts['manifest.rdf'].keys()), 13, "File stats for manifest.rdf") @@ -6153,15 +6171,14 @@ def testFileUnpack(self): stype = URIRef("http://vocab.ox.ac.uk/dataset/schema#Grouping") base = self.getRequestUri("datasets/TestSubmission-testdir2/") owl = "http://www.w3.org/2002/07/owl#" - self.assertEqual(len(rdfgraph),22,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),21,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"license"),None) in rdfgraph, 'dcterms:license') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') self.failUnless((subj,URIRef(dcterms+"isVersionOf"),None) in rdfgraph, 'dcterms:isVersionOf') @@ -6210,15 +6227,14 @@ def testFileUnpack(self): stype = URIRef("http://vocab.ox.ac.uk/dataset/schema#Grouping") base = self.getRequestUri("datasets/TestSubmission-testdir2/") owl = "http://www.w3.org/2002/07/owl#" - self.assertEqual(len(rdfgraph),22,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),21,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"license"),None) in rdfgraph, 'dcterms:license') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') self.failUnless((subj,URIRef(dcterms+"isVersionOf"),None) in rdfgraph, 'dcterms:isVersionOf') @@ -6278,15 +6294,14 @@ def testFileUnpack(self): subj = URIRef(self.getRequestUri("datasets/TestSubmission-testrdf")) stype = URIRef("http://vocab.ox.ac.uk/dataset/schema#Grouping") base = self.getRequestUri("datasets/TestSubmission-testrdf/") - self.assertEqual(len(rdfgraph),21,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),20,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"license"),None) in rdfgraph, 'dcterms:license') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') self.failUnless((subj,URIRef(dcterms+"isVersionOf"),None) in rdfgraph, 'dcterms:isVersionOf') @@ -6337,15 +6352,14 @@ def testFileUnpack(self): subj = URIRef(self.getRequestUri("datasets/TestSubmission-testrdf")) stype = URIRef("http://vocab.ox.ac.uk/dataset/schema#Grouping") base = self.getRequestUri("datasets/TestSubmission-testrdf/") - self.assertEqual(len(rdfgraph),21,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),20,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"license"),None) in rdfgraph, 'dcterms:license') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') self.failUnless((subj,URIRef(dcterms+"isVersionOf"),None) in rdfgraph, 'dcterms:isVersionOf') @@ -6616,15 +6630,14 @@ def testSymlinkFileUnpack(self): subj = URIRef(self.getRequestUri("datasets/TestSubmission-testdir")) stype = URIRef("http://vocab.ox.ac.uk/dataset/schema#Grouping") base = self.getRequestUri("datasets/TestSubmission-testdir/") - self.assertEqual(len(rdfgraph),17,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),16,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"license"),None) in rdfgraph, 'dcterms:license') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') self.failUnless((subj,URIRef(dcterms+"isVersionOf"),None) in rdfgraph, 'dcterms:isVersionOf') @@ -6662,6 +6675,7 @@ def testSymlinkFileUnpack(self): self.assertEqual(state['subdir']['1'], ['directory'], "Subdirectory for version 1") self.assertEqual(state['metadata']['createdby'], RDFDatabankConfig.endpointsubmitteruser, "Created by") self.assertEqual(state['metadata']['embargoed'], True, "Embargoed?") + self.assertEqual(state['metadata']['embargoed_until'], '', "Embargoed until?") self.assertEqual(len(parts.keys()), 5, "Parts") self.assertEqual(len(parts['4=TestSubmission-testdir'].keys()), 13, "File stats for 4=TestSubmission-testdir") self.assertEqual(len(parts['manifest.rdf'].keys()), 13, "File stats for manifest.rdf") @@ -6714,15 +6728,14 @@ def testFileUploadToUnpackedDataset(self): dcterms = "http://purl.org/dc/terms/" ore = "http://www.openarchives.org/ore/terms/" oxds = "http://vocab.ox.ac.uk/dataset/schema#" - self.assertEqual(len(rdfgraph),17,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),16,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"license"),None) in rdfgraph, 'dcterms:license') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') self.failUnless((subj,URIRef(dcterms+"isVersionOf"),None) in rdfgraph, 'dcterms:isVersionOf') @@ -6758,15 +6771,14 @@ def testFileUploadToUnpackedDataset(self): subj = URIRef(self.getRequestUri("datasets/TestSubmission-testdir")) stype = URIRef("http://vocab.ox.ac.uk/dataset/schema#Grouping") base = self.getRequestUri("datasets/TestSubmission-testdir/") - self.assertEqual(len(rdfgraph),18,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),17,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"license"),None) in rdfgraph, 'dcterms:license') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') self.failUnless((subj,URIRef(dcterms+"isVersionOf"),None) in rdfgraph, 'dcterms:isVersionOf') @@ -6803,6 +6815,7 @@ def testFileUploadToUnpackedDataset(self): self.assertEqual(state['subdir']['2'], ['directory'], "Subdirectory for version 2") self.assertEqual(state['metadata']['createdby'], RDFDatabankConfig.endpointsubmitteruser, "Created by") self.assertEqual(state['metadata']['embargoed'], True, "Embargoed?") + self.assertEqual(state['metadata']['embargoed_until'], '', "Embargoed until?") self.assertEqual(len(parts.keys()), 6, "Parts") self.assertEqual(len(parts['4=TestSubmission-testdir'].keys()), 13, "File stats for 4=TestSubmission-testdir") self.assertEqual(len(parts['manifest.rdf'].keys()), 13, "File stats for manifest.rdf") @@ -7016,15 +7029,14 @@ def testUpdateUnpackedDataset(self): dcterms = "http://purl.org/dc/terms/" ore = "http://www.openarchives.org/ore/terms/" oxds = "http://vocab.ox.ac.uk/dataset/schema#" - self.assertEqual(len(rdfgraph),17,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),16,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"license"),None) in rdfgraph, 'dcterms:license') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') self.failUnless((subj,URIRef(dcterms+"isVersionOf"),None) in rdfgraph, 'dcterms:isVersionOf') @@ -7093,7 +7105,7 @@ def testUpdateUnpackedDataset(self): base = self.getRequestUri("datasets/TestSubmission-testdir/") owl = "http://www.w3.org/2002/07/owl#" dc = "http://purl.org/dc/elements/1.1/" - self.assertEqual(len(rdfgraph),29,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),28,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') self.failUnless((subj,URIRef(dcterms+"isVersionOf"),None) in rdfgraph, 'dcterms:isVersionOf') @@ -7111,8 +7123,7 @@ def testUpdateUnpackedDataset(self): self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"license"),None) in rdfgraph, 'dcterms:license') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dc+"description"),"This is a archived test item 2a ") in rdfgraph, 'dc:description') #self.failUnless((subj,URIRef(dcterms+"title"),"Test dataset 4 with updated and merged metadata") in rdfgraph, 'dcterms:title') @@ -7152,6 +7163,7 @@ def testUpdateUnpackedDataset(self): self.assertEqual(state['subdir']['2'], ['testrdf4'], "Subdirectory for version 2 should be directory") self.assertEqual(state['metadata']['createdby'], RDFDatabankConfig.endpointsubmitteruser, "Created by") self.assertEqual(state['metadata']['embargoed'], True, "Embargoed?") + self.assertEqual(state['metadata']['embargoed_until'], '', "Embargoed until?") self.assertEqual(len(parts.keys()), 4, "Parts") self.assertEqual(len(parts['4=TestSubmission-testdir'].keys()), 13, "File stats for 4=TestSubmission-testdir") self.assertEqual(len(parts['manifest.rdf'].keys()), 13, "File stats for manifest.rdf") @@ -7215,7 +7227,7 @@ def testUpdateUnpackedDataset(self): stype = URIRef("http://vocab.ox.ac.uk/dataset/schema#Grouping") base = self.getRequestUri("datasets/TestSubmission-testdir/") owl = "http://www.w3.org/2002/07/owl#" - self.assertEqual(len(rdfgraph),22,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),21,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') @@ -7223,7 +7235,6 @@ def testUpdateUnpackedDataset(self): self.failUnless((subj,URIRef(dcterms+"license"),None) in rdfgraph, 'dcterms:license') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') self.failUnless((subj,URIRef(dcterms+"isVersionOf"),None) in rdfgraph, 'dcterms:isVersionOf') @@ -7285,7 +7296,7 @@ def testUpdateUnpackedDataset(self): subj = URIRef(self.getRequestUri("datasets/TestSubmission-testdir")) stype = URIRef("http://vocab.ox.ac.uk/dataset/schema#Grouping") base = self.getRequestUri("datasets/TestSubmission-testdir/") - self.assertEqual(len(rdfgraph),21,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),20,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') @@ -7293,7 +7304,6 @@ def testUpdateUnpackedDataset(self): self.failUnless((subj,URIRef(dcterms+"license"),None) in rdfgraph, 'dcterms:license') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') self.failUnless((subj,URIRef(dcterms+"isVersionOf"),None) in rdfgraph, 'dcterms:isVersionOf') @@ -7502,7 +7512,7 @@ def testUpdateUnpackedDataset(self): stype2 = URIRef(oxds+"Grouping") subj = URIRef(self.getRequestUri("datasets/TestSubmission-testdir")) base = self.getRequestUri("datasets/TestSubmission-testdir/") - self.assertEqual(len(rdfgraph),10,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),9,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') @@ -7510,7 +7520,6 @@ def testUpdateUnpackedDataset(self): self.failUnless((subj,URIRef(dcterms+"license"),None) in rdfgraph, 'dcterms:license') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(oxds+"currentVersion"),"0") in rdfgraph, 'oxds:currentVersion') #Access state information of TestSubmission-testdir version 0 @@ -7531,7 +7540,7 @@ def testUpdateUnpackedDataset(self): rdfgraph = Graph() rdfstream = StringIO(rdfdata) rdfgraph.parse(rdfstream) - self.assertEqual(len(rdfgraph),17,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),16,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype2) in rdfgraph, 'Testing submission type: '+subj+", "+stype2) self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') @@ -7539,7 +7548,6 @@ def testUpdateUnpackedDataset(self): self.failUnless((subj,URIRef(dcterms+"license"),None) in rdfgraph, 'dcterms:license') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') self.failUnless((subj,URIRef(dcterms+"isVersionOf"),None) in rdfgraph, 'dcterms:isVersionOf') @@ -7590,7 +7598,6 @@ def testUpdateUnpackedDataset(self): self.failUnless((subj,URIRef(dcterms+"license"),None) in rdfgraph, 'dcterms:license') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dc+"description"),"This is a archived test item 2a ") in rdfgraph, 'dc:description') self.failUnless((subj,URIRef(dcterms+"title"),"Test item 2a") in rdfgraph, 'dcterms:title') @@ -7640,7 +7647,7 @@ def testUpdateUnpackedDataset(self): stype = URIRef("http://vocab.ox.ac.uk/dataset/schema#Grouping") base = self.getRequestUri("datasets/TestSubmission-testdir/") owl = "http://www.w3.org/2002/07/owl#" - self.assertEqual(len(rdfgraph),22,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),21,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') @@ -7648,7 +7655,6 @@ def testUpdateUnpackedDataset(self): self.failUnless((subj,URIRef(dcterms+"license"),None) in rdfgraph, 'dcterms:license') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') self.failUnless((subj,URIRef(dcterms+"isVersionOf"),None) in rdfgraph, 'dcterms:isVersionOf') @@ -7712,7 +7718,7 @@ def testUpdateUnpackedDataset(self): subj = URIRef(self.getRequestUri("datasets/TestSubmission-testdir")) stype = URIRef("http://vocab.ox.ac.uk/dataset/schema#Grouping") base = self.getRequestUri("datasets/TestSubmission-testdir/") - self.assertEqual(len(rdfgraph),21,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),20,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"identifier"),None) in rdfgraph, 'dcterms:identifier') self.failUnless((subj,URIRef(dcterms+"mediator"),None) in rdfgraph, 'dcterms:mediator') @@ -7720,7 +7726,6 @@ def testUpdateUnpackedDataset(self): self.failUnless((subj,URIRef(dcterms+"license"),None) in rdfgraph, 'dcterms:license') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') self.failUnless((subj,URIRef(dcterms+"isVersionOf"),None) in rdfgraph, 'dcterms:isVersionOf') @@ -7872,7 +7877,7 @@ def testMetadataMerging(self): base = self.getRequestUri("datasets/TestSubmission-testrdf/") owl = "http://www.w3.org/2002/07/owl#" stype = URIRef(oxds+"Grouping") - self.assertEqual(len(rdfgraph),21,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),20,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(owl+"sameAs"),URIRef("http://example.org/testrdf/")) in rdfgraph, 'owl:sameAs') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') @@ -7889,8 +7894,7 @@ def testMetadataMerging(self): self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"license"),None) in rdfgraph, 'dcterms:license') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(oxds+"currentVersion"),'1') in rdfgraph, 'oxds:currentVersion') #Get the file arabic.txt @@ -7981,7 +7985,7 @@ def testMetadataInDirectoryMerging(self): base = self.getRequestUri("datasets/TestSubmission-testrdf2/") owl = "http://www.w3.org/2002/07/owl#" stype = URIRef(oxds+"Grouping") - self.assertEqual(len(rdfgraph),20, 'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),19, 'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(owl+"sameAs"),URIRef("http://example.org/testrdf/")) in rdfgraph, 'owl:sameAs') self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') @@ -7999,7 +8003,6 @@ def testMetadataInDirectoryMerging(self): self.failUnless((subj,URIRef(dcterms+"license"),None) in rdfgraph, 'dcterms:license') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(oxds+"currentVersion"),'1') in rdfgraph, 'oxds:currentVersion') # Delete the dataset TestSubmission-testrdf2 @@ -8091,7 +8094,7 @@ def testReferencedMetadataMerging(self): base = self.getRequestUri("datasets/TestSubmission-testrdf3/") stype = URIRef(oxds+"Grouping") stype2 = URIRef(oxds+"item") - self.assertEqual(len(rdfgraph),32,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),31,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') self.failUnless((subj,URIRef(dcterms+"isVersionOf"),None) in rdfgraph, 'dcterms:isVersionOf') @@ -8112,8 +8115,7 @@ def testReferencedMetadataMerging(self): self.failUnless((subj,URIRef(dcterms+"rights"),None) in rdfgraph, 'dcterms:rights') self.failUnless((subj,URIRef(dcterms+"license"),None) in rdfgraph, 'dcterms:license') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') - self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') + self.failUnless((subj,URIRef(oxds+"isEmbargoed"),'True') in rdfgraph, 'oxds:isEmbargoed') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(oxds+"currentVersion"),'1') in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(owl+"sameAs"),URIRef("http://example.org/2aFiles/")) in rdfgraph, 'owl:sameAs') @@ -8216,7 +8218,7 @@ def testReferencedMetadataMerging2(self): dc = "http://purl.org/dc/elements/1.1/" stype = URIRef(oxds+"Grouping") stype2 = URIRef(oxds+"item") - self.assertEqual(len(rdfgraph),29,'Graph length %i' %len(rdfgraph)) + self.assertEqual(len(rdfgraph),28,'Graph length %i' %len(rdfgraph)) self.failUnless((subj,RDF.type,stype) in rdfgraph, 'Testing submission type: '+subj+", "+stype) self.failUnless((subj,URIRef(dcterms+"modified"),None) in rdfgraph, 'dcterms:modified') self.failUnless((subj,URIRef(dcterms+"isVersionOf"),None) in rdfgraph, 'dcterms:isVersionOf') @@ -8235,7 +8237,6 @@ def testReferencedMetadataMerging2(self): self.failUnless((subj,URIRef(dcterms+"license"),None) in rdfgraph, 'dcterms:license') self.failUnless((subj,URIRef(dcterms+"publisher"),None) in rdfgraph, 'dcterms:publisher') self.failUnless((subj,URIRef(oxds+"isEmbargoed"),None) in rdfgraph, 'oxds:isEmbargoed') - self.failUnless((subj,URIRef(oxds+"embargoedUntil"),None) in rdfgraph, 'oxds:embargoedUntil') self.failUnless((subj,URIRef(dcterms+"created"),None) in rdfgraph, 'dcterms:created') self.failUnless((subj,URIRef(oxds+"currentVersion"),'1') in rdfgraph, 'oxds:currentVersion') self.failUnless((subj,URIRef(dc+"description"),"This is a archived test item 2a ") in rdfgraph, 'dc:description') diff --git a/rdfdatabank/tests/testdata/rdfdatabank.zip b/rdfdatabank/tests/testdata/rdfdatabank.zip new file mode 100644 index 0000000000000000000000000000000000000000..5486da4dceeb5d82660fdd49104fc97ca00df66d GIT binary patch literal 376392 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 C|AH-5V%=otc9D`UU5Mvz;zZMHS_BT~$wE#{n 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

    #vt<+V!6Oi9atN)nT(jBwKa=37-lpfj`eUjt7 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

      5Pf=WEBRj5ubyHy zW6SabuKG-*VQDHO<(&9*l1Q6lZN^k$dgk|m#eB==s! ze;fl#Fqx~~%nPOv2RUQ8M&eH}-ao;BvSWmLgG5dW=i0*`xyzi9nA%U1L*r>&`-s03 zzaLJ#O3}`J=J9hS`8ngZZzc`phEmgtZW63f?><(#05OC0HS|0eaCnuP3!zFiCO^eo z+5i;M8IAn48D`4L!hZ;I1+s@^38>Ue9)Hu~3rP?o>1{H=a6ymi6pl$-L^Jf@^7n%AtSE$>~-!)Wx0|1uJ|;kf-M!{|q%8bXV7L;czzabzC7_0)zUM-kQY ztuBa+!nsQ?&ejWMW(cQm(^v z+e)vRVCvanr`l7kp(hAeTQhAYhAhj00Q{I3%g7D;e?;NSQkBAIOi^^<-uXv5B=R3p0H*YaK(XAh+!5P zc6`0gGRm1K*YT&$OWlwhRTSHqA>k-Ie_94BTG&_<(8nKu7qi61Qcp{3(Qj?=aqu|u*|aIOdqeg?SK&62 z2lm3eDlkE(zG1xyhKUczo&yylruy2NTjnOY6L$aOD+W)LIRPvThx-dh^ov6;Xp-Z) z5Q0=LWCw6P2d@Vwdg%!4f*aTks(R!WLR|ocWgtw?okiaG#B!f!>-?k9&Zjl2mGaS7 z@i2VQjjK8GeXN0?F0Uw5SDXftB?$?{r#Z54>6aJBpi}-ea5f=Q)LM(NOV=a6Qgp$_ z7gztZ-`%duqMNFGU2# zAkCa#L+K>UiiyE!1-p<_uWq}fO%jmwhe)G$PI~i4LZLZsiO{boR((F}e;Jbi}z5CKX|_$5^D z4vk-wEFOi*kpEah!gIrC)r5X$*6c&)<6W+(7BV|{KQfRKxlf3;>)a0J!UwYTIb<4O zxNmQO0{4Q&k%cG>PAy+w?3QAQ!t<4+o8-8So4-3>-+AhZFlJrQ^-Q``ruZh&AR<7O zgc3>t4vc_yK*S++QwbIb0n!RSvl)%=zN)`5QK^uKmTR2P1W9UpaNV1XYR`lvrs(8) zo`|0lKpY_%sSZPvedUEH@_UOlKnCN&C7Q&5WL9p_f^GBVuAjv1T8@0^Mg{kRW5_1D zGhoH7?w(H5vSGpBM4uY4T<(~Ne`SjQ$|xFJHPDZBp3z!ojQ`CQ)NoLK$#eF*44d2F!v)jSh!BQIE@2kGE8MWJqH4gIOoX@4WFp*V0M$xIF z5`I8;LH$msd3SbpVu>0#;2z*+!Hr4M?3Mp0>~ml4#l?RD2m5d=;-6aro=vG?=&C%t znpj9fe)W@(15FwVAcCeKCAjgewxAN`bxJHT0hQcY#^enLOq~ABMb0VhpEZ#+2ouY1 z;-KgY*g)31(dHt5pps|^OEf2RiH(9GVCkrMN_4rh zuYi(U2}G66Y$mS9oKbN1bTa0x*TAW20}C;cfpyXcO=JBCZl^)#53nrDL`CYcK5BIT zGi_(f3IKZgR$niKpj)EwZPp5@Oj!P?+rfW4tZ;*hcp{Pfoy=R-lFXqZL$#(XWYPdm zWK;x~c0zXXYL7uX3Va`F#z_rN;^FhYYSWVdm+}{lKm#*4hUc|lz#T;pw6tI}jV9A& z?CC;Z%>XWz_O9WCEs16e` zQcW}}_zkO~v)m`3zjYz-UE<~+5#i)IW)g7 zxig1tbi2bagVQN{I83prEi*dGv~w%o3|f3$r1PVv{joE(PhM0(8$Q_hwUk~CozH6L z++e*HUPQIBJ2r_0XB~@aBVjF@Os7z=rmoz+4zrz7iw7Yrd0Mv|#Y&DIVdcEubWPMA zLfwUtlE|RAEsu3(t-xuDF3(kzjBUoO&Aym3RBhHJ_pKY8Y^B|UK$u$BFh$CI@+5l9 zgIvwUnozK=%VS-7O}vPAG3A!goZR~|Y*)%!mj9Y!Kdkva*?0D}NVm?b+huC7& zX(-O=t$DO2M5C(43J%t&Dc6v<=szJB)hp9cS_(o`)esUWHw|q<57A$Vck;|}!X0x& z+vc@TO)rxjR}&kWwK%?}zN~Q^gSA-E;XagR&}XnCBQdvQWRD>a*wv>lF{Vs{FkOf#(D$Dhgm(a*w3H;O5DFRY zyYx|ADEMAJTC~^g&^g~Xb#r?;LAa|GY@#cVrW1DiZg2sA&~{VnRM8maS0^$!h5a)z z(|U`X9Ccle6Y520-X+^zosG&vF3cVi<~1NM?pJomuYSjWSlUUDsIT@qDtp1QDN>fJ z@|&&6Fy?GM7@8t1wgI(Xcds}?plAvMGCOJ>)LD3a$c~H`#XYW|o#34jqHuNv!tSSh zHD=3m_C5CgF?Cs}u9C)<(r3mc;9Icvu6{YcQ>gjGT-dLc^>^@Aa&dU;4AI&M|#w#UQlti{?R`a>G;Z&wU$(pg7G{dH>0kE)7 zA&iK>3-0KJB5emIpYy|lSSo|U{p@8_bZL(?f%gj zF;jE1uR#l$$8`S8))fc*(-?vGf#*(EWvnS^YsAc!z5erXw=2C99pY4u> zqy^BUzhDFiz?SO?(VG!`1H85MU-?|EkJm@aKY_z8&wsMj#|nBD0rIIt1ppwWO|pg+ zc!NOPwGHeDlV>v>`7x~+)UED-(3}JA7fKz(RR(!~l=h^z^V#^lUG{hd{z~{(*YQXb z7q+}duZ**iy;7#PjG?`{^;BUKLhr^Z&XRJMI>DJPwv}|J~-Xg3@_%|DK zqrPzqbWS*vBj?3zn@65_y@g$OqaW`2`g%~?l-FD3#8Sll1-aQxs4KK}Tz1}#yh#BY z8fnw}RO}4rx8aim@HBQ5Ts-j}i3@*$%dY%9v?XGNpynmDLjZv-a~S@r2Y4E?mBKnP zp?h&0ir7x9K?$S_@gR28JaPR?`du*sz{eM!=XfuPl6~;20o`nII4LSdH0f$cI$Ar@ zil&Qz0$vxSJakVUYOL;Jct8!Hdp2VVaiGc^!^JdpVSxMeseFn2kQ=Vtc6B?YR8Z5% zn@npl91hwpy31<22V{~e${p{fuRa?a=L1(!%ha#>R~=B((z`?p$kUc#+eJV|;6I4n z5Y<#3tkMD|mEgv%OM>fG(A|%Y>bg@lxLZ?jAI}b3s)LTk!B&lgZR#!fVlEbm$%-qr zsD%pdqJKV<3@Yrs`g&02>=L-S%pQ~gd`^GVO{}%@ ztbJtTh@%5E-C4Dj{AJ$^`rVS2s?{imO@o*6FiFt(k+Yv44IJ(G7Og0Rek89D-9+fo z<3PnkdH6SV5lz9hQUQA=Hkv%xVFVElqaZ>|(c#bUqNj>XaZAZ%JliDgQS`nq+sdYU zTWxNfFj^izU%x%MQh0hcmIf7Z?F^6ea(&h-jS=lEn@IYEK43Ukc8C{um#5>sl3~n? z2_nf$^U8eB`L>zOoa`q<19;EPrxhl8r zA&rao661K)>Euiz{*+q|?ENj!I$o*B5x0F7G>M##T{$Re&K{Movfiu8`*D@8D4Nb* zFbYJ{!wKAI8}Apv9$BP+RN%a25c}5m7|u=2XC-PGMyGBT-l%a~hEg&Z3lQJV$Kj== zd>YB7SFGHnkd6XNI9G_ah^}jQh7=1Q>b!tT2uUwezyO^Z3yw!ebU^Q|6Zf@!LkqpS z8X^74eYzz+U7uMinR^3|5nmkohXi-SoBdmR673Q{8T5m zP^w0Gr=P>*j%z7+|E9pNqDv8er5VB8(X_VlVZZRQrIT)k`A#$&!i|YUT>?&I;1_cw zRpu?hP>x2R=`MZKC9ghP3Iao$wZ^HvpLg84U0HklUHRM^h{RY^2UKfHIaEVZrRP zm1yoAju)$J*j|);ywEZnk}kPxGe&$r;)$B{B(uGXo#}K}&2n#wWY4OC@pX)ejF>cy zp#2N-V3)MN8gVfOo7H_MC=UO+w&t-d5fexLis@g=@`#)T-NpB}qJ=$$lG^)Lnz#3L z+YY!Ro0!?;Mf$U1ZmyKHdR@H*iE2@7>{YFc8+z;;J6WQs8lWK9-himTd9{kYX9Pal zV2a9|?v$I`Ch#QP*3%SN2AF(78ujV|J-wJ@;Ruoqr-nr7Nl1=m(q6ZT;`m%>Vs5F?Td{u=oj@D_l#r1CdKF z-w;WBddMQW&WSsU;1BnYwzN#8z)X&E!up^q8*TSbH|NRd<2vM0?HX{8I$0j#n4)%; zM6v6a5BP@)xqB|@a~gfIo3ydxhRB+RcczTeD3i{L!V0=^7A(Hc!$N1>WcEUev6B*p z%u;}^(RrqG*re0yxF`=UuB#`a*RJPv>p7+jhWR~-oS|T*969sKqKXn_DvuOjks!w& z4O8?xvu0g057gT7IgM66_bDObn44kM(jzXid4R5!>0d~yna*Gk=5sTc44O0<>GCii zyitCcU-IYD?m~ZpE4X6#^o!4q%~BT+P75<<_&*$Q`uH`ou{6uilfpIQ(kyv#FnaR2 z(Bfz~J(Ys(JsRXvAV8ErLaQ?V5}YPzznb7K&}kaxM3_+?Kc8~Ode-VKKOH|Fim)b^ zK3U5Wk0Fky#o_Tup%3^1tmDUEi9_)=jfC_wKrq1ANTv;teqXXHKmr5#(#l74skiN- zV9KUiI)jCL26G`qRW7JHCe&2%am9UfZ*Q1NB?3F!qrb^-c&nMmDGNdEzwI-{oEsrm z&yN6bQQvcoIU;NpP!yUpN7mh(Xq|S`fYStdD3PN}roicNf}MupRn}weDBF;A*PvdQ z%TJRtz8`zX+T@6k^7z2$??F4m#p|c7nWd=xp>PrcCJpj6>O+ZJK=KuPsFE>%Iwu3# z_KIs1=@ZQ?3hj8KOz3nvT!kTb=?LAsbAWrY0Mp)IP1gLuqMWwAXEY0`(r3bip?z_9 zJx{vZde(|QubgyQu&zQXTG06c%5wh!g@o)w_ zN*i+Z&^#zfQ&H?)E%JEeplmz@`h7XljVC|Ko;Jax+wV+sf6AdDL6uP#H*fM+vZo_o z9E+eh8({rrsV-5qPU}wZk5b1ISzFgiN8y$|t;cSf#KpyXjwaaV$%}Rl|LhEIg}V@9 z&yUD0z~)(`0r7Pk#wtOp7I^B*kKBaZiRqLZya@tZ{>rC&k6-DjTd-I0fMjhQ%k|{m3hLBu!$~4HbA? zI%7qPM&+T^LaNj{;SC<3SUI#eF=;O|orOI+7a`J{ruQ78SLbQAOtoNhTp`6yc)Ge~ zjnWDx=eFtUh^c#4+DihEQYED=QH&}w(mHm^t4b}T6eE~Tn5L+_`=YK8Ua;|_+R8Cc zQA6Q%q;E8$SFxD`Ox@A?eHE}v3k`B7+Zi2GjruJzUn8@es5Ba=Rh8z8;;D8vH@}RR zx@T3izX{^3J|03dw*hCiwx7>#JK@KpK7CxI*5*PGpZ9csk;iPK3csA~l)YFgsg*VR zeiCRU4`G!EK=R}J&O5c12>{cZ-#Rm3U_9-?<{2mG7W(>NiM|6ky11a~^M*$`dN|%3 zrRno|T>l;W`WR6-Y3m3W=zIF5hue)dB&$)eKt}VD>vi3pbaI`I5V>aBA&2wI%y*oX zA&JyY1O=B;rdjL|cCnJcpQ!i1h!G&}=zV*EvMDiuhLR24F6B>TuCvBIOMIsAGJrtB zi*-<^LH=YC&yT@Uq4?5FwegYIk>u%_^oOVDjZ&N%hY8;deKxs#-nT0Gy`DbhT3iL6 z>5mWF?#ap4FDsF5U;J1r7KhS>A+%Ih23nCdPvvBnCK;zy>^%8OJ$YU&)Ctn?QuZNw zh7GcJ$a4q$`NsSf1%PK_(3YIuJjUcaZZzw!3o1${|4^{=`%rWiqGP6Vx`4&eK>1qp zvyxc6`6RcA28v=nwYu|tWBdadcnDqj@9mg2R4BL^1A+=OQ`ZDI$tyg4e^`ig%!P(R zIWPhPy}}*E;`maK0~U*zg?+4Ko1KgeWq@f|=bm_{kX3_$ z3lT09r8!ipVJW``4?v%hSIrEJDeOJP55hsK_e`Ly40yPj(C%4mX??BH>y~$29m%Xy zlw+2ynH%=P)U*2g98$hAQcGezjMR%z)v5Mk+Zy{}WDU+(CfGMTwE{d@q`8&86%)zp z27ezxkd2rnR4c`QAGJ)Y)t#wFTWQzSDaQ1FUO#y@ZWaI#;~wDhX=h~`XQTilkzI-1at9RCYFFQmc300Hs@|rfM>a{tm~~oc z6k7toW&MS*ndiwHQDxakC1q*u02FJS0%Itct_ER?OkbTTui-nVuH63Rm?F^WZA zzG~QeXpiNQ{Rv}YhX9VCQni4189_jF9Ta67L-9}mX6qu{uOskn3z&#WyP)5qDQO*H z=M1B2{$ue9&{v$tlh!7lHL3g*6MelAbx_Pm&TwD~D2;8^TaU>961oK`0Xuhzm8Pkg z3Z7aa+eT-1I~#b(uOq_gYM^$f#ns|TO8mv8eN13vdVZo>TT|7d0q6mrQwxn^cb)Zv zt+MdOV7b(u$me)D09CF%K{~xk>Y>+#Y%35iP~LK6YdP+QJfkeZ|J@A8fXF3RLbiQf zP-CsDZYTA>On_PD>T$c*g3#Bg*7_5$ccRA?a9;?M4)oh z=UAEfW4q;@d^myP&*j}Vg(AXmY5kzzi(K?{mb3vGiyS7L73-@&FnzLlF^Ofbp5oWA_%ghB&Fmt7NldIez4{*os@if?Z zxL)d>uj)#!)4g=<8NKsXR|})+iHyLkx@n(BD!ZejDmq{ks$Xi81`XfB_9E5&oy37p zp}z&tDr=PU8f7MgGy!7!DwN#JJq{u&y(%{KuvLw;Ga_Kg2<%3GX&(rmAwDG*0#gOVM8o@wR?ZX7L>?1C(nuuARyK5LUi}yGJBK z43q37uEKL&@qot(`UWh90je~-jJOoHdKu=gr@m! z7tYqp{pisI5;k#zWKZ-;|s!B}2inMSD=zu`CO$c!nyX zoJ|E*uqDU^U|9ZUV)d3wFl+%6Klkv*@6 z+46FQC@}=hGhDjuEb>2j9@926MckAcdsv*$6vD|*ue zChSm~t=d&D|ALAAraN~eC95alC{j*06QZvYh8`Imq0w!@?na*_;vWbtnzVwI{(<9d z&7xcl%~96|+a1Gd5|TQ$Qb+Wtfuim!Qtp2x*NT^B507=MFudrTu|`>J3i&T2kzN)o zSW3e`>le4%(8J2B&)uF`J!I zT?D&@Q%Cty@^p$l4#vk_#n0Dn3L(ip_&e7$J=Ea>uBPbr2zuG3+MfY{6|(o(>%RvM zT)KKYkYE@DGtByHFY${FRe-;dNCA4fB84hsGEqshN)6p0+{$7%fr_gPG-k#QctAd* z!>~#w_(wo)YnUGpqkg4Kc0lEoBIp#Y$@hpdyjp4;+g9{pN_CL~bF<#IEEcvfTh3X< zXES#6HcUYSAJ)V__$swtcD+WHh)fT=y$OU#8&!22N%4ytl;LM9fR>Ow;>b3*3%Q*D zcI!x~q>`naYkUY1;-MpG;+aU=$lzT49*e5>W)u}Bm{5$%IXC*KbEvR*>;1=Mi8bYg~q_GItr4)~a0 zKy?PVO~FB52*1HoD?HB6R?UzvARZ|^`n@;U18^-DCz{7*4MTKbh>}xRLJ~eG2>cN! zVTFAl6ykDJdv+%nlk?u47kPdK_jJ9PMpBAEVfFEg7(|BvK*QMaxVTT`^su+roMMYk zYaYN0mmWk6trt!u6AgJ+%X@MBf#vXE-^pp#`!zrdNMs#O37Q5&=&!wlxM-{}`j1heJ(Aj1~)pBWJ3+t?T8l(N;V{>99ao&mOZQ zFea)7|EwfTc-|-mI#&VxMr9?ZphR!yOfkV&8&4tsb(iU$>={8wo z1HA9iX3Qx)>Iw=+b(Pfz!VeYJXY}^(J zl|y!oZ^xVU;t~?qZA4Z-^s`LF92{Il98Gs21z7w>(CVrD&Z|Za5()L zlPnyYMPw7ZYNm?BROl#a(vTc}@Ya?%KW@J5yH{?!m;vdkPkc!PZe0wxb*njz8jk_E z+RIe1I#^?5D0bSx@RsYa#bc{MFeiqrC3;o^AvkxUbAEfu-b;%R+DV=NSbad@6(yGs za0%TNr=oLH?C)7ALYX}cG1qPBKq11qy`bO_6E^SVC8TrM4}E}*y|*pmn7#KK%abZp;%*-`~>nJbc*4~p!CUDw`PoGs4_Kv zgWE=IAPpe*d4N^?*tc3Y++|5S8(VcFW;eJnn_th&U3o^%WbKeO`!6g&I}>?#<=KG( zuNc~EtK9T_#X-$;D6+zuU`g>*ljXgsc7#fbtvR^@bWj6^iHZV#K{hHATSY;wahldg z`P=(}OmZM#yWM(S9jShY`(StB&Zp>GIlJ5}%o>%eqf0iqZT-y&{y2uWtY;BZtjl{* z9Z^*v<6GyGSO*Y`x>U-dLZ;ZByA5awzf^=n0pU)ycT%Oq^#o-0Flzp`A+hYFP%MlG z#+gO?3%j=dY~^EMjVd4}DF;9Sgk-)zVqFcXA63AeAD23<$eUE#b9dY3tO__T%y?wT za9B9hQA7r4JLgByCC*c4NY2&TCG_~GMa!1P$ijuDW@!CAh&skXN2Alk)H;W1(R7MQ z50X7rlC}+s>p4tcp^Hm3dLXnT*&5Sd;Uv^IUmh#B?L z)=`Mk@+qq5_XHqw5(|2qc+2gRHp&UTMygO+v zmVXk0j>*1ODGzYNK#1`HcKid&kQLyU4pXhFcqnnPiI6(;t1_Yh#S-H5v8O&U_)9?A zv3$hIKj9Dd@)O#@;wng((ym10^*3115<1w_x!6XHQt?Yi)E@7BV$$@|TwLS~{sEfpki%A4jl>zr`_+pW zDLK1K21<5L+^Gy;4)CxSZ|j9h0&_gnR8q zQa@+_R0tUjzy_~{KgMCiP^e|#c|ZWOmlSiW4IwC2CRwUhszQTU82xkMB6mH*efre9 zUwbzB?h+uKzgP4{Y?NZuXS>Z+b!Gy|k~>FNg!(--sjtv*WizD0CnCXn$|6xQKKz

      u@Lp>rb#ahPnv6`*9tL$Yg-FHwn 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

      n))UzYR#+<$Geh!s0u4`H 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%0A7F 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 pDoR9y@Q?)i#d;PB0%E`&1XlltLT?4RQb

    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%0Dt~wBoaZ{a@nkD()u++;BBV^ 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