Example #1
0
    def setUp(self):
        self.client = Client()

        # dependent objects to use for creating test pids
        self.domain = Domain(name="test domain")
        self.domain.save()
        self.user = User(username="******")
        self.user.set_password("pidpass")
        self.user.save()
        self.policy = Policy(commitment="Not Guaranteed")
        self.policy.save()

        # test pids: one ark & one purl
        self.ark = Pid(name="testark",
                       domain=self.domain,
                       creator=self.user,
                       editor=self.user,
                       type="Ark",
                       policy=self.policy)
        self.ark.save()
        self.ark.target_set.create(uri="http://some.uri")
        self.ark.target_set.create(qualify="q", uri="http://other.uri")
        self.purl = Pid(name="testpurl",
                        domain=self.domain,
                        creator=self.user,
                        editor=self.user,
                        type="Purl")
        self.purl.save()
        self.purl.target_set.create(uri="http://some.uri")
        self.proxy = Proxy(name="testproxy", transform="http://proxy.com?url=")
        self.proxy.save()
Example #2
0
    def setUp(self):
        # dependent objects to use for creating test pids
        self.domain = Domain(name="test domain")
        self.domain.save()
        self.user = User(username="******")
        self.user.set_password("pidpass")
        self.user.save()

        # test pids: one ark & one purl
        self.ark = Pid(name="testark", domain=self.domain, creator=self.user,
            editor=self.user, type="Ark")
        self.ark.save()
        self.purl = Pid(name="testpurl", domain=self.domain, creator=self.user,
            editor=self.user, type="Purl")
        self.purl.save()
Example #3
0
 def test_mint_noid(self):
     noid = Pid.mint_noid()
     self.assertNotEqual(None, noid,
                         "value returned by mint_noid should not be None")
     self.assert_(
         re.compile("^[a-z0-9]+$").match(noid),
         "generated noid '" + noid + "' matches expected pattern")
Example #4
0
    def setUp(self):
        # dependent objects to use for creating test pids
        self.domain = Domain(name="test domain")
        self.domain.save()
        self.user = User(username="******")
        self.user.set_password("pidpass")
        self.user.save()

        self.ark = Pid(name="testark", domain=self.domain, creator=self.user,
            editor=self.user, type="Ark")
        self.ark.save()
        self.purl = Pid(name="testpurl", domain=self.domain, creator=self.user,
            editor=self.user, type="Purl")
        self.purl.save()

        self.proxy = Proxy(name="testproxy", transform="proxy.com?url=")
        self.proxy.save()
Example #5
0
    def setUp(self):
        # dependent objects to use for creating test pids
        self.domain = Domain(name="test domain")
        self.domain.save()
        self.user = User(username="******")
        self.user.set_password("pidpass")
        self.user.save()

        # test pids: one ark & one purl
        self.ark = Pid(name="testark",
                       domain=self.domain,
                       creator=self.user,
                       editor=self.user,
                       type="Ark")
        self.ark.save()
        self.purl = Pid(name="testpurl",
                        domain=self.domain,
                        creator=self.user,
                        editor=self.user,
                        type="Purl")
        self.purl.save()
Example #6
0
    def setUp(self):
        # dependent objects to use for creating test pids
        self.domain = Domain(name="test domain")
        self.domain.save()
        self.user = User(username="******")
        self.user.set_password("pidpass")
        self.user.save()

        self.ark = Pid(name="testark",
                       domain=self.domain,
                       creator=self.user,
                       editor=self.user,
                       type="Ark")
        self.ark.save()
        self.purl = Pid(name="testpurl",
                        domain=self.domain,
                        creator=self.user,
                        editor=self.user,
                        type="Purl")
        self.purl.save()

        self.proxy = Proxy(name="testproxy", transform="proxy.com?url=")
        self.proxy.save()
Example #7
0
    def setUp(self):
        self.client = Client()

        # dependent objects to use for creating test pids
        self.domain = Domain(name="test domain")
        self.domain.save()
        self.user = User(username="******")
        self.user.set_password("pidpass")
        self.user.save()
        self.policy = Policy(commitment="Not Guaranteed")
        self.policy.save()

        # test pids: one ark & one purl
        self.ark = Pid(name="testark", domain=self.domain, creator=self.user,
            editor=self.user, type="Ark", policy=self.policy)
        self.ark.save()
        self.ark.target_set.create(uri="http://some.uri")
        self.ark.target_set.create(qualify="q", uri="http://other.uri")
        self.purl = Pid(name="testpurl", domain=self.domain, creator=self.user,
            editor=self.user, type="Purl")
        self.purl.save()
        self.purl.target_set.create(uri="http://some.uri")
        self.proxy = Proxy(name="testproxy", transform="http://proxy.com?url=")
        self.proxy.save()
