Skip to content

Commit 07b9b57

Browse files
committed
Refactor the current codebase
This commit contains the following changes: - clean the directory tree to regroup common features with more explicit names - regroup CI testing into one workflow and add the mock service smoke test - simplify the README.md file instruction with what is currently there - change the way new tests are added to make it easier Signed-off-by: Hugues de Valon <[email protected]>
1 parent a7fc837 commit 07b9b57

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+1949
-1034
lines changed

.github/workflows/build.yml

-33
This file was deleted.

.github/workflows/ci.yml

+30
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,33 @@ jobs:
1414
args: -v -r *.md
1515
- name: Fail if there were link errors
1616
run: exit ${{ steps.lc.outputs.exit_code }}
17+
18+
build:
19+
runs-on: ubuntu-latest
20+
strategy:
21+
matrix:
22+
# pyyaml version we use only supporting python 3.6 upwards
23+
python-version: [ 3.6, 3.7, 3.8]
24+
25+
steps:
26+
- uses: actions/checkout@v2
27+
- name: Set up Python ${{ matrix.python-version }}
28+
uses: actions/setup-python@v2
29+
with:
30+
python-version: ${{ matrix.python-version }}
31+
- name: Install dependencies
32+
run: |
33+
python -m pip install --upgrade pip
34+
pip install flake8 pytest
35+
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
36+
- name: Lint with flake8
37+
run: |
38+
# stop the build if there are Python syntax errors or undefined names
39+
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics --exclude generator/protobuf
40+
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
41+
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics --exclude generator/generators/protobuf
42+
- name: Execute smoke test
43+
run: |
44+
python parsec_mock/parsec_mock.py
45+
sleep 5
46+
python tests/mock_test.py

.gitmodules

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
[submodule "parsec-operations"]
2-
path = parsec-operations
2+
path = generator/generators/parsec-operations
33
url = https://github.com/parallaxsecond/parsec-operations

Makefile

-11
This file was deleted.

README.md

+81-83
Large diffs are not rendered by default.

generator/generator.py

+24-26
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,13 @@
99
from struct import pack
1010
import base64
1111

12-
from generator_lib import generators
13-
12+
# Generator functions
13+
# Add your new generator function here
14+
# TODO: with some import syntax or clever moduling, it might be possible not
15+
# to have to do anything here?
16+
from generators.ping_noauth import gen as ping_noauth
17+
from generators.list_opcodes_bad1 import gen as list_opcodes_bad1
18+
from generators.list_opcodes_directauth import gen as list_opcodes_directauth
1419

