Skip to content

Commit 13471de

Browse files
committed
Optimise tests to prefer non-Docker and be cross-platform
1 parent 0a3ced7 commit 13471de

10 files changed

Lines changed: 411 additions & 314 deletions

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,10 @@ jobs:
6464
run: cargo run -p cdd-cli -- from_openapi to_sdk -i ./petstore_oas3.yaml -o ./target/petstore3
6565

6666
- name: Test Swagger 2.0 Petstore Server & Client
67-
run: bash scripts/test_server_and_client.sh ./petstore.json ./target/server_petstore2 ./target/client_petstore2
67+
run: python scripts/test_server_and_client.py ./petstore.json ./target/server_petstore2 ./target/client_petstore2
6868

6969
- name: Test OpenAPI 3.2.0 Petstore Server & Client
70-
run: bash scripts/test_server_and_client.sh ./petstore_oas3.yaml ./target/server_petstore3 ./target/client_petstore3
70+
run: python scripts/test_server_and_client.py ./petstore_oas3.yaml ./target/server_petstore3 ./target/client_petstore3
7171

7272
- name: Check Documentation Coverage
7373
run: |

.pre-commit-config.yaml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,36 +45,36 @@ repos:
4545

4646
- id: test-swagger-2
4747
name: Test Swagger 2.0 Petstore SDK
48-
entry: bash scripts/test_sdk.sh ../petstore.json ./target/petstore2
48+
entry: python3 scripts/test_sdk.py ../petstore.json ./target/petstore2
4949
language: system
5050
pass_filenames: false
5151
types: [rust]
5252

5353
- id: test-openapi-3
5454
name: Test OpenAPI 3.2.0 Petstore SDK
55-
entry: bash scripts/test_sdk.sh ../petstore_oas3.json ./target/petstore3
55+
entry: python3 scripts/test_sdk.py ../petstore_oas3.json ./target/petstore3
5656
language: system
5757
pass_filenames: false
5858
types: [rust]
5959

6060
- id: test-server-swagger-2
6161
name: Test Swagger 2.0 Petstore Server & Client
62-
entry: bash scripts/test_server_and_client.sh ../petstore.json ./target/server_petstore2 ./target/client_petstore2
62+
entry: python3 scripts/test_server_and_client.py ../petstore.json ./target/server_petstore2 ./target/client_petstore2
6363
language: system
6464
pass_filenames: false
6565
types: [rust]
6666

6767
- id: test-server-openapi-3
6868
name: Test OpenAPI 3.2.0 Petstore Server & Client
69-
entry: bash scripts/test_server_and_client.sh ../petstore_oas3.json ./target/server_petstore3 ./target/client_petstore3
69+
entry: python3 scripts/test_server_and_client.py ../petstore_oas3.json ./target/server_petstore3 ./target/client_petstore3
7070
language: system
7171
pass_filenames: false
7272
types: [rust]
7373

7474
- id: wasm-build
7575
name: WASM Build Test
76-
entry: python scripts/build_wasm.py
77-
language: python
76+
entry: python3 scripts/build_wasm.py
77+
language: system
7878
pass_filenames: false
7979
types: [rust]
8080

scripts/build_wasm.py

100644100755
Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
1+
#!/usr/bin/env python3
12
import subprocess
23
import sys
34

45
def main():
56
print("Adding wasm32-wasip1 target...")
67
try:
7-
subprocess.run("rustup target add wasm32-wasip1", shell=True, check=True)
8-
except subprocess.CalledProcessError as e:
9-
print(f"Failed to add target: {e}")
8+
subprocess.run(["rustup", "target", "add", "wasm32-wasip1"], check=True)
9+
except subprocess.CalledProcessError:
10+
print("Failed to add target")
1011
sys.exit(1)
1112

1213
print("Building WASM target...")
1314
try:
14-
subprocess.run("cargo build -p cdd-cli --release --target wasm32-wasip1 --no-default-features", shell=True, check=True)
15-
except subprocess.CalledProcessError as e:
16-
print(f"WASM build failed: {e}")
17-
# Make.bat had a fallback, we'll just print a warning and exit 0 or 1 depending on strictness.
18-
# Let's exit 1 so pre-commit correctly reports failure.
15+
subprocess.run(
16+
["cargo", "build", "-p", "cdd-cli", "--release", "--target", "wasm32-wasip1", "--no-default-features"],
17+
check=True
18+
)
19+
except subprocess.CalledProcessError:
20+
print("WASM build failed")
1921
sys.exit(1)
2022

2123
if __name__ == "__main__":
22-
main()
24+
main()