Example #8
0
class ResolverTestCase(unittest.TestCase):
    def setUp(self):
        self.client = Client()

        # dependent objects to use for creating test pids
        self.domain = Domain(name="test domain")
        self.domain.save()
        self.user = User(username="******")
        self.user.set_password("pidpass")
        self.user.save()
        self.policy = Policy(commitment="Not Guaranteed")
        self.policy.save()

        # test pids: one ark & one purl
        self.ark = Pid(name="testark",
                       domain=self.domain,
                       creator=self.user,
                       editor=self.user,
                       type="Ark",
                       policy=self.policy)
        self.ark.save()
        self.ark.target_set.create(uri="http://some.uri")
        self.ark.target_set.create(qualify="q", uri="http://other.uri")
        self.purl = Pid(name="testpurl",
                        domain=self.domain,
                        creator=self.user,
                        editor=self.user,
                        type="Purl")
        self.purl.save()
        self.purl.target_set.create(uri="http://some.uri")
        self.proxy = Proxy(name="testproxy", transform="http://proxy.com?url=")
        self.proxy.save()

    def tearDown(self):
        self.proxy.delete()
        self.purl.delete()
        self.ark.delete()
        self.user.delete()
        self.domain.delete()
        self.policy.delete()

    def test_resolve_purl(self):
        response = self.client.get("/" + self.purl.pid)
        self.assert_(isinstance(response, HttpResponseRedirect),
                     "response to resolve purl is a redirect")
        self.assertEqual(self.purl.primary_target_uri(), response["Location"])

    def test_resolve_proxied_purl(self):
        # add a proxy to the purl target
        t = self.purl.primary_target()
        t.proxy = self.proxy
        t.save()
        response = self.client.get("/" + self.purl.pid)
        self.assert_(isinstance(response, HttpResponseRedirect),
                     "resonse to resolve purl is a redirect")
        self.assertEqual(self.proxy.transform + self.purl.primary_target_uri(),
                         response["Location"])

    def test_resolve_ark(self):
        response = self.client.get("/ark:/" + settings.PID_ARK_NAAN + '/' +
                                   self.ark.pid)
        self.assert_(isinstance(response, HttpResponseRedirect),
                     "response to resolver ark is a redirect")
        self.assertEqual(self.ark.primary_target_uri(), response["Location"])

    def test_resolve_inactive_ark(self):
        for t in self.ark.target_set.all():
            t.active = False
            t.save()

        response = self.client.get("/ark:/" + settings.PID_ARK_NAAN + '/' +
                                   self.ark.pid)
        self.assertEqual(404, response.status_code)

    def test_resolve_inactive_purl(self):
        for t in self.purl.target_set.all():
            t.active = False
            t.save()

        response = self.client.get("/" + self.purl.pid)
        self.assertEqual(404, response.status_code)

    def test_resolve_qualified_ark(self):
        response = self.client.get("/ark:/" + settings.PID_ARK_NAAN + '/' +
                                   self.ark.pid + "/q")
        self.assert_(isinstance(response, HttpResponseRedirect),
                     "response to resolve qualified ark is a redirect")
        self.assertEqual(
            self.ark.target_set.get(qualify='q').uri, response["Location"])

    def test_notfound_purl(self):
        response = self.client.get("/boguspurl")
        self.assert_(isinstance(response, HttpResponseNotFound),
                     "response for non-existent purl is not found")
        self.assertEqual(404, response.status_code)

    def test_notfound_ark(self):
        response = self.client.get("/ark:/34235/bogusark")
        self.assert_(isinstance(response, HttpResponseNotFound),
                     "response for non-existent ark is not found")
        self.assertEqual(404, response.status_code)

    def test_ark_metadata(self):
        # NOTE: can't currently test using django test client because of limitations recognizing ? with no query string
        #response = self.client.get("/ark:/" + settings.PID_ARK_NAAN + '/' + self.ark.pid + "?")

        request = HttpRequest()
        request.META[
            "REQUEST_URI"] = "/ark:/" + settings.PID_ARK_NAAN + '/' + self.ark.pid + "?"
        response = ark_metadata(request, self.ark.pid)
        self.assert_(isinstance(response, HttpResponse),
                     "ark_metadata returns HttpResponse")
        for header in response.items():
            if header[0] == 'Content-Type':
                self.assertEqual(header[1], "text/plain",
                                 "response has text/plain mimetype")
        lines = response.content.splitlines()
        self.assertEqual("erc:", lines[0], "response is in ERC format")
        what = lines[1].split(":", 1)  # only split once
        self.assertEqual("what", what[0])
        self.assertEqual(self.ark.name, what[1].strip(),
                         "ark name is listed as what:")
        where = lines[2].split(":", 1)  # only split once
        self.assertEqual("where", where[0])
        self.assertEqual(
            self.ark.primary_target_uri(), where[1].strip(),
            "ark target url " + self.ark.primary_target_uri() +
            " listed as location; got " + where[1].strip())

    def test_ark_policy(self):
        response = self.client.get("/ark:/" + settings.PID_ARK_NAAN + '/' +
                                   self.ark.pid + "??")
        self.assert_(isinstance(response, HttpResponse),
                     "response for ark?? is an HttpResponse")
        for header in response.items():
            if header[0] == 'Content-Type':
                self.assertEqual(header[1], "text/plain",
                                 "response to ark?? is plain text")
        self.assert_("erc-support:" in response.content,
                     "content includes 'erc-support:'")
        sections = response.content.split("erc-support:\n")
        lines = sections[1].splitlines()
        what = lines[0].split(":", 1)
        self.assertEqual("what", what[0])
        self.assertEqual(
            self.policy.commitment, what[1].strip(),
            "what: value should be policy commitment %s, got %s" %
            (self.policy.commitment, what[1].strip()))
        when = lines[1].split(":", 1)
        self.assertEqual("when", when[0])
        create_date = self.policy.created_at.strftime("%Y%m%d")
        self.assertEqual(
            create_date, when[1].strip(),
            "when: value should be policy creation date " + create_date +
            ", got " + when[1].strip())

    def test_resolve_and_ark_normalization(self):
        # test that url rules follow ark character repertoires

        # should resolve just the same as an unqualified ark with a / or . on the end
        response = self.client.get("/ark:/" + settings.PID_ARK_NAAN + '/' +
                                   self.ark.pid + "/")
        self.assert_(isinstance(response, HttpResponseRedirect),
                     "response for ark/ is a redirect")
        self.assertEqual(self.ark.primary_target_uri(), response["Location"],
                         "redirect location for ark/ is primary target")
        response = self.client.get("/ark:/" + settings.PID_ARK_NAAN + '/' +
                                   self.ark.pid + ".")
        self.assert_(isinstance(response, HttpResponseRedirect),
                     "response for ark. is a redirect")
        self.assertEqual(self.ark.primary_target_uri(), response["Location"],
                         "redirect location for ark. is primary target")

        # hyphens in the pid should be ignored
        hyphenated_pid = '-'.join(self.ark.pid)
        response = self.client.get("/ark:/" + settings.PID_ARK_NAAN + '/' +
                                   hyphenated_pid)
        self.assert_(isinstance(response, HttpResponseRedirect),
                     "response for hyphenated pid is a redirect")
        self.assertEqual(
            self.ark.primary_target_uri(), response["Location"],
            "redirect location for hyphenated ark is primary target")

        # qualifier with hyphens
        target = self.ark.target_set.create(qualify="abc",
                                            uri="http://weirdos.net")
        response = self.client.get("/ark:/" + settings.PID_ARK_NAAN + '/' +
                                   self.ark.pid + '/' +
                                   '-'.join(target.qualify))
        self.assert_(isinstance(response, HttpResponseRedirect),
                     "response for hyphenated qualifier is a redirect")
        self.assertEqual(target.uri, response["Location"],
                         "hyphens in qualifier ignored when resolving")

        # . or / at end of qualifier should be ignored
        response = self.client.get("/ark:/" + settings.PID_ARK_NAAN + '/' +
                                   self.ark.pid + '/' + target.qualify + '.')
        self.assert_(
            isinstance(response, HttpResponseRedirect),
            "response for qualifier with following '.' is a redirect")
        self.assertEqual(target.uri, response["Location"],
                         "'.' at end of qualifier ignored when resolving")

        response = self.client.get("/ark:/" + settings.PID_ARK_NAAN + '/' +
                                   self.ark.pid + '/' + target.qualify + '/')
        self.assert_(
            isinstance(response, HttpResponseRedirect),
            "response for qualifier with following '/' is a redirect")
        self.assertEqual(target.uri, response["Location"],
                         "'/' at end of qualifier ignored when resolving")

    def test_resolve_invalid_ark(self):
        # more character repertoire stuff - test allowed characters in noid & qualifier
        response = self.client.get("/ark:/" + settings.PID_ARK_NAAN + '/123!')
        self.assert_(isinstance(response, HttpResponseNotFound),
                     "response for ark with invalid characters is not found")

        # characters included in the allowed set
        self.ark.target_set.create(qualify="q=@_$", uri="http://weirdos.net")
        response = self.client.get("/ark:/" + settings.PID_ARK_NAAN + '/' +
                                   self.ark.pid + '/q=@_$')
        self.assert_(isinstance(response, HttpResponseRedirect))
        self.assertEqual("http://weirdos.net", response["Location"])

        # qualifier with invalid character
        response = self.client.get("/ark:/" + settings.PID_ARK_NAAN + '/' +
                                   self.ark.pid + '/ab^')
        self.assert_(
            isinstance(response, HttpResponseNotFound),
            "response for ark with invalid characters in qualifier is not found"
        )