1520
class TestSpec(object):
1621
"""Class to represent a test specification. Used to convert
@@ -27,39 +32,30 @@ def _traverse(key, element):
2732
self.__dict__.update(objd)
2833
self.basedict = dictionary
2934

30-
def is_valid(self):
31-
return True
32-
33-
3435
def read_specs(folder):
3536
"""Read test specs from a folder"""
3637
specfiles = [f for f in listdir(folder) if isfile(join(folder, f))]
3738
specs = []
3839
for file in specfiles:
3940
print(f"Parsing spec file: {file}")
41+
# Only use the first part of the filename as spec name
42+
name = file.split('.')[0]
4043
with open(os.path.join(folder, file), 'r') as f:
4144
spec = safe_load(f)
4245
testspec = TestSpec(spec["spec"])
43-
if testspec.is_valid():
44-
specs.append(testspec)
45-
else:
46-
print(f"Error loading test spec from {file}")
46+
specs.append((name, testspec))
4747
return specs
4848

4949

5050
def generate_data(specs, output_folder):
5151
"""Generate test data for a list of specs"""
52-
for spec in specs:
53-
if spec.generator in generators:
54-
print(f"Generating test {spec.name}")
55-
generate_spec_data(output_folder, spec, generators[spec.generator])
56-
else:
57-
print(f"No generator function found for spec {spec.name}, skipping...")
58-
52+
for (name, spec) in specs:
53+
generate_spec_data(output_folder, spec, name)
5954

60-
def generate_spec_data(output_folder, spec, generator_fn):
55+
def generate_spec_data(output_folder, spec, name):
6156
"""Generates data for a single spec and outputs it into the specified output folder."""
62-
(operation, result) = generator_fn()
57+
# The generator function has the same name as the test specification
58+
(operation, result) = eval(name)()
6359

6460
request_auth = create_auth(spec.request.auth)
6561
request_content_len = spec.request.header.content_length
@@ -76,21 +72,21 @@ def generate_spec_data(output_folder, spec, generator_fn):
7672
response_content_len = len(result)
7773

7874
response_auth_len = spec.response.header.auth_length
79-
8075
response_header = pack_header(spec.response.header, response_auth_len, response_content_len)
8176

8277
request_buf = request_header + operation + request_auth
8378
response_buf = response_header + result
8479

80+
# The generator appends the base64 data at the end of the spec file
8581
out_data = {
8682
"spec": spec.basedict,
8783
"test_data": {
8884
"request": base64.b64encode(request_buf).decode('ascii'),
8985
"response": base64.b64encode(response_buf).decode('ascii'),
9086
}
9187
}
92-
out_path = os.path.join(output_folder, spec.name + ".test.yaml")
93-
print(f"Writing spec {spec.name} test data to {out_path}")
88+
out_path = os.path.join(output_folder, name + ".test.yaml")
89+
print(f"Writing spec {name} test data to {out_path}")
9490
with open(out_path, 'w') as f:
9591
dump(out_data, f, sort_keys=False)
9692

@@ -100,6 +96,8 @@ def pack_header(header, auth_len, body_len):
10096
# pack function converts arguments into binary string, based on format string.
10197
# < means integers are little endian. Rest of format string is one character per input to indicate
10298
# packed field interpretation. See struct.pack docs for details.
99+
# This should map to the Fixed Common Header defined here:
100+
# https://parallaxsecond.github.io/parsec-book/parsec_client/wire_protocol.html#the-fixed-common-header
103101
return pack('<IHBBHBQBBBIHIHH',
104102
header.magic_number,
105103
header.header_size,
@@ -129,15 +127,15 @@ def create_auth(auth_spec):
129127

130128

131129
def main():
132-
specdir = os.path.abspath(os.path.join(os.path.dirname(__file__), 'testspecs'))
133-
datadir = os.path.abspath(os.path.join(os.path.dirname(__file__), '../testdata'))
134130
print("Generating test data.")
131+
132+
specdir = os.path.abspath(os.path.join(os.path.dirname(__file__), 'test_specs'))
135133
print(f"Reading test specs from {specdir}")
136-
print(f"Generating test data to {datadir}")
137134
specs = read_specs(specdir)
138135

136+
datadir = os.path.abspath(os.path.join(os.path.dirname(__file__), '../generator_output'))
137+
print(f"Generating test data to {datadir}")
139138
generate_data(specs, datadir)
140139

141-
142140
if __name__ == "__main__":
143141
main()

generator/generator_lib.py

-12
This file was deleted.

generator/generators/Makefile

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Copyright 2021 Contributors to the Parsec project.
2+
# SPDX-License-Identifier: Apache-2.0
3+
PROTOC_OUTPUT_FILES=$(shell find parsec-operations/protobuf/ -name "*.proto" -exec basename {} .proto \; | awk '{print "protobuf/"$$1"_pb2.py"}')
4+
.PHONY: protobuf all
5+
6+
all: protobuf
7+
8+
protobuf: ${PROTOC_OUTPUT_FILES}
9+
10+
protobuf/%_pb2.py: parsec-operations/protobuf/%.proto
11+
@protoc -I=parsec-operations/protobuf --python_out=protobuf $< > /dev/null

generator/generators/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
# Copyright 2021 Contributors to the Parsec project.
22
# SPDX-License-Identifier: Apache-2.0
3-
import protobuf.ping_pb2
4-
import protobuf.list_opcodes_pb2
3+
from .protobuf import list_opcodes_pb2
54

6-
7-
def gen_list_opcodes_auth_direct():
8-
operation = protobuf.list_opcodes_pb2.Operation()
5+
def gen():
6+
operation = list_opcodes_pb2.Operation()
97
operation.provider_id = 1
108

11-
result = protobuf.list_opcodes_pb2.Result()
9+
result = list_opcodes_pb2.Result()
1210
result.opcodes.extend([1, 3, 2])
1311
return (operation.SerializeToString(), result.SerializeToString())
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Copyright 2021 Contributors to the Parsec project.
2+
# SPDX-License-Identifier: Apache-2.0
3+
from .protobuf import list_opcodes_pb2
4+
5+
def gen():
6+
operation = list_opcodes_pb2.Operation()
7+
operation.provider_id = 1
8+
9+
result = list_opcodes_pb2.Result()
10+
result.opcodes.extend([1, 3, 2, 6])
11+
return (operation.SerializeToString(), result.SerializeToString())
Submodule parsec-operations added at 87cef31

generator/gen_ping_operations.py generator/generators/ping_noauth.py

+4-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
# Copyright 2021 Contributors to the Parsec project.
22
# SPDX-License-Identifier: Apache-2.0
3-
import protobuf.ping_pb2
4-
import protobuf.list_opcodes_pb2
3+
from .protobuf import ping_pb2
54

6-
7-
def gen_ping_no_auth():
8-
op = protobuf.ping_pb2.Operation()
9-
result = protobuf.ping_pb2.Result()
5+
def gen():
6+
op = ping_pb2.Operation()
7+
result = ping_pb2.Result()
108
result.wire_protocol_version_maj = 1
119
result.wire_protocol_version_min = 0
1210

File renamed without changes.

0 commit comments

Comments
 (0)