scripts/test_sdk.py

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
#!/usr/bin/env python3
2+
import sys
3+
import os
4+
import subprocess
5+
import random
6+
import time
7+
import atexit
8+
import shutil
9+
10+
server_process = None
11+
mock_server_path = None
12+
13+
def cleanup():
14+
global server_process, mock_server_path
15+
if server_process:
16+
server_process.terminate()
17+
server_process.wait()
18+
if mock_server_path and os.path.exists(mock_server_path):
19+
os.remove(mock_server_path)
20+
21+
atexit.register(cleanup)
22+
23+
def main():
24+
if len(sys.argv) < 3:
25+
print("Usage: test_sdk.py <spec> <output_dir>")
26+
sys.exit(1)
27+
28+
spec_file = sys.argv[1]
29+
output_dir = sys.argv[2]
30+
31+
port = random.randint(8000, 8999)
32+
33+
global mock_server_path
34+
mock_server_path = os.path.abspath(f"mock_server_{port}.py")
35+
36+
mock_server_code = """
37+
from http.server import HTTPServer, BaseHTTPRequestHandler
38+
import sys
39+
port = int(sys.argv[1])
40+
class MockHandler(BaseHTTPRequestHandler):
41+
def log_message(self, format, *args): pass
42+
def do_GET(self): self.mock()
43+
def do_POST(self): self.mock()
44+
def do_PUT(self): self.mock()
45+
def do_DELETE(self): self.mock()
46+
def mock(self):
47+
self.send_response(200)
48+
self.send_header("Content-Type", "application/json")
49+
self.end_headers()
50+
path = self.path
51+
if "findByStatus" in path or "findByTags" in path or "createWithList" in path or "createWithArray" in path:
52+
if "pet" in path: self.wfile.write(b"[{\\"name\\": \\"mocked\\", \\"photoUrls\\": []}]")
53+
else: self.wfile.write(b"[]")
54+
else:
55+
if "pet" in path: self.wfile.write(b"{\\"name\\": \\"mocked\\", \\"photoUrls\\": []}")
56+
elif "user/login" in path: self.wfile.write(b"\\"token\\"")
57+
else: self.wfile.write(b"{}")
58+
if __name__ == "__main__": HTTPServer(("", port), MockHandler).serve_forever()
59+
"""
60+
with open(mock_server_path, "w") as f:
61+
f.write(mock_server_code)
62+
63+
global server_process
64+
server_process = subprocess.Popen([sys.executable, mock_server_path, str(port)])
65+
66+
time.sleep(2)
67+
68+
if os.path.exists(output_dir):
69+
shutil.rmtree(output_dir)
70+
71+
subprocess.run(["cargo", "run", "-p", "cdd-cli", "--", "from_openapi", "to_sdk", "-i", spec_file, "-o", output_dir, "--target", "client-reqwest", "--tests"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=True)
72+
73+
with open(os.path.join(output_dir, "Cargo.toml"), "a") as f:
74+
f.write("\n[workspace]\n")
75+
76+
api_contracts_path = os.path.join(output_dir, "tests", "api_contracts.rs")
77+
if os.path.exists(api_contracts_path):
78+
with open(api_contracts_path, "r") as f:
79+
content = f.read()
80+
content = content.replace("localhost:8080", f"127.0.0.1:{port}")
81+
with open(api_contracts_path, "w") as f:
82+
f.write(content)
83+
84+
try:
85+
subprocess.run(["cargo", "test"], cwd=output_dir, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=True)
86+
except subprocess.CalledProcessError:
87+
print(f"Test failed for {spec_file}")
88+
subprocess.run(["cargo", "test"], cwd=output_dir)
89+
sys.exit(1)
90+
91+
if __name__ == "__main__":
92+
main()

scripts/test_sdk.sh

Lines changed: 0 additions & 42 deletions
This file was deleted.

scripts/test_server.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#!/usr/bin/env python3
2+
import sys
3+
import os
4+
import subprocess
5+
import random
6+
import time
7+
import atexit
8+
import shutil
9+
10+
server_process = None
11+
12+
def cleanup():
13+
global server_process
14+
if server_process:
15+
server_process.terminate()
16+
server_process.wait()
17+
18+
atexit.register(cleanup)
19+
20+
def main():
21+
if len(sys.argv) < 4:
22+
print("Usage: test_server.py <spec> <server_out> <client_out>")
23+
sys.exit(1)
24+
25+
spec_file = sys.argv[1]
26+
server_dir = sys.argv[2]
27+
client_dir = sys.argv[3]
28+
29+
port = random.randint(8000, 8999)
30+
31+
# 1. Generate Server
32+
if os.path.exists(server_dir):
33+
shutil.rmtree(server_dir)
34+
35+
subprocess.run(["cargo", "run", "-p", "cdd-cli", "--", "from_openapi", "to_server", "-i", spec_file, "-o", server_dir], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=True)
36+
37+
with open(os.path.join(server_dir, "Cargo.toml"), "a") as f:
38+
f.write("\n[workspace]\n")
39+
40+
subprocess.run(["cargo", "build"], cwd=server_dir, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=True)
41+
42+
env = os.environ.copy()
43+
env["CDD_WEB_BIND"] = f"127.0.0.1:{port}"
44+
45+
global server_process
46+
server_process = subprocess.Popen(["cargo", "run", "--", "--ephemeral"], cwd=server_dir, env=env, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
47+
48+
time.sleep(5)
49+
50+
# 2. Generate Client
51+
if os.path.exists(client_dir):
52+
shutil.rmtree(client_dir)
53+
54+
subprocess.run(["cargo", "run", "-p", "cdd-cli", "--", "from_openapi", "to_sdk", "-i", spec_file, "-o", client_dir, "--target", "client-reqwest", "--tests"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=True)
55+
56+
with open(os.path.join(client_dir, "Cargo.toml"), "a") as f:
57+
f.write("\n[workspace]\n")
58+
59+
api_contracts_path = os.path.join(client_dir, "tests", "api_contracts.rs")
60+
if os.path.exists(api_contracts_path):
61+
with open(api_contracts_path, "r") as f:
62+
content = f.read()
63+
content = content.replace("localhost:8080", f"127.0.0.1:{port}")
64+
with open(api_contracts_path, "w") as f:
65+
f.write(content)
66+
67+
try:
68+
subprocess.run(["cargo", "test"], cwd=client_dir, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=True)
69+
except subprocess.CalledProcessError:
70+
print(f"Test failed for {spec_file} against generated server")
71+
subprocess.run(["cargo", "test"], cwd=client_dir)
72+
sys.exit(1)
73+
74+
if __name__ == "__main__":
75+
main()

scripts/test_server.sh

Lines changed: 0 additions & 50 deletions
This file was deleted.

0 commit comments

Comments
 (0)