-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rewrite the existing tests to be integration tests against a compiled Rust binary. We use the httpbin library to start up a Python webserver and instruct the proxy to connect to it. This allows to test connection properties that aren't recordable in the VCR format, like timeouts or streamed responses. The tests are reorganized to be split into proxy handling and error handling.
- Loading branch information
Showing
8 changed files
with
1,116 additions
and
1,144 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import json | ||
import os | ||
import subprocess | ||
from typing import Optional, Union | ||
|
||
import pytest | ||
|
||
|
||
@pytest.fixture(scope="session") | ||
def proxy_bin() -> str: | ||
if "PROXY_BIN" in os.environ: | ||
# allow running tests against e.g. a packaged binary | ||
return os.environ["PROXY_BIN"] | ||
# default debug path, expects `cargo build` to already have been run | ||
metadata = subprocess.check_output(["cargo", "metadata"]) | ||
return json.loads(metadata)["target_directory"] + "/debug/securedrop-proxy" | ||
|
||
|
||
@pytest.fixture | ||
def proxy_request(httpbin, proxy_bin): | ||
def proxy_( | ||
input: Union[bytes, dict], origin: Optional[str] = None | ||
) -> subprocess.CompletedProcess: | ||
if isinstance(input, dict): | ||
input = json.dumps(input).encode() | ||
if origin is None: | ||
origin = httpbin.url | ||
return subprocess.run( | ||
[proxy_bin], env={"SD_PROXY_ORIGIN": origin}, input=input, capture_output=True | ||
) | ||
|
||
return proxy_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import os | ||
import subprocess | ||
|
||
|
||
def test_missing_config(proxy_bin): | ||
env = os.environ.copy() | ||
if "SD_PROXY_ORIGIN" in env: | ||
del env["SD_PROXY_ORIGIN"] | ||
result = subprocess.run([proxy_bin], env=env, capture_output=True) | ||
assert result.returncode == 1 | ||
assert result.stderr.decode().strip() == '{"error":"environment variable not found"}' | ||
|
||
|
||
def test_empty_input(proxy_request): | ||
result = proxy_request(input=b"") | ||
assert result.returncode == 1 | ||
assert ( | ||
result.stderr.decode().strip() == '{"error":"EOF while parsing a value at line 1 column 0"}' | ||
) | ||
|
||
|
||
def test_input_invalid(proxy_request): | ||
test_input = b'"foo": "bar", "baz": "bliff"}' | ||
result = proxy_request(input=test_input) | ||
assert result.returncode == 1 | ||
assert ( | ||
result.stderr.decode().strip() | ||
== '{"error":"invalid type: string \\"foo\\", ' | ||
+ 'expected struct IncomingRequest at line 1 column 5"}' | ||
) | ||
|
||
|
||
def test_input_missing_keys(proxy_request): | ||
test_input = b'{"foo": "bar", "baz": "bliff"}' | ||
result = proxy_request(input=test_input) | ||
assert result.returncode == 1 | ||
assert ( | ||
result.stderr.decode().strip() | ||
== '{"error":"unknown field `foo`, expected one of `method`, ' | ||
+ '`path_query`, `stream`, `headers`, `body`, `timeout` at line 1 column 6"}' | ||
) | ||
|
||
|
||
def test_invalid_origin(proxy_request): | ||
test_input = { | ||
"method": "GET", | ||
"path_query": "/status/200", | ||
"stream": False, | ||
} | ||
# invalid port | ||
result = proxy_request(input=test_input, origin="http://127.0.0.1:-1/foo") | ||
assert result.returncode == 1 | ||
assert result.stderr.decode().strip() == '{"error":"invalid port number"}' | ||
|
||
|
||
def test_cannot_connect(proxy_request): | ||
test_input = { | ||
"method": "GET", | ||
"path_query": "/", | ||
"stream": False, | ||
} | ||
# .test is a reserved TLD, so it should never resolve | ||
result = proxy_request(input=test_input, origin="http://missing.test/foo") | ||
assert result.returncode == 1 | ||
assert ( | ||
result.stderr.decode().strip() | ||
== '{"error":"error sending request for url (http://missing.test/): ' | ||
+ "error trying to connect: dns error: failed to lookup address information: " | ||
+ 'Name or service not known"}' | ||
) |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.