Example #9
0
class TargetTestCase(TestCase):
    fixtures = ['pids.json']

    def setUp(self):
        # dependent objects to use for creating test pids
        self.domain = Domain(name="test domain")
        self.domain.save()
        self.user = User(username="******")
        self.user.set_password("pidpass")
        self.user.save()

        self.ark = Pid(name="testark",
                       domain=self.domain,
                       creator=self.user,
                       editor=self.user,
                       type="Ark")
        self.ark.save()
        self.purl = Pid(name="testpurl",
                        domain=self.domain,
                        creator=self.user,
                        editor=self.user,
                        type="Purl")
        self.purl.save()

        self.proxy = Proxy(name="testproxy", transform="proxy.com?url=")
        self.proxy.save()

    def tearDown(self):
        self.domain.delete()
        self.user.delete()
        self.ark.delete()
        self.purl.delete()
        self.proxy.delete()

    def test_get_resolvable_url(self):
        t = self.ark.target_set.create(uri="some.uri")
        # test against expected ark url from settings in config file
        base_ark = settings.PID_RESOLVER_URL + "/ark:/" + settings.PID_ARK_NAAN
        self.assertEqual(base_ark + "/" + self.ark.pid, t.get_resolvable_url())
        t.qualify = ""
        self.assertEqual(base_ark + "/" + self.ark.pid, t.get_resolvable_url())
        t.qualify = "?"
        self.assertEqual(base_ark + "/" + self.ark.pid + "/?",
                         t.get_resolvable_url())
        t.qualify = "some/long/qualifier.txt"
        self.assertEqual(
            base_ark + "/" + self.ark.pid + "/some/long/qualifier.txt",
            t.get_resolvable_url())

        t = self.purl.target_set.create(uri="some.uri")
        self.assertEqual(settings.PID_RESOLVER_URL + "/" + self.purl.pid,
                         t.get_resolvable_url())

    def test_token_replacement(self):
        self.ark.target_set.create(uri="http://some.url/with/" +
                                   settings.PID_REPLACEMENT_TOKEN)
        self.assertEqual("http://some.url/with/" + self.ark.pid,
                         self.ark.primary_target().uri)

    def test_invalid_qualifier(self):
        self.assertRaises(
            Exception,
            self.ark.target_set.create,
            "attempting to save a target with invalid qualifiers raises an exception",
            qualify='q^',
            uri="no.uri",
        )

    def test_get_policy(self):
        # top-level domain
        domain = Domain.objects.get(pk=1)
        p = domain.get_policy()
        self.assert_(isinstance(p, Policy),
                     "domain get_policy returns Policy object")
        self.assertEqual(p, domain.policy)

        #  with no explicit policy
        collection = Domain.objects.get(pk=4)
        self.assertEqual(collection.policy, None, "collection has no policy")
        p = collection.get_policy()
        self.assert_(isinstance(p, Policy),
                     "collection get_policy returns Policy object")
        self.assertEqual(
            p, collection.parent.policy,
            "collection get_policy returns parent domain's policy")

        # collection with explicit policy different from parent domain
        collection = Domain.objects.get(pk=2)
        self.assert_(isinstance(collection.policy, Policy),
                     "collection has its own policy")
        p = collection.get_policy()
        self.assert_(isinstance(p, Policy),
                     "collection get_policy returns Policy object")
        self.assertEqual(p, collection.policy,
                         "collection get_policy returns collection's policy")
        self.assertNotEqual(
            p, collection.parent.policy,
            "collection get_policy returns collection's policy")
