"""Tests for resync.resource.""" import unittest import re from resync.resource import Resource, ChangeTypeError class TestResource(unittest.TestCase): def test01_init(self): """Test __init__ method.""" # No uri = error self.assertRaises(ValueError, Resource) self.assertRaises(ValueError, Resource, timestamp=12) # Create with many params r1 = Resource(uri='a', timestamp=0, length=123, md5='aaa', sha1='bbb', sha256='ccc', mime_type='text/plain', change='updated', ts_datetime=1000, path='/a/b/c', ln={'x': 'y'}, ts_at=2000, ts_completed=3000, ts_from=4000, ts_until=5000) self.assertEqual(r1.uri, 'a') self.assertEqual(r1.timestamp, 0) self.assertEqual(r1.length, 123) self.assertEqual(r1.md5, 'aaa') self.assertEqual(r1.sha1, 'bbb') self.assertEqual(r1.sha256, 'ccc') self.assertEqual(r1.mime_type, 'text/plain') self.assertEqual(r1.change, 'updated') self.assertEqual(r1.ts_datetime, 1000) self.assertEqual(r1.path, '/a/b/c') self.assertEqual(r1.ln, {'x': 'y'}) self.assertEqual(r1.ts_at, 2000) self.assertEqual(r1.ts_completed, 3000) self.assertEqual(r1.ts_from, 4000) self.assertEqual(r1.ts_until, 5000) # Create r2 like r1 r2 = Resource(resource=r1) self.assertEqual(r2.uri, 'a') self.assertEqual(r2.timestamp, 0) self.assertEqual(r2.length, 123) self.assertEqual(r2.md5, 'aaa') self.assertEqual(r2.sha1, 'bbb') self.assertEqual(r2.sha256, 'ccc') self.assertEqual(r2.mime_type, 'text/plain') self.assertEqual(r2.change, 'updated') self.assertEqual(r2.ts_datetime, 1000) self.assertEqual(r2.path, '/a/b/c') self.assertEqual(r2.ln, {'x': 'y'}) def test02_equal(self): """Test equal method via = operator.""" # just uri r1 = Resource('a') r2 = Resource('a') self.assertEqual(r1, r1) self.assertEqual(r1, r2) # with timestamps r1 = Resource(uri='a', timestamp=1234.0) r2 = Resource(uri='a', timestamp=1234.0) self.assertEqual(r1, r1) self.assertEqual(r1, r2) # with lastmod instead of direct timestamp r1 = Resource('a') r1lm = '2012-01-01T00:00:00Z' r1.lastmod = r1lm r2 = Resource('a') for r2lm in ('2012', '2012-01', '2012-01-01', '2012-01-01T00:00Z', '2012-01-01T00:00:00Z', '2012-01-01T00:00:00.000000Z', '2012-01-01T00:00:00.000000000000Z', '2012-01-01T00:00:00.000000000001Z', # below resolution '2012-01-01T00:00:00.00+00:00', '2012-01-01T00:00:00.00-00:00', '2012-01-01T02:00:00.00-02:00', '2011-12-31T23:00:00.00+01:00' ): r2.lastmod = r2lm self.assertEqual(r1.timestamp, r2.timestamp, ('%s (%f) == %s (%f)' % ( r1lm, r1.timestamp, r2lm, r2.timestamp))) self.assertEqual(r1, r2) # with slight timestamp diff r1 = Resource('a') r1.lastmod = '2012-01-02T01:02:03Z' r2 = Resource('a') r2.lastmod = '2012-01-02T01:02:03.99Z' self.assertNotEqual(r1.timestamp, r2.timestamp) self.assertEqual(r1, r2) # now with too much time diff r1 = Resource('a', lastmod='2012-01-11') r2 = Resource('a', lastmod='2012-01-22') self.assertNotEqual(r1, r2) # different uris r1 = Resource('a') r2 = Resource('b') self.assertNotEqual(r1, r2) # same and different lengths r1 = Resource('a', length=1234) r2 = Resource('a', length=4321) self.assertNotEqual(r1, r2) r2.length = r1.md5 self.assertEqual(r1, r2) # same and different md5 r1.md5 = "3006f84272f2653a6cf5ec3af8f0d773" r2.md5 = "3006f84272f2653a6cf5ec3af8f00000" self.assertNotEqual(r1, r2) r2.md5 = r1.md5 self.assertEqual(r1, r2) # same and different sha1 r1.sha1 = "3be0f3af2aa4656ce38e0cef305c6eb2af4385d4" r2.sha1 = "555" self.assertNotEqual(r1, r2) r2.sha1 = r1.sha1 self.assertEqual(r1, r2) # same and different sha256 r1.sha256 = "f41094ad47ef3e93ec1021bfa40f4bf0185f1bf897533638ae5358b61713f84a" r2.sha256 = "fab" self.assertNotEqual(r1, r2) r2.sha256 = r1.sha256 self.assertEqual(r1, r2) def test04_bad_lastmod(self): def setlastmod(r, v): r.lastmod = v r = Resource('4') # Bad formats self.assertRaises(ValueError, setlastmod, r, "bad_lastmod") self.assertRaises(ValueError, setlastmod, r, "") self.assertRaises(ValueError, setlastmod, r, "2012-13-01") self.assertRaises(ValueError, setlastmod, r, "2012-12-32") self.assertRaises(ValueError, setlastmod, r, "2012-11-01T10:10:60") self.assertRaises(ValueError, setlastmod, r, "2012-11-01T10:10:59.9x") # Valid ISO8601 but not alloed in W3C Datetime self.assertRaises(ValueError, setlastmod, r, "2012-11-01T01:01:01") self.assertRaises(ValueError, setlastmod, r, "2012-11-01 01:01:01Z") self.assertRaises(ValueError, setlastmod, r, "2012-11-01T01:01:01+0000") self.assertRaises(ValueError, setlastmod, r, "2012-11-01T01:01:01-1000") def test05_lastmod_roundtrips(self): r = Resource('a') r.lastmod = '2012-03-14' self.assertEqual(r.lastmod, '2012-03-14T00:00:00Z') r.lastmod = '2012-03-14T00:00:00+00:00' # print r.timestamp self.assertEqual(r.lastmod, '2012-03-14T00:00:00Z') r.lastmod = '2012-03-14T00:00:00-00:00' # print r.timestamp self.assertEqual(r.lastmod, '2012-03-14T00:00:00Z') r.lastmod = '2012-03-14T18:37:36Z' # print r.timestamp self.assertEqual(r.lastmod, '2012-03-14T18:37:36Z') def test06_str(self): r1 = Resource('abc', lastmod='2012-01-01') self.assertTrue(re.match(r"\[ abc \| 2012-01-01T", str(r1))) def test07_repr(self): r1 = Resource('def', lastmod='2012-01-01') self.assertEqual(repr(r1), "{'uri': 'def', 'timestamp': 1325376000}") def test08_hash(self): """Test hash getter and setters.""" r1 = Resource('abcd') r1.md5 = "some_md5" r1.sha1 = "some_sha1" r1.sha256 = "some_sha256" self.assertEqual(r1.md5, "some_md5") self.assertEqual(r1.sha1, "some_sha1") self.assertEqual(r1.sha256, "some_sha256") self.assertEqual(r1.hash, "md5:some_md5 sha-1:some_sha1 sha-256:some_sha256") r2 = Resource('def') r2.hash = "md5:ddd" self.assertEqual(r2.md5, 'ddd') self.assertEqual(r2.sha1, None) r2.hash = "sha-1:eee" self.assertEqual(r2.md5, None) self.assertEqual(r2.sha1, 'eee') r2.hash = "md5:fff sha-1:eee sha-256:ggg" self.assertEqual(r2.md5, 'fff') self.assertEqual(r2.sha1, 'eee') self.assertEqual(r2.sha256, 'ggg') # bogus value will reset r2.hash = 11 self.assertEqual(r2.md5, None) self.assertEqual(r2.sha1, None) self.assertEqual(r2.sha256, None) # string withough : will raise error with self.assertRaises(ValueError): r2.hash = "no-colon" # dupe with self.assertRaises(ValueError): r2.hash = "md5:aaa md5:bbb" # unknown with self.assertRaises(ValueError): r2.hash = "sha999:aaa" def test09_changetypeerror(self): r1 = Resource('a') self.assertEqual(r1.change, None) r1.change = 'deleted' self.assertEqual(r1.change, 'deleted') self.assertRaises(ChangeTypeError, Resource, 'a', change="bad") # disable checking ct = Resource.CHANGE_TYPES Resource.CHANGE_TYPES = False r1 = Resource('a', change="bad") self.assertEqual(r1.change, 'bad') Resource.CHANGE_TYPES = ct def test10_md_at_roundtrips(self): r = Resource('a') r.md_at = '2013-03-14' self.assertEqual(r.md_at, '2013-03-14T00:00:00Z') r.md_at = '2013-03-14T00:00:00+00:00' self.assertEqual(r.md_at, '2013-03-14T00:00:00Z') r.md_at = '2013-03-14T00:00:00-00:00' self.assertEqual(r.md_at, '2013-03-14T00:00:00Z') r.md_at = '2013-03-14T18:37:36Z' self.assertEqual(r.md_at, '2013-03-14T18:37:36Z') def test11_md_completed_roundtrips(self): r = Resource('a') r.md_completed = '2013-04-14' self.assertEqual(r.md_completed, '2013-04-14T00:00:00Z') r.md_completed = '2013-04-14T00:00:00+00:00' self.assertEqual(r.md_completed, '2013-04-14T00:00:00Z') r.md_completed = '2013-04-14T00:00:00-00:00' self.assertEqual(r.md_completed, '2013-04-14T00:00:00Z') r.md_completed = '2013-04-14T18:37:36Z' self.assertEqual(r.md_completed, '2013-04-14T18:37:36Z') def test12_timevalues(self): r = Resource(uri='tv', lastmod="2000-01-01", md_at="2000-01-02", md_completed="2000-01-03", md_from="2000-01-04", md_until="2000-01-05") self.assertEqual(r.lastmod, '2000-01-01T00:00:00Z') self.assertEqual(r.md_at, '2000-01-02T00:00:00Z') self.assertEqual(r.md_completed, '2000-01-03T00:00:00Z') self.assertEqual(r.md_from, '2000-01-04T00:00:00Z') self.assertEqual(r.md_until, '2000-01-05T00:00:00Z') def test13_mime_type(self): r = Resource(uri='tv1', mime_type='text/plain') self.assertEqual(r.mime_type, 'text/plain') r.mime_type = None self.assertEqual(r.mime_type, None) r = Resource(uri='tv2') self.assertEqual(r.mime_type, None) def test14_datetime(self): # v1.1 adds a datetime attribute r = Resource(uri='dt1') self.assertEqual(r.datetime, None) r = Resource(uri='dt2', datetime='2000-01-04T00:00:00Z') self.assertEqual(r.datetime, '2000-01-04T00:00:00Z') def test15_link(self): """Test link link_href and link_set methods.""" r = Resource(uri='ln1') self.assertEqual(r.link('up'), None) self.assertEqual(r.link_href('up'), None) r.link_set('up', 'uri:up') self.assertEqual(r.link('up'), {'rel': 'up', 'href': 'uri:up'}) self.assertEqual(r.link_href('up'), 'uri:up') r.link_set('down', 'uri:down') self.assertEqual(r.link('down'), {'rel': 'down', 'href': 'uri:down'}) self.assertEqual(r.link_href('down'), 'uri:down') r.link_set('up', 'uri:up2') self.assertEqual(r.link('up'), {'rel': 'up', 'href': 'uri:up2'}) r.link_add('up', 'uri:up3') self.assertEqual(r.link('up'), {'rel': 'up', 'href': 'uri:up2'}) # still get first self.assertEqual(r.ln, [{'rel': 'up', 'href': 'uri:up2'}, {'href': 'uri:down', 'rel': 'down'}, {'rel': 'up', 'href': 'uri:up3'}]) def test16_specific_links(self): """Test setters/getters for specific link types.""" r = Resource(uri='laughing') r.describedby = 'uri:db' self.assertEqual(r.describedby, 'uri:db') r.up = 'uri:up' self.assertEqual(r.up, 'uri:up') r.index = 'uri:index' self.assertEqual(r.index, 'uri:index') r.contents = 'uri:ct' self.assertEqual(r.contents, 'uri:ct') def test17_basename(self): """Test basename property derived from uri.""" r = Resource(uri='http://example.org/any/complex/path/file') self.assertEqual(r.basename, 'file') r.uri = 'http://example.org/any/complex/path/' self.assertEqual(r.basename, '') r.uri = 'http://example.org' self.assertEqual(r.basename, '') def test18_str(self): """Test str method.""" self.assertEqual(str(Resource('uri:a')), '[ uri:a | None | None | None ]') self.assertEqual(str(Resource('uri:a', timestamp=0, length=999)), '[ uri:a | 1970-01-01T00:00:00Z | 999 | None ]') self.assertEqual(str(Resource('uri:a', timestamp=0, length=999, sha256='abcdef123')), '[ uri:a | 1970-01-01T00:00:00Z | 999 | abcdef123 ]') self.assertEqual(str(Resource('uri:a', change='updated', ts_datetime=3661)), '[ uri:a | None | None | None | updated @ 1970-01-01T01:01:01Z ]') self.assertEqual(str(Resource('uri:a', path='/a/b/c')), '[ uri:a | None | None | None | /a/b/c ]') def test19_change_type_error(self): """Test error from bad change type.""" cte = ChangeTypeError('unk') self.assertIn('ChangeTypeError: got unk, expected one of ', str(cte))