""" Tests for the gocookies code. """ import os import shutil import tempfile import unittest import urllib.request import pyrfc3339 from juju.client.gocookies import GoCookieJar # cookie_content holds the JSON contents of a Go-produced # cookie file (reformatted so it's not all on one line but # otherwise unchanged). cookie_content = """ [ { "CanonicalHost": "bar.com", "Creation": "2017-11-17T08:53:55.088820092Z", "Domain": "bar.com", "Expires": "2345-11-15T18:16:08Z", "HostOnly": true, "HttpOnly": false, "LastAccess": "2017-11-17T08:53:55.088822562Z", "Name": "bar", "Path": "/", "Persistent": true, "Secure": false, "Updated": "2017-11-17T08:53:55.088822562Z", "Value": "bar-value" }, { "CanonicalHost": "x.foo.com", "Creation": "2017-11-17T08:53:55.088814857Z", "Domain": "x.foo.com", "Expires": "2345-11-15T18:16:05Z", "HostOnly": true, "HttpOnly": false, "LastAccess": "2017-11-17T08:53:55.088884015Z", "Name": "foo", "Path": "/path", "Persistent": true, "Secure": false, "Updated": "2017-11-17T08:53:55.088814857Z", "Value": "foo-path-value" }, { "CanonicalHost": "x.foo.com", "Creation": "2017-11-17T08:53:55.088814857Z", "Domain": "foo.com", "Expires": "2345-11-15T18:16:06Z", "HostOnly": false, "HttpOnly": false, "LastAccess": "2017-11-17T08:53:55.088919437Z", "Name": "foo4", "Path": "/path", "Persistent": true, "Secure": false, "Updated": "2017-11-17T08:53:55.088814857Z", "Value": "foo4-value" }, { "CanonicalHost": "x.foo.com", "Creation": "2017-11-17T08:53:55.088790709Z", "Domain": "x.foo.com", "Expires": "2345-11-15T18:16:01Z", "HostOnly": true, "HttpOnly": false, "LastAccess": "2017-11-17T08:53:55.088884015Z", "Name": "foo", "Path": "/", "Persistent": true, "Secure": false, "Updated": "2017-11-17T08:53:55.088790709Z", "Value": "foo-value" }, { "CanonicalHost": "x.foo.com", "Creation": "2017-11-17T08:53:55.088790709Z", "Domain": "foo.com", "Expires": "2345-11-15T18:16:02Z", "HostOnly": false, "HttpOnly": false, "LastAccess": "2017-11-17T08:53:55.088919437Z", "Name": "foo1", "Path": "/", "Persistent": true, "Secure": false, "Updated": "2017-11-17T08:53:55.088790709Z", "Value": "foo1-value" }, { "CanonicalHost": "x.foo.com", "Creation": "2017-11-17T08:53:55.088790709Z", "Domain": "x.foo.com", "Expires": "2345-11-15T18:16:03Z", "HostOnly": true, "HttpOnly": false, "LastAccess": "2017-11-17T08:53:55.088850252Z", "Name": "foo2", "Path": "/", "Persistent": true, "Secure": true, "Updated": "2017-11-17T08:53:55.088790709Z", "Value": "foo2-value" }, { "CanonicalHost": "x.foo.com", "Creation": "2017-11-17T08:53:55.088790709Z", "Domain": "foo.com", "Expires": "2345-11-15T18:16:04Z", "HostOnly": false, "HttpOnly": false, "LastAccess": "2017-11-17T08:53:55.088919437Z", "Name": "foo3", "Path": "/", "Persistent": true, "Secure": false, "Updated": "2017-11-17T08:53:55.088790709Z", "Value": "foo3-value" } ] """ # cookie_content_queries holds a set of queries # that were automatically generated by running # the queries on the above cookie_content data # and printing the results. cookie_content_queries = [ ('http://x.foo.com', [ ('foo', 'foo-value'), ('foo1', 'foo1-value'), ('foo3', 'foo3-value'), ]), ('https://x.foo.com', [ ('foo', 'foo-value'), ('foo1', 'foo1-value'), ('foo2', 'foo2-value'), ('foo3', 'foo3-value'), ]), ('http://arble.foo.com', [ ('foo1', 'foo1-value'), ('foo3', 'foo3-value'), ]), ('http://arble.com', [ ]), ('http://x.foo.com/path/x', [ ('foo', 'foo-path-value'), ('foo4', 'foo4-value'), ('foo', 'foo-value'), ('foo1', 'foo1-value'), ('foo3', 'foo3-value'), ]), ('http://arble.foo.com/path/x', [ ('foo4', 'foo4-value'), ('foo1', 'foo1-value'), ('foo3', 'foo3-value'), ]), ('http://foo.com/path/x', [ ('foo4', 'foo4-value'), ('foo1', 'foo1-value'), ('foo3', 'foo3-value'), ]), ] class TestGoCookieJar(unittest.TestCase): def setUp(self): self.dir = tempfile.mkdtemp() def tearDown(self): shutil.rmtree(self.dir) def test_readcookies(self): jar = self.load_jar(cookie_content) self.assert_jar_queries(jar, cookie_content_queries) def test_roundtrip(self): jar = self.load_jar(cookie_content) filename2 = os.path.join(self.dir, 'cookies2') jar.save(filename=filename2) jar = GoCookieJar() jar.load(filename=filename2) self.assert_jar_queries(jar, cookie_content_queries) def test_expiry_time(self): content = '''[ { "CanonicalHost": "bar.com", "Creation": "2017-11-17T08:53:55.088820092Z", "Domain": "bar.com", "Expires": "2345-11-15T18:16:08Z", "HostOnly": true, "HttpOnly": false, "LastAccess": "2017-11-17T08:53:55.088822562Z", "Name": "bar", "Path": "/", "Persistent": true, "Secure": false, "Updated": "2017-11-17T08:53:55.088822562Z", "Value": "bar-value" } ]''' jar = self.load_jar(content) got_expires = tuple(jar)[0].expires want_expires = int(pyrfc3339.parse('2345-11-15T18:16:08Z').timestamp()) self.assertEqual(got_expires, want_expires) def load_jar(self, content): filename = os.path.join(self.dir, 'cookies') with open(filename, 'x') as f: f.write(content) jar = GoCookieJar() jar.load(filename=filename) return jar def assert_jar_queries(self, jar, queries): '''Assert that all the given queries (see cookie_content_queries) are satisfied when run on the given cookie jar. :param jar CookieJar: the cookie jar to query :param queries: the queries to run. ''' for url, want_cookies in queries: req = urllib.request.Request(url) jar.add_cookie_header(req) # We can't use SimpleCookie to find out what cookies # have been presented, because SimpleCookie # only allows one cookie with a given name, # so we naively parse the cookies ourselves, which # is OK because we know we don't have to deal # with any complex cases. cookie_header = req.get_header('Cookie') got_cookies = [] if cookie_header is not None: got_cookies = [ tuple(part.split('=')) for part in cookie_header.split('; ') ] got_cookies.sort() want_cookies = list(want_cookies) want_cookies.sort() self.assertEqual(got_cookies, want_cookies, msg='query {}; got {}; want {}'.format(url, got_cookies, want_cookies))