Example #10
0
class PidTestCase(TestCase):
    fixtures = ['pids.json']

    def setUp(self):
        # dependent objects to use for creating test pids
        self.domain = Domain(name="test domain")
        self.domain.save()
        self.user = User(username="******")
        self.user.set_password("pidpass")
        self.user.save()

        # test pids: one ark & one purl
        self.ark = Pid(name="testark",
                       domain=self.domain,
                       creator=self.user,
                       editor=self.user,
                       type="Ark")
        self.ark.save()
        self.purl = Pid(name="testpurl",
                        domain=self.domain,
                        creator=self.user,
                        editor=self.user,
                        type="Purl")
        self.purl.save()

    def tearDown(self):
        self.domain.delete()
        self.user.delete()
        self.ark.delete()
        self.purl.delete()

    def test_mint_noid(self):
        noid = Pid.mint_noid()
        self.assertNotEqual(None, noid,
                            "value returned by mint_noid should not be None")
        self.assert_(
            re.compile("^[a-z0-9]+$").match(noid),
            "generated noid '" + noid + "' matches expected pattern")

    def test_primary_target(self):
        self.assertEqual(None, self.ark.primary_target())
        self.assertEqual(None, self.purl.primary_target())
        purl_target = self.purl.target_set.create(uri="some.uri")
        self.assertEqual(purl_target, self.purl.primary_target())
        ark_target = self.ark.target_set.create(uri="some.other.uri")
        ark_qual_target = self.ark.target_set.create(uri="some.other.uri/foo",
                                                     qualify='q')
        self.assertEqual(ark_target, self.ark.primary_target())

    def test_is_valid__purl(self):
        self.assert_(self.purl.is_valid(), "purl with no targets is valid")
        self.purl.target_set.create(uri="some.uri")
        self.assert_(self.purl.is_valid(),
                     "purl with single unqualified target is valid")
        self.purl.primary_target().qualify = "qual"
        self.assertRaises(Exception, self.purl.is_valid,
                          "purl with single qualified target is invalid")
        self.purl.target_set.get().qualify = ""
        self.purl.target_set.create(qualify='q', uri="no.uri")
        self.assertRaises(Exception, self.purl.is_valid,
                          "purl with multiple targets is invalid")

    def test_is_valid__ark(self):
        self.assert_(self.ark.is_valid(), "ark with no targets is valid")
        self.ark.target_set.create(uri="http://some.uri")
        self.assert_(self.ark.is_valid(),
                     "ark with one unqualified target is valid")
        self.ark.target_set.create(qualify="q", uri="http://other.uri")
        self.assert_(self.ark.is_valid(), "ark with two targets is valid")

        self.ark.target_set.create(qualify="qual",
                                   uri="http://some.url",
                                   proxy=None)
        self.assert_(self.ark.is_valid(), "ark with two targets is valid")

        for t in self.ark.target_set.all():
            t.qualify = "q"
        self.assertRaises(Exception, self.ark.is_valid,
                          "ark with duplicate qualifiers is invalid")

    def test_purl_url(self):
        # url when there is no target
        self.assertEqual(
            '', self.purl.url(),
            "url for purl with no target should be '', got " + self.purl.url())
        # now add a target
        self.purl.target_set.create(uri="some.uri")
        self.assertEqual(
            settings.PID_RESOLVER_URL + "/" + self.purl.pid, self.purl.url(),
            "url for purl with target should be " + settings.PID_RESOLVER_URL +
            "/" + self.purl.pid + ", got " + self.purl.url())

    def test_ark_url(self):
        # url when there is no target
        self.assertEqual(
            '', self.ark.url(),
            "url for ark with no target should be '', got " + self.ark.url())
        # add a qualified target (no unqualified/primary target)
        self.ark.target_set.create(qualify="q", uri="http://ti.ny")
        self.assertEqual(
            settings.PID_RESOLVER_URL +
            "/ark:/" + settings.PID_ARK_NAAN + "/" + self.ark.pid + "/q",
            self.ark.url(), "url for ark with no primary target should be " +
            settings.PID_RESOLVER_URL + "/ark:/" + settings.PID_ARK_NAAN +
            "/" + self.ark.pid + "/q , got " + self.ark.url())
        # add an unqualified target
        self.ark.target_set.create(uri="http://wh.ee")
        self.assertEqual(
            settings.PID_RESOLVER_URL +
            "/ark:/" + settings.PID_ARK_NAAN + "/" + self.ark.pid,
            self.ark.url(), "url for ark with primary target should be " +
            settings.PID_RESOLVER_URL + "/ark:/" + settings.PID_ARK_NAAN +
            "/" + self.ark.pid + ", got " + self.ark.url())

    def test_get_policy(self):
        # pid with explicit policy set
        pid = Pid.objects.get(pk=1)
        p = pid.get_policy()
        self.assert_(isinstance(p, Policy),
                     "Pid get_policy returns Policy object")
        self.assertEqual(p, pid.policy, "get_policy response is Pid policy")
        self.assertNotEqual(
            p, pid.domain.policy,
            "get_policy response is different than domain policy")

        # pid with no explicit policy - inherits from domain
        pid = Pid.objects.get(pk=2)
        self.assertEqual(pid.policy, None, "test pid has no explicit policy")
        p = pid.get_policy()
        self.assert_(isinstance(p, Policy),
                     "pid get_policy returns Policy object")
        self.assertEqual(p, pid.domain.policy,
                         "pid get_policy returns domain policy")

        # inactive pid returns inactive policy
        pid = Pid.objects.get(pk=2)
        for t in pid.target_set.all():
            t.active = False
            t.save()
        self.assertEquals(pid.is_active(), False)

        p = Policy.objects.get(title__exact='Inactive Policy')
        self.assertEquals(pid.get_policy(), p)

    def test_url_link(self):
        self.purl.target_set.create(uri="some.uri")
        url = settings.PID_RESOLVER_URL + "/" + self.purl.pid
        self.assert_(
            re.compile('^<a [^>]*href=[\'"]' + url + '[\'"]>' + url +
                       '</a>$').match(self.purl.url_link()),
            "url link for purl with target should match pattern for link with "
            + url + ", got " + self.purl.url_link())

    def test_is_active(self):
        # setup creates ark/purl with no targets, so they are inactive
        self.assertFalse(self.ark.is_active())
        self.assertFalse(self.purl.is_active())

        purl_target = self.purl.target_set.create(uri="some.uri")
        ark_target = self.ark.target_set.create(uri="some.other.uri")
        self.assertTrue(self.ark.is_active())
        self.assertTrue(self.purl.is_active())

        purl_target.active = False
        purl_target.save()
        ark_target.active = False
        ark_target.save()

        self.assertFalse(self.ark.is_active())
        self.assertFalse(self.purl.is_active())

    @unittest.skip  # linkcheck disabled in 0.10
    def test_target_linkcheck_status(self):
        # no links checked, status -> none
        self.assertEqual(
            None, self.ark.target_linkcheck_status(),
            'ARK with no targets should have linkcheck status of None (unknown)'
        )
        self.assertEqual(
            None, self.purl.target_linkcheck_status(),
            'PURL with no targets should have linkcheck status of None (unknown)'
        )

        # add targets; automatically get checked and will fail
        purl_target = self.purl.target_set.create(uri="some.uri")
        ark_target = self.ark.target_set.create(uri="some.other.uri")
        ark_qual_target = self.ark.target_set.create(uri="some.other.uri/foo",
                                                     qualify='q')
        self.assertFalse(
            self.ark.target_linkcheck_status(),
            'ARK with invalid target uris should have linkcheck status of False (error)'
        )
        self.assertFalse(
            self.purl.target_linkcheck_status(),
            'PURL with invalid target uri should have linkcheck status of False (error)'
        )

        # manually update status to check valid / mixed
        purl_linkcheck = purl_target.linkcheck.first()
        purl_linkcheck.url.status = True
        purl_linkcheck.url.save()
        self.assertTrue(
            self.purl.target_linkcheck_status(),
            'purl with valid target uri should have link status True (ok)')
        # one valid ark target and one invalid is still invalid
        ark_linkcheck = ark_target.linkcheck.first()
        ark_linkcheck.url.status = True
        ark_linkcheck.url.save()
        self.assertFalse(self.ark.target_linkcheck_status(),
            'ark with one valid and one invalid target uri should have ' + \
            'link status False (error)')
        ark_qual_linkcheck = ark_qual_target.linkcheck.first()
        ark_qual_linkcheck.url.status = True
        ark_qual_linkcheck.url.save()
        self.assertTrue(
            self.ark.target_linkcheck_status(),
            'ark with all valid target uris should have link status True (ok)')
