launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #24539
[Merge] ~cjwatson/lp-signing:refactor-webapi-tests into lp-signing:master
Colin Watson has proposed merging ~cjwatson/lp-signing:refactor-webapi-tests into lp-signing:master.
Commit message:
Refactor some repetitive webapi tests
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~cjwatson/lp-signing/+git/lp-signing/+merge/381501
TestClient.post now handles the setup of encrypted data a bit more flexibly, and the various post_* methods have better defaults. This allows most of the tests to specify just how they differ from a working request rather than having to repeat lots of things, which is more concise and easier to read.
--
Your team Launchpad code reviewers is requested to review the proposed merge of ~cjwatson/lp-signing:refactor-webapi-tests into lp-signing:master.
diff --git a/lp_signing/tests/test_webapi.py b/lp_signing/tests/test_webapi.py
index 84b5a9d..0201740 100644
--- a/lp_signing/tests/test_webapi.py
+++ b/lp_signing/tests/test_webapi.py
@@ -137,54 +137,41 @@ class TestGenerateView(TestCase):
self.nonce = Nonce.generate().nonce
store.commit()
+ def post_generate(self, json_data=None, **kwargs):
+ kwargs.setdefault("private_key", self.private_key)
+ kwargs.setdefault("nonce", self.nonce)
+ return self.fixture.client.post(
+ "/generate", json_data=json_data, **kwargs)
+
def test_unauthenticated(self):
- resp = self.fixture.client.post("/generate")
+ resp = self.post_generate(private_key=None)
self.assertThat(resp, HasAPIError("Request not authenticated"))
def test_undecodable_client_public_key(self):
- resp = self.fixture.client.post(
- "/generate",
- headers={
- "X-Client-Public-Key": "nonsense key",
- "X-Nonce": base64.b64encode(self.nonce).decode("UTF-8"),
- })
+ resp = self.post_generate(
+ headers={"X-Client-Public-Key": "nonsense key"})
self.assertThat(resp, HasAPIError("Cannot decode client public key"))
def test_undecodable_nonce(self):
- resp = self.fixture.client.post(
- "/generate",
- headers={
- "X-Client-Public-Key": self.private_key.public_key.encode(
- encoder=Base64Encoder).decode("UTF-8"),
- "X-Nonce": "nonsense nonce",
- })
+ resp = self.post_generate(headers={"X-Nonce": "nonsense nonce"})
self.assertThat(resp, HasAPIError("Cannot decode nonce"))
def test_nonce_already_used(self):
Nonce.check(self.nonce)
- resp = self.fixture.client.post(
- "/generate", private_key=self.private_key, nonce=self.nonce)
+ resp = self.post_generate()
self.assertThat(resp, HasAPIError("Invalid nonce"))
def assertNonceConsumed(self):
self.assertRaises(InvalidNonce, Nonce.check, self.nonce)
def test_unboxable_data(self):
- resp = self.fixture.client.post(
- "/generate",
- headers={
- "X-Client-Public-Key": self.private_key.public_key.encode(
- encoder=Base64Encoder).decode("UTF-8"),
- "X-Nonce": base64.b64encode(self.nonce).decode("UTF-8"),
- },
- data=b"data")
+ resp = self.post_generate(encrypted_data=b"data")
self.assertThat(resp, HasAPIError("Authentication failed"))
self.assertNonceConsumed()
def test_unregistered_private_key(self):
private_key = PrivateKey.generate()
- resp = self.fixture.client.post(
- "/generate", private_key=private_key, nonce=self.nonce)
+ resp = self.post_generate(private_key=private_key)
self.assertThat(resp, HasAPIError("Unregistered client public key"))
self.assertNonceConsumed()
@@ -192,28 +179,15 @@ class TestGenerateView(TestCase):
private_key = PrivateKey.generate()
box = Box(self.private_key, private_key.public_key)
message = box.encrypt(b"{}", self.nonce, encoder=Base64Encoder)
- resp = self.fixture.client.post(
- "/generate",
- headers={
- "X-Client-Public-Key": self.private_key.public_key.encode(
- encoder=Base64Encoder).decode("UTF-8"),
- "X-Nonce": message.nonce.decode("UTF-8"),
- },
- data=message.ciphertext)
+ resp = self.post_generate(encrypted_data=message.ciphertext)
self.assertThat(resp, HasAPIError("Authentication failed"))
self.assertNonceConsumed()
def test_no_json(self):
- resp = self.fixture.client.post(
- "/generate", private_key=self.private_key, nonce=self.nonce)
+ resp = self.post_generate()
self.assertThat(resp, HasAPIError("Error decoding JSON request body"))
self.assertNonceConsumed()
- def post_generate(self, json_data=None):
- return self.fixture.client.post(
- "/generate", json_data=json_data,
- private_key=self.private_key, nonce=self.nonce)
-
def test_missing_key_type(self):
resp = self.post_generate({"description": ""})
self.assertThat(
@@ -564,54 +538,39 @@ class TestSignView(TestCase):
self.nonce = Nonce.generate().nonce
store.commit()
+ def post_sign(self, json_data=None, **kwargs):
+ kwargs.setdefault("private_key", self.private_key)
+ kwargs.setdefault("nonce", self.nonce)
+ return self.fixture.client.post("/sign", json_data=json_data, **kwargs)
+
def test_unauthenticated(self):
- resp = self.fixture.client.post("/sign")
+ resp = self.post_sign(private_key=None)
self.assertThat(resp, HasAPIError("Request not authenticated"))
def test_undecodable_client_public_key(self):
- resp = self.fixture.client.post(
- "/sign",
- headers={
- "X-Client-Public-Key": "nonsense key",
- "X-Nonce": base64.b64encode(self.nonce).decode("UTF-8"),
- })
+ resp = self.post_sign(headers={"X-Client-Public-Key": "nonsense key"})
self.assertThat(resp, HasAPIError("Cannot decode client public key"))
def test_undecodable_nonce(self):
- resp = self.fixture.client.post(
- "/sign",
- headers={
- "X-Client-Public-Key": self.private_key.public_key.encode(
- encoder=Base64Encoder).decode("UTF-8"),
- "X-Nonce": "nonsense nonce",
- })
+ resp = self.post_sign(headers={"X-Nonce": "nonsense nonce"})
self.assertThat(resp, HasAPIError("Cannot decode nonce"))
def test_nonce_already_used(self):
Nonce.check(self.nonce)
- resp = self.fixture.client.post(
- "/sign", private_key=self.private_key, nonce=self.nonce)
+ resp = self.post_sign()
self.assertThat(resp, HasAPIError("Invalid nonce"))
def assertNonceConsumed(self):
self.assertRaises(InvalidNonce, Nonce.check, self.nonce)
def test_unboxable_data(self):
- resp = self.fixture.client.post(
- "/sign",
- headers={
- "X-Client-Public-Key": self.private_key.public_key.encode(
- encoder=Base64Encoder).decode("UTF-8"),
- "X-Nonce": base64.b64encode(self.nonce).decode("UTF-8"),
- },
- data=b"data")
+ resp = self.post_sign(encrypted_data=b"data")
self.assertThat(resp, HasAPIError("Authentication failed"))
self.assertNonceConsumed()
def test_unregistered_private_key(self):
private_key = PrivateKey.generate()
- resp = self.fixture.client.post(
- "/sign", private_key=private_key, nonce=self.nonce)
+ resp = self.post_sign(private_key=private_key)
self.assertThat(resp, HasAPIError("Unregistered client public key"))
self.assertNonceConsumed()
@@ -619,28 +578,15 @@ class TestSignView(TestCase):
private_key = PrivateKey.generate()
box = Box(self.private_key, private_key.public_key)
message = box.encrypt(b"{}", self.nonce, encoder=Base64Encoder)
- resp = self.fixture.client.post(
- "/sign",
- headers={
- "X-Client-Public-Key": self.private_key.public_key.encode(
- encoder=Base64Encoder).decode("UTF-8"),
- "X-Nonce": message.nonce.decode("UTF-8"),
- },
- data=message.ciphertext)
+ resp = self.post_sign(encrypted_data=message.ciphertext)
self.assertThat(resp, HasAPIError("Authentication failed"))
self.assertNonceConsumed()
def test_no_json(self):
- resp = self.fixture.client.post(
- "/sign", private_key=self.private_key, nonce=self.nonce)
+ resp = self.post_sign()
self.assertThat(resp, HasAPIError("Error decoding JSON request body"))
self.assertNonceConsumed()
- def post_sign(self, json_data=None):
- return self.fixture.client.post(
- "/sign", json_data=json_data,
- private_key=self.private_key, nonce=self.nonce)
-
def test_missing_key_type(self):
resp = self.post_sign(
{
@@ -1099,54 +1045,41 @@ class TestInjectView(TestCase):
store.commit()
+ def post_inject(self, json_data=None, index=0, **kwargs):
+ kwargs.setdefault("private_key", self.private_keys[index])
+ kwargs.setdefault("nonce", self.nonces[index])
+ return self.fixture.client.post(
+ "/inject", json_data=json_data, **kwargs)
+
def test_unauthenticated(self):
- resp = self.fixture.client.post("/inject")
+ resp = self.post_inject(private_key=None)
self.assertThat(resp, HasAPIError("Request not authenticated"))
def test_undecodable_client_public_key(self):
- resp = self.fixture.client.post(
- "/inject",
- headers={
- "X-Client-Public-Key": "nonsense key",
- "X-Nonce": base64.b64encode(self.nonces[0]).decode("UTF-8"),
- })
+ resp = self.post_inject(
+ headers={"X-Client-Public-Key": "nonsense key"})
self.assertThat(resp, HasAPIError("Cannot decode client public key"))
def test_undecodable_nonce(self):
- resp = self.fixture.client.post(
- "/inject",
- headers={
- "X-Client-Public-Key": self.private_keys[0].public_key.encode(
- encoder=Base64Encoder).decode("UTF-8"),
- "X-Nonce": "nonsense nonce",
- })
+ resp = self.post_inject(headers={"X-Nonce": "nonsense nonce"})
self.assertThat(resp, HasAPIError("Cannot decode nonce"))
def test_nonce_already_used(self):
Nonce.check(self.nonces[0])
- resp = self.fixture.client.post(
- "/inject", private_key=self.private_keys[0], nonce=self.nonces[0])
+ resp = self.post_inject()
self.assertThat(resp, HasAPIError("Invalid nonce"))
def assertNonceConsumed(self):
self.assertRaises(InvalidNonce, Nonce.check, self.nonces[0])
def test_unboxable_data(self):
- resp = self.fixture.client.post(
- "/inject",
- headers={
- "X-Client-Public-Key": self.private_keys[0].public_key.encode(
- encoder=Base64Encoder).decode("UTF-8"),
- "X-Nonce": base64.b64encode(self.nonces[0]).decode("UTF-8"),
- },
- data=b"data")
+ resp = self.post_inject(encrypted_data=b"data")
self.assertThat(resp, HasAPIError("Authentication failed"))
self.assertNonceConsumed()
def test_unregistered_private_key(self):
private_key = PrivateKey.generate()
- resp = self.fixture.client.post(
- "/inject", private_key=private_key, nonce=self.nonces[0])
+ resp = self.post_inject(private_key=private_key)
self.assertThat(resp, HasAPIError("Unregistered client public key"))
self.assertNonceConsumed()
@@ -1154,28 +1087,15 @@ class TestInjectView(TestCase):
private_key = PrivateKey.generate()
box = Box(self.private_keys[0], private_key.public_key)
message = box.encrypt(b"{}", self.nonces[0], encoder=Base64Encoder)
- resp = self.fixture.client.post(
- "/inject",
- headers={
- "X-Client-Public-Key": self.private_keys[0].public_key.encode(
- encoder=Base64Encoder).decode("UTF-8"),
- "X-Nonce": message.nonce.decode("UTF-8"),
- },
- data=message.ciphertext)
+ resp = self.post_inject(encrypted_data=message.ciphertext)
self.assertThat(resp, HasAPIError("Authentication failed"))
self.assertNonceConsumed()
def test_no_json(self):
- resp = self.fixture.client.post(
- "/inject", private_key=self.private_keys[0], nonce=self.nonces[0])
+ resp = self.post_inject()
self.assertThat(resp, HasAPIError("Error decoding JSON request body"))
self.assertNonceConsumed()
- def post_inject(self, json_data=None, index=0):
- return self.fixture.client.post(
- "/inject", json_data=json_data,
- private_key=self.private_keys[index], nonce=self.nonces[index])
-
def test_missing_key_type(self):
resp = self.post_inject({"private-key": "",
"public-key": "",
diff --git a/lp_signing/tests/testfixtures.py b/lp_signing/tests/testfixtures.py
index 433b0b8..8cfb84d 100644
--- a/lp_signing/tests/testfixtures.py
+++ b/lp_signing/tests/testfixtures.py
@@ -75,7 +75,7 @@ class TestClient(FlaskClient):
"""A Flask client that understands JSON and boxed authentication."""
def post(self, *args, headers=None, data=None, json_data=None,
- private_key=None, nonce=None, **kwargs):
+ encrypted_data=None, private_key=None, nonce=None, **kwargs):
headers = dict(headers) if headers else {}
if json_data is not None:
if data is not None:
@@ -84,18 +84,27 @@ class TestClient(FlaskClient):
if "Content-Type" not in headers:
headers["Content-Type"] = "application/json"
data = json.dumps(json_data).encode("UTF-8")
- if private_key is not None and nonce is not None:
+ if private_key is not None:
+ headers.setdefault(
+ "X-Client-Public-Key",
+ private_key.public_key.encode(
+ encoder=Base64Encoder).decode("UTF-8"))
+ if nonce is not None:
+ headers.setdefault(
+ "X-Nonce", Base64Encoder.encode(nonce).decode("UTF-8"))
+ if (private_key is not None and nonce is not None and
+ encrypted_data is None):
data = data or b""
- headers["X-Client-Public-Key"] = private_key.public_key.encode(
- encoder=Base64Encoder).decode("UTF-8")
box = Box(
private_key,
boxed_authentication.service_private_keys[0].public_key)
message = box.encrypt(data, nonce, encoder=Base64Encoder)
- headers["X-Nonce"] = message.nonce.decode("UTF-8")
headers["Content-Type"] = "application/x-boxed-json"
- data = message.ciphertext
- resp = super().post(*args, headers=headers, data=data, **kwargs)
+ encrypted_data = message.ciphertext
+ else:
+ encrypted_data = data
+ resp = super().post(
+ *args, headers=headers, data=encrypted_data, **kwargs)
# If there's a current transaction, roll it back. The POST may have
# committed a transaction in another thread, so anything we try to
# commit might otherwise conflict with that.