--- /dev/null
+"""
+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))