Example #11
0
def create_pid(request, type):
    '''On POST, create a new ARK or PURL.  On successful creation, returns a
    response with status code 201 (Created), and response content is the resolvables
    url for the newly minted ARK or PURL.  If required parameters are missing
    or any parameters are invalid (e.g., referencing a Proxy or Policy that does
    not exist), the returned response will have a status code 400 (Bad Request),
    and the content of the response will be an explanatory message.

    Supported POST parameters:
        * domain - REQUIRED; domain should be in URI resource format, e.g.
          http://pid.emory.edu/domains/1/
        * target_uri - REQUIRED; URL that the new ARK or PURL should resolve to
        * name - label or title for the new pid
        * external_system_id - external system name
        * external_system_key - key or identifier in the specified external system
        * policy - policy by name (if this pid needs a different policy from its
          domain)
        * proxy - proxy to use when resolving target url; specify by name
        * qualifier - target should be created with the specified target; **ARK only**

    :param type: type of pid to create - ark or purl

    Example create urls::

        http://pid.emory.edu/ark/ - create a new ARK
        http://pid.emory.edu/purl/ - create a new PURL

    '''
    if request.method == 'POST':
        # TODO: require ssl ?
        if not request.user.is_authenticated():
            # 401 unauthorized - not logged in or invalid credentials
            return HttpResponseUnauthorized(BASIC_AUTH_REALM)
        elif not request.user.has_perm('pid.add_pid'):
            # 403 Forbidden - logged in but insufficient permissions
            return HttpResponseForbidden()

        try:
            # if required fields are not present, return an error message
            if 'domain' not in request.POST or 'target_uri' not in request.POST:
                raise BadRequest('domain and target_uri are required')
            # incompatible options - qualifier only makes sense for purls
            if 'qualifier' in request.POST and type == 'purl':
                raise BadRequest('Purl targets can not have qualifiers')

            # domain should be passed in as resource URI - resolve to model instance
            domain = _domain_from_uri(request.POST['domain'])

            # assemble the data for creating the new pid
            # - required fields
            pid_opts = {
                'type':
                type.title(),  # url uses lower case, model requires title case
                'domain': domain,
                'creator_id': request.user.id,
                'editor_id': request.user.id
            }
            # - optional fields
            if 'name' in request.POST:
                pid_opts['name'] = request.POST['name']
            # could you have an external system id and not a ext-sys key? or vice versa?
            if 'external_system_id' in request.POST:
                try:
                    pid_opts['ext_system'] = ExtSystem.objects.get(
                        name=request.POST['external_system_id'])
                except ObjectDoesNotExist:
                    raise BadRequest("External System '%s' not found" %
                                     request.POST['external_system_id'])
            if 'external_system_key' in request.POST:
                pid_opts['ext_system_key'] = request.POST[
                    'external_system_key']
            if 'policy' in request.POST:
                try:
                    pid_opts['policy'] = Policy.objects.get(
                        title=request.POST['policy'])
                except ObjectDoesNotExist:
                    raise BadRequest("Policy '%s' not found" %
                                     request.POST['policy'])

            # target can't be created until after the noid is minted
            # - init target options before creating pid to be sure they are valid
            #   (i.e., if a proxy is specified, it exists)
            target_opts = {'uri': request.POST['target_uri']}
            if 'proxy' in request.POST:
                try:
                    target_opts['proxy'] = Proxy.objects.get(
                        name=request.POST['proxy'])
                except ObjectDoesNotExist:
                    raise BadRequest("Proxy '%s' not found" %
                                     request.POST['proxy'])
            if 'qualifier' in request.POST:
                # an invalid qualifier would normally get caught when a target is saved
                # checking here to avoid creating a new Pid if the qualifier is invalid
                if not valid_qualifier(request.POST['qualifier']):
                    raise BadRequest(
                        "Qualifier '%s' contains invalid characters" %
                        request.POST['qualifier'])
                target_opts['qualify'] = request.POST['qualifier']

            # create the pid, and then save to mint the noid before target is created
            p = Pid(**pid_opts)
            p.save()
            _log_rest_action(request, p, ADDITION,
                             'Added pid:%s via rest api' % p.__unicode__())
            t = p.target_set.create(**target_opts)
            _log_rest_action(
                request, t, ADDITION,
                'Added target:%s for pid:%s via rest api' %
                (t.__unicode__(), p.__unicode__()))

            # return the resolvable url (purl/ark) for the new target
            return HttpResponse(t.get_resolvable_url(),
                                status=201)  # 201 Created

        except BadRequest as err:
            # return a response with status code 400, Bad Request
            return HttpResponseBadRequest('Error: %s' % err)

    # if request method is not POST, return 405 method not allowed
    return HttpResponseNotAllowed(['POST'])
Example #12
0
class ResolverTestCase(unittest.TestCase):
    def setUp(self):
        self.client = Client()

        # dependent objects to use for creating test pids
        self.domain = Domain(name="test domain")
        self.domain.save()
        self.user = User(username="******")
        self.user.set_password("pidpass")
        self.user.save()
        self.policy = Policy(commitment="Not Guaranteed")
        self.policy.save()

        # test pids: one ark & one purl
        self.ark = Pid(name="testark", domain=self.domain, creator=self.user,
            editor=self.user, type="Ark", policy=self.policy)
        self.ark.save()
        self.ark.target_set.create(uri="http://some.uri")
        self.ark.target_set.create(qualify="q", uri="http://other.uri")
        self.purl = Pid(name="testpurl", domain=self.domain, creator=self.user,
            editor=self.user, type="Purl")
        self.purl.save()
        self.purl.target_set.create(uri="http://some.uri")
        self.proxy = Proxy(name="testproxy", transform="http://proxy.com?url=")
        self.proxy.save()

    def tearDown(self):
        self.proxy.delete()
        self.purl.delete()
        self.ark.delete()
        self.user.delete()
        self.domain.delete()
        self.policy.delete()

    def test_resolve_purl(self):
        response = self.client.get("/" + self.purl.pid)
        self.assert_(isinstance(response, HttpResponseRedirect), "response to resolve purl is a redirect")
        self.assertEqual(self.purl.primary_target_uri(), response["Location"])

    def test_resolve_proxied_purl(self):
        # add a proxy to the purl target
        t = self.purl.primary_target()
        t.proxy = self.proxy
        t.save()
        response = self.client.get("/" + self.purl.pid)
        self.assert_(isinstance(response, HttpResponseRedirect), "resonse to resolve purl is a redirect")
        self.assertEqual(self.proxy.transform + self.purl.primary_target_uri(), response["Location"])

    def test_resolve_ark(self):
        response = self.client.get("/ark:/" + settings.PID_ARK_NAAN + '/' + self.ark.pid)
        self.assert_(isinstance(response, HttpResponseRedirect), "response to resolver ark is a redirect")
        self.assertEqual(self.ark.primary_target_uri(), response["Location"])

    def test_resolve_inactive_ark(self):
        for t in self.ark.target_set.all():
            t.active = False
            t.save()

        response = self.client.get("/ark:/" + settings.PID_ARK_NAAN + '/' + self.ark.pid)
        self.assertEqual(404, response.status_code)

    def test_resolve_inactive_purl(self):
        for t in self.purl.target_set.all():
            t.active = False
            t.save()

        response = self.client.get("/" + self.purl.pid)
        self.assertEqual(404, response.status_code)

    def test_resolve_qualified_ark(self):
        response = self.client.get("/ark:/" + settings.PID_ARK_NAAN + '/' + self.ark.pid + "/q")
        self.assert_(isinstance(response, HttpResponseRedirect), "response to resolve qualified ark is a redirect")
        self.assertEqual(self.ark.target_set.get(qualify='q').uri, response["Location"])

    def test_notfound_purl(self):
        response = self.client.get("/boguspurl")
        self.assert_(isinstance(response, HttpResponseNotFound), "response for non-existent purl is not found")
        self.assertEqual(404, response.status_code)

    def test_notfound_ark(self):
        response = self.client.get("/ark:/34235/bogusark")
        self.assert_(isinstance(response, HttpResponseNotFound), "response for non-existent ark is not found")
        self.assertEqual(404, response.status_code)

    def test_ark_metadata(self):
        # NOTE: can't currently test using django test client because of limitations recognizing ? with no query string
        #response = self.client.get("/ark:/" + settings.PID_ARK_NAAN + '/' + self.ark.pid + "?")

        request = HttpRequest()
        request.META["REQUEST_URI"] = "/ark:/" + settings.PID_ARK_NAAN + '/' + self.ark.pid + "?"
        response = ark_metadata(request, self.ark.pid)
        self.assert_(isinstance(response, HttpResponse), "ark_metadata returns HttpResponse")
        for header in response.items():
            if header[0] == 'Content-Type':
                self.assertEqual(header[1], "text/plain", "response has text/plain mimetype")
        lines = response.content.splitlines()
        self.assertEqual("erc:", lines[0], "response is in ERC format")
        what = lines[1].split(":", 1)       # only split once
        self.assertEqual("what", what[0])
        self.assertEqual(self.ark.name, what[1].strip(), "ark name is listed as what:")
        where = lines[2].split(":", 1)      # only split once
        self.assertEqual("where", where[0])
        self.assertEqual(self.ark.primary_target_uri(), where[1].strip(),
			"ark target url " + self.ark.primary_target_uri() + " listed as location; got " + where[1].strip())

    def test_ark_policy(self):
        response = self.client.get("/ark:/" + settings.PID_ARK_NAAN + '/' + self.ark.pid + "??")
        self.assert_(isinstance(response, HttpResponse), "response for ark?? is an HttpResponse")
        for header in response.items():
            if header[0] == 'Content-Type':
                self.assertEqual(header[1], "text/plain", "response to ark?? is plain text");
        self.assert_("erc-support:" in response.content, "content includes 'erc-support:'")
        sections = response.content.split("erc-support:\n")
        lines = sections[1].splitlines()
        what = lines[0].split(":", 1)
        self.assertEqual("what", what[0])
        self.assertEqual(self.policy.commitment, what[1].strip(),
                         "what: value should be policy commitment %s, got %s" % (self.policy.commitment, what[1].strip()))
        when = lines[1].split(":", 1)
        self.assertEqual("when", when[0])
        create_date = self.policy.created_at.strftime("%Y%m%d")
        self.assertEqual(create_date, when[1].strip(),
                         "when: value should be policy creation date " + create_date + ", got " + when[1].strip())

    def test_resolve_and_ark_normalization(self):
        # test that url rules follow ark character repertoires

        # should resolve just the same as an unqualified ark with a / or . on the end
        response = self.client.get("/ark:/" + settings.PID_ARK_NAAN + '/' + self.ark.pid + "/")
        self.assert_(isinstance(response, HttpResponseRedirect), "response for ark/ is a redirect")
        self.assertEqual(self.ark.primary_target_uri(), response["Location"],
            "redirect location for ark/ is primary target")
        response = self.client.get("/ark:/" + settings.PID_ARK_NAAN + '/' + self.ark.pid + ".")
        self.assert_(isinstance(response, HttpResponseRedirect), "response for ark. is a redirect")
        self.assertEqual(self.ark.primary_target_uri(), response["Location"],
            "redirect location for ark. is primary target")

        # hyphens in the pid should be ignored
        hyphenated_pid = '-'.join(self.ark.pid)
        response = self.client.get("/ark:/" + settings.PID_ARK_NAAN + '/' + hyphenated_pid)
        self.assert_(isinstance(response, HttpResponseRedirect), "response for hyphenated pid is a redirect")
        self.assertEqual(self.ark.primary_target_uri(), response["Location"],
            "redirect location for hyphenated ark is primary target")

        # qualifier with hyphens
        target = self.ark.target_set.create(qualify="abc", uri="http://weirdos.net")
        response = self.client.get("/ark:/" + settings.PID_ARK_NAAN + '/' + self.ark.pid + '/' +
            '-'.join(target.qualify))
        self.assert_(isinstance(response, HttpResponseRedirect),
            "response for hyphenated qualifier is a redirect")
        self.assertEqual(target.uri, response["Location"], "hyphens in qualifier ignored when resolving")

        # . or / at end of qualifier should be ignored
        response = self.client.get("/ark:/" + settings.PID_ARK_NAAN + '/' + self.ark.pid +
            '/' + target.qualify + '.')
        self.assert_(isinstance(response, HttpResponseRedirect),
            "response for qualifier with following '.' is a redirect")
        self.assertEqual(target.uri, response["Location"], "'.' at end of qualifier ignored when resolving")

        response = self.client.get("/ark:/" + settings.PID_ARK_NAAN + '/' + self.ark.pid +
            '/' + target.qualify + '/')
        self.assert_(isinstance(response, HttpResponseRedirect),
            "response for qualifier with following '/' is a redirect")
        self.assertEqual(target.uri, response["Location"], "'/' at end of qualifier ignored when resolving")

    def test_resolve_invalid_ark(self):
        # more character repertoire stuff - test allowed characters in noid & qualifier
        response = self.client.get("/ark:/" + settings.PID_ARK_NAAN + '/123!')
        self.assert_(isinstance(response, HttpResponseNotFound),
            "response for ark with invalid characters is not found")

        # characters included in the allowed set
        self.ark.target_set.create(qualify="q=@_$", uri="http://weirdos.net")
        response = self.client.get("/ark:/" + settings.PID_ARK_NAAN + '/' + self.ark.pid + '/q=@_$')
        self.assert_(isinstance(response, HttpResponseRedirect))
        self.assertEqual("http://weirdos.net", response["Location"])

        # qualifier with invalid character
        response = self.client.get("/ark:/" + settings.PID_ARK_NAAN + '/' + self.ark.pid + '/ab^')
        self.assert_(isinstance(response, HttpResponseNotFound),
            "response for ark with invalid characters in qualifier is not found")
Example #13
0
def create_pid(request, type):
    """On POST, create a new ARK or PURL.  On successful creation, returns a
    response with status code 201 (Created), and response content is the resolvables
    url for the newly minted ARK or PURL.  If required parameters are missing
    or any parameters are invalid (e.g., referencing a Proxy or Policy that does
    not exist), the returned response will have a status code 400 (Bad Request),
    and the content of the response will be an explanatory message.

    Supported POST parameters:
        * domain - REQUIRED; domain should be in URI resource format, e.g.
          http://pid.emory.edu/domains/1/
        * target_uri - REQUIRED; URL that the new ARK or PURL should resolve to
        * name - label or title for the new pid
        * external_system_id - external system name
        * external_system_key - key or identifier in the specified external system
        * policy - policy by name (if this pid needs a different policy from its
          domain)
        * proxy - proxy to use when resolving target url; specify by name
        * qualifier - target should be created with the specified target; **ARK only**

    :param type: type of pid to create - ark or purl

    Example create urls::

        http://pid.emory.edu/ark/ - create a new ARK
        http://pid.emory.edu/purl/ - create a new PURL

    """
    if request.method == "POST":
        # TODO: require ssl ?
        if not request.user.is_authenticated():
            # 401 unauthorized - not logged in or invalid credentials
            return HttpResponseUnauthorized(BASIC_AUTH_REALM)
        elif not request.user.has_perm("pid.add_pid"):
            # 403 Forbidden - logged in but insufficient permissions
            return HttpResponseForbidden()

        try:
            # if required fields are not present, return an error message
            if "domain" not in request.POST or "target_uri" not in request.POST:
                raise BadRequest("domain and target_uri are required")
            # incompatible options - qualifier only makes sense for purls
            if "qualifier" in request.POST and type == "purl":
                raise BadRequest("Purl targets can not have qualifiers")

            # domain should be passed in as resource URI - resolve to model instance
            domain = _domain_from_uri(request.POST["domain"])

            # assemble the data for creating the new pid
            # - required fields
            pid_opts = {
                "type": type.title(),  # url uses lower case, model requires title case
                "domain": domain,
                "creator_id": request.user.id,
                "editor_id": request.user.id,
            }
            # - optional fields
            if "name" in request.POST:
                pid_opts["name"] = request.POST["name"]
            # could you have an external system id and not a ext-sys key? or vice versa?
            if "external_system_id" in request.POST:
                try:
                    pid_opts["ext_system"] = ExtSystem.objects.get(name=request.POST["external_system_id"])
                except ObjectDoesNotExist:
                    raise BadRequest("External System '%s' not found" % request.POST["external_system_id"])
            if "external_system_key" in request.POST:
                pid_opts["ext_system_key"] = request.POST["external_system_key"]
            if "policy" in request.POST:
                try:
                    pid_opts["policy"] = Policy.objects.get(title=request.POST["policy"])
                except ObjectDoesNotExist:
                    raise BadRequest("Policy '%s' not found" % request.POST["policy"])

            # target can't be created until after the noid is minted
            # - init target options before creating pid to be sure they are valid
            #   (i.e., if a proxy is specified, it exists)
            target_opts = {"uri": request.POST["target_uri"]}
            if "proxy" in request.POST:
                try:
                    target_opts["proxy"] = Proxy.objects.get(name=request.POST["proxy"])
                except ObjectDoesNotExist:
                    raise BadRequest("Proxy '%s' not found" % request.POST["proxy"])
            if "qualifier" in request.POST:
                # an invalid qualifier would normally get caught when a target is saved
                # checking here to avoid creating a new Pid if the qualifier is invalid
                if not valid_qualifier(request.POST["qualifier"]):
                    raise BadRequest("Qualifier '%s' contains invalid characters" % request.POST["qualifier"])
                target_opts["qualify"] = request.POST["qualifier"]

            # create the pid, and then save to mint the noid before target is created
            p = Pid(**pid_opts)
            p.save()
            _log_rest_action(request, p, ADDITION, "Added pid:%s via rest api" % p.__unicode__())
            t = p.target_set.create(**target_opts)
            _log_rest_action(
                request, t, ADDITION, "Added target:%s for pid:%s via rest api" % (t.__unicode__(), p.__unicode__())
            )

            # return the resolvable url (purl/ark) for the new target
            return HttpResponse(t.get_resolvable_url(), status=201)  # 201 Created

        except BadRequest as err:
            # return a response with status code 400, Bad Request
            return HttpResponseBadRequest("Error: %s" % err)

    # if request method is not POST, return 405 method not allowed
    return HttpResponseNotAllowed(["POST"])
Example #14
0
 def test_mint_noid(self):
     noid = Pid.mint_noid()
     self.assertNotEqual(None, noid, "value returned by mint_noid should not be None")
     self.assert_(re.compile("^[a-z0-9]+$").match(noid),
                  "generated noid '" + noid + "' matches expected pattern")
Example #15
0
class TargetTestCase(TestCase):
    fixtures = ['pids.json']

    def setUp(self):
        # dependent objects to use for creating test pids
        self.domain = Domain(name="test domain")
        self.domain.save()
        self.user = User(username="******")
        self.user.set_password("pidpass")
        self.user.save()

        self.ark = Pid(name="testark", domain=self.domain, creator=self.user,
            editor=self.user, type="Ark")
        self.ark.save()
        self.purl = Pid(name="testpurl", domain=self.domain, creator=self.user,
            editor=self.user, type="Purl")
        self.purl.save()

        self.proxy = Proxy(name="testproxy", transform="proxy.com?url=")
        self.proxy.save()

    def tearDown(self):
        self.domain.delete()
        self.user.delete()
        self.ark.delete()
        self.purl.delete()
        self.proxy.delete()

    def test_get_resolvable_url(self):
        t = self.ark.target_set.create(uri="some.uri")
        # test against expected ark url from settings in config file
        base_ark = settings.PID_RESOLVER_URL + "/ark:/" + settings.PID_ARK_NAAN
        self.assertEqual(base_ark + "/" + self.ark.pid, t.get_resolvable_url())
        t.qualify = ""
        self.assertEqual(base_ark + "/" + self.ark.pid, t.get_resolvable_url())
        t.qualify = "?"
        self.assertEqual(base_ark + "/" + self.ark.pid + "/?", t.get_resolvable_url())
        t.qualify = "some/long/qualifier.txt"
        self.assertEqual(base_ark + "/" + self.ark.pid + "/some/long/qualifier.txt", t.get_resolvable_url())

        t = self.purl.target_set.create(uri="some.uri")
        self.assertEqual(settings.PID_RESOLVER_URL + "/" + self.purl.pid, t.get_resolvable_url())

    def test_token_replacement(self):
        self.ark.target_set.create(uri="http://some.url/with/" + settings.PID_REPLACEMENT_TOKEN)
        self.assertEqual("http://some.url/with/" + self.ark.pid, self.ark.primary_target().uri)

    def test_invalid_qualifier(self):
        self.assertRaises(Exception, self.ark.target_set.create,
            "attempting to save a target with invalid qualifiers raises an exception",
             qualify='q^', uri="no.uri",)

    def test_get_policy(self):
        # top-level domain
        domain = Domain.objects.get(pk=1)
        p = domain.get_policy()
        self.assert_(isinstance(p, Policy), "domain get_policy returns Policy object")
        self.assertEqual(p, domain.policy)

        #  with no explicit policy
        collection = Domain.objects.get(pk=4)
        self.assertEqual(collection.policy, None, "collection has no policy")
        p = collection.get_policy()
        self.assert_(isinstance(p, Policy), "collection get_policy returns Policy object")
        self.assertEqual(p, collection.parent.policy, "collection get_policy returns parent domain's policy")

        # collection with explicit policy different from parent domain
        collection = Domain.objects.get(pk=2)
        self.assert_(isinstance(collection.policy, Policy), "collection has its own policy")
        p = collection.get_policy()
        self.assert_(isinstance(p, Policy), "collection get_policy returns Policy object")
        self.assertEqual(p, collection.policy, "collection get_policy returns collection's policy")
        self.assertNotEqual(p, collection.parent.policy, "collection get_policy returns collection's policy")
Example #16
0
class PidTestCase(TestCase):
    fixtures = ['pids.json']

    def setUp(self):
        # dependent objects to use for creating test pids
        self.domain = Domain(name="test domain")
        self.domain.save()
        self.user = User(username="******")
        self.user.set_password("pidpass")
        self.user.save()

        # test pids: one ark & one purl
        self.ark = Pid(name="testark", domain=self.domain, creator=self.user,
            editor=self.user, type="Ark")
        self.ark.save()
        self.purl = Pid(name="testpurl", domain=self.domain, creator=self.user,
            editor=self.user, type="Purl")
        self.purl.save()

    def tearDown(self):
        self.domain.delete()
        self.user.delete()
        self.ark.delete()
        self.purl.delete()

    def test_mint_noid(self):
        noid = Pid.mint_noid()
        self.assertNotEqual(None, noid, "value returned by mint_noid should not be None")
        self.assert_(re.compile("^[a-z0-9]+$").match(noid),
                     "generated noid '" + noid + "' matches expected pattern")

    def test_primary_target(self):
        self.assertEqual(None, self.ark.primary_target())
        self.assertEqual(None, self.purl.primary_target())
        purl_target = self.purl.target_set.create(uri="some.uri")
        self.assertEqual(purl_target, self.purl.primary_target())
        ark_target = self.ark.target_set.create(uri="some.other.uri")
        ark_qual_target = self.ark.target_set.create(uri="some.other.uri/foo", qualify='q')
        self.assertEqual(ark_target, self.ark.primary_target())

    def test_is_valid__purl(self):
        self.assert_(self.purl.is_valid(), "purl with no targets is valid")
        self.purl.target_set.create(uri="some.uri")
        self.assert_(self.purl.is_valid(), "purl with single unqualified target is valid")
        self.purl.primary_target().qualify = "qual"
        self.assertRaises(Exception, self.purl.is_valid, "purl with single qualified target is invalid")
        self.purl.target_set.get().qualify = ""
        self.purl.target_set.create(qualify='q', uri="no.uri")
        self.assertRaises(Exception, self.purl.is_valid, "purl with multiple targets is invalid")

    def test_is_valid__ark(self):
        self.assert_(self.ark.is_valid(), "ark with no targets is valid")
        self.ark.target_set.create(uri="http://some.uri")
        self.assert_(self.ark.is_valid(), "ark with one unqualified target is valid")
        self.ark.target_set.create(qualify="q", uri="http://other.uri")
        self.assert_(self.ark.is_valid(), "ark with two targets is valid")

        self.ark.target_set.create(qualify="qual", uri="http://some.url", proxy=None)
        self.assert_(self.ark.is_valid(), "ark with two targets is valid")

        for t in self.ark.target_set.all():
            t.qualify = "q"
        self.assertRaises(Exception, self.ark.is_valid, "ark with duplicate qualifiers is invalid")

    def test_purl_url(self):
        # url when there is no target
        self.assertEqual('', self.purl.url(),
            "url for purl with no target should be '', got " + self.purl.url())
        # now add a target
        self.purl.target_set.create(uri="some.uri")
        self.assertEqual(settings.PID_RESOLVER_URL + "/" + self.purl.pid, self.purl.url(),
            "url for purl with target should be " + settings.PID_RESOLVER_URL + "/" +
            self.purl.pid + ", got " + self.purl.url())

    def test_ark_url(self):
        # url when there is no target
        self.assertEqual('', self.ark.url(),
            "url for ark with no target should be '', got " + self.ark.url())
        # add a qualified target (no unqualified/primary target)
        self.ark.target_set.create(qualify="q", uri="http://ti.ny")
        self.assertEqual(settings.PID_RESOLVER_URL + "/ark:/" + settings.PID_ARK_NAAN + "/" +
            self.ark.pid + "/q", self.ark.url(), "url for ark with no primary target should be " +
            settings.PID_RESOLVER_URL + "/ark:/" + settings.PID_ARK_NAAN + "/" +
            self.ark.pid + "/q , got " + self.ark.url())
        # add an unqualified target
        self.ark.target_set.create(uri="http://wh.ee")
        self.assertEqual(settings.PID_RESOLVER_URL + "/ark:/" + settings.PID_ARK_NAAN + "/" +
            self.ark.pid, self.ark.url(), "url for ark with primary target should be " +
            settings.PID_RESOLVER_URL + "/ark:/" + settings.PID_ARK_NAAN + "/" +
            self.ark.pid + ", got " + self.ark.url())

    def test_get_policy(self):
        # pid with explicit policy set
        pid = Pid.objects.get(pk=1)
        p = pid.get_policy()
        self.assert_(isinstance(p, Policy), "Pid get_policy returns Policy object")
        self.assertEqual(p, pid.policy, "get_policy response is Pid policy")
        self.assertNotEqual(p, pid.domain.policy, "get_policy response is different than domain policy")

        # pid with no explicit policy - inherits from domain
        pid = Pid.objects.get(pk=2)
        self.assertEqual(pid.policy, None, "test pid has no explicit policy")
        p = pid.get_policy()
        self.assert_(isinstance(p, Policy), "pid get_policy returns Policy object")
        self.assertEqual(p, pid.domain.policy, "pid get_policy returns domain policy")

        # inactive pid returns inactive policy
        pid = Pid.objects.get(pk=2)
        for t in pid.target_set.all():
            t.active = False
            t.save()
        self.assertEquals(pid.is_active(), False)

        p = Policy.objects.get(title__exact='Inactive Policy')
        self.assertEquals(pid.get_policy(), p)

    def test_url_link(self):
        self.purl.target_set.create(uri="some.uri")
        url = settings.PID_RESOLVER_URL + "/" + self.purl.pid
        self.assert_(re.compile('^<a [^>]*href=[\'"]' + url + '[\'"]>' + url + '</a>$').match(self.purl.url_link()),
                     "url link for purl with target should match pattern for link with "
                     + url + ", got " + self.purl.url_link())

    def test_is_active(self):
        # setup creates ark/purl with no targets, so they are inactive
        self.assertFalse(self.ark.is_active())
        self.assertFalse(self.purl.is_active())

        purl_target = self.purl.target_set.create(uri="some.uri")
        ark_target = self.ark.target_set.create(uri="some.other.uri")
        self.assertTrue(self.ark.is_active())
        self.assertTrue(self.purl.is_active())

        purl_target.active = False
        purl_target.save()
        ark_target.active = False
        ark_target.save()

        self.assertFalse(self.ark.is_active())
        self.assertFalse(self.purl.is_active())

    @unittest.skip    # linkcheck disabled in 0.10
    def test_target_linkcheck_status(self):
        # no links checked, status -> none
        self.assertEqual(None, self.ark.target_linkcheck_status(),
            'ARK with no targets should have linkcheck status of None (unknown)')
        self.assertEqual(None, self.purl.target_linkcheck_status(),
            'PURL with no targets should have linkcheck status of None (unknown)')

        # add targets; automatically get checked and will fail
        purl_target = self.purl.target_set.create(uri="some.uri")
        ark_target = self.ark.target_set.create(uri="some.other.uri")
        ark_qual_target = self.ark.target_set.create(uri="some.other.uri/foo", qualify='q')
        self.assertFalse(self.ark.target_linkcheck_status(),
            'ARK with invalid target uris should have linkcheck status of False (error)')
        self.assertFalse(self.purl.target_linkcheck_status(),
            'PURL with invalid target uri should have linkcheck status of False (error)')

        # manually update status to check valid / mixed
        purl_linkcheck = purl_target.linkcheck.first()
        purl_linkcheck.url.status = True
        purl_linkcheck.url.save()
        self.assertTrue(self.purl.target_linkcheck_status(),
            'purl with valid target uri should have link status True (ok)')
        # one valid ark target and one invalid is still invalid
        ark_linkcheck = ark_target.linkcheck.first()
        ark_linkcheck.url.status = True
        ark_linkcheck.url.save()
        self.assertFalse(self.ark.target_linkcheck_status(),
            'ark with one valid and one invalid target uri should have ' + \
            'link status False (error)')
        ark_qual_linkcheck = ark_qual_target.linkcheck.first()
        ark_qual_linkcheck.url.status = True
        ark_qual_linkcheck.url.save()
        self.assertTrue(self.ark.target_linkcheck_status(),
            'ark with all valid target uris should have link status True (ok)')