Skip to content

Commit 247a2d7

Browse files
authored
Merge pull request #4 from hug-dev/refactor
Refactor the current codebase
2 parents a7fc837 + 83fc51f commit 247a2d7

Some content is hidden

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

57 files changed

+2015
-1075
lines changed

.github/workflows/build.yml

-33
This file was deleted.

.github/workflows/ci.yml

+26
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,29 @@ 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+
name: CI tests
20+
runs-on: ubuntu-latest
21+
steps:
22+
- uses: actions/checkout@v2
23+
- name: Set up Python 3.7
24+
uses: actions/setup-python@v1
25+
with:
26+
python-version: 3.7
27+
- name: Install dependencies
28+
run: |
29+
python -m pip install --upgrade pip
30+
pip install -r requirements.txt
31+
- name: Check formatting with blake
32+
run: |
33+
black --check . --exclude generator/generators/protobuf
34+
- name: Lint with flake8
35+
run: |
36+
# The GitHub editor is 127 chars wide
37+
flake8 . --count --max-line-length=127 --statistics --exclude generator/generators/protobuf
38+
- name: Execute smoke test
39+
run: |
40+
python parsec_mock/parsec_mock.py &
41+
sleep 5
42+
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

+66-54
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,16 @@
99
from struct import pack
1010
import base64
1111

12-
from generator_lib import generators
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+
# F401 ignored for flake8 as those methods are called through eval
17+
from generators.ping_noauth import gen as ping_noauth # noqa: F401
18+
from generators.list_opcodes_bad1 import gen as list_opcodes_bad1 # noqa: F401
19+
from generators.list_opcodes_directauth import ( # noqa: F401
20+
gen as list_opcodes_directauth,
21+
)
1322

1423

1524
class TestSpec(object):
@@ -27,71 +36,68 @@ def _traverse(key, element):
2736
self.__dict__.update(objd)
2837
self.basedict = dictionary
2938

30-
def is_valid(self):
31-
return True
32-
3339

3440
def read_specs(folder):
3541
"""Read test specs from a folder"""
3642
specfiles = [f for f in listdir(folder) if isfile(join(folder, f))]
3743
specs = []
3844
for file in specfiles:
3945
print(f"Parsing spec file: {file}")
40-
with open(os.path.join(folder, file), 'r') as f:
46+
# Only use the first part of the filename as spec name
47+
name = file.split(".")[0]
48+
with open(os.path.join(folder, file), "r") as f:
4149
spec = safe_load(f)
4250
testspec = TestSpec(spec["spec"])
43-
if testspec.is_valid():
44-
specs.append(testspec)
45-
else:
46-
print(f"Error loading test spec from {file}")
51+
specs.append((name, testspec))
4752
return specs
4853

4954

5055
def generate_data(specs, output_folder):
5156
"""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...")
57+
for (name, spec) in specs:
58+
generate_spec_data(output_folder, spec, name)
5859

5960

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

6466
request_auth = create_auth(spec.request.auth)
6567
request_content_len = spec.request.header.content_length
66-
if request_content_len == 'auto':
68+
if request_content_len == "auto":
6769
request_content_len = len(operation)
6870

6971
request_auth_len = spec.request.header.auth_length
70-
if request_auth_len == 'auto':
72+
if request_auth_len == "auto":
7173
request_auth_len = len(request_auth)
72-
request_header = pack_header(spec.request.header, request_auth_len, request_content_len)
74+
request_header = pack_header(
75+
spec.request.header, request_auth_len, request_content_len
76+
)
7377

7478
response_content_len = spec.response.header.content_length
75-
if response_content_len == 'auto':
79+
if response_content_len == "auto":
7680
response_content_len = len(result)
7781

7882
response_auth_len = spec.response.header.auth_length
79-
80-
response_header = pack_header(spec.response.header, response_auth_len, response_content_len)
83+
response_header = pack_header(
84+
spec.response.header, response_auth_len, response_content_len
85+
)
8186

8287
request_buf = request_header + operation + request_auth
8388
response_buf = response_header + result
8489

90+
# The generator appends the base64 data at the end of the spec file
8591
out_data = {
8692
"spec": spec.basedict,
8793
"test_data": {
88-
"request": base64.b64encode(request_buf).decode('ascii'),
89-
"response": base64.b64encode(response_buf).decode('ascii'),
90-
}
94+
"request": base64.b64encode(request_buf).decode("ascii"),
95+
"response": base64.b64encode(response_buf).decode("ascii"),
96+
},
9197
}
92-
out_path = os.path.join(output_folder, spec.name + ".test.yaml")
93-
print(f"Writing spec {spec.name} test data to {out_path}")
94-
with open(out_path, 'w') as f:
98+
out_path = os.path.join(output_folder, name + ".test.yaml")
99+
print(f"Writing spec {name} test data to {out_path}")
100+
with open(out_path, "w") as f:
95101
dump(out_data, f, sort_keys=False)
96102

97103

@@ -100,42 +106,48 @@ def pack_header(header, auth_len, body_len):
100106
# pack function converts arguments into binary string, based on format string.
101107
# < means integers are little endian. Rest of format string is one character per input to indicate
102108
# packed field interpretation. See struct.pack docs for details.
103-
return pack('<IHBBHBQBBBIHIHH',
104-
header.magic_number,
105-
header.header_size,
106-
header.major_version_number,
107-
header.minor_version_number,
108-
header.flags,
109-
header.provider,
110-
header.session_handle,
111-
header.content_type,
112-
header.accept_type,
113-
header.auth_type,
114-
body_len,
115-
auth_len,
116-
header.opcode,
117-
header.status,
118-
0
119-
)
109+
# This should map to the Fixed Common Header defined here:
110+
# https://parallaxsecond.github.io/parsec-book/parsec_client/wire_protocol.html#the-fixed-common-header
111+
return pack(
112+
"<IHBBHBQBBBIHIHH",
113+
header.magic_number,
114+
header.header_size,
115+
header.major_version_number,
116+
header.minor_version_number,
117+
header.flags,
118+
header.provider,
119+
header.session_handle,
120+
header.content_type,
121+
header.accept_type,
122+
header.auth_type,
123+
body_len,
124+
auth_len,
125+
header.opcode,
126+
header.status,
127+
0,
128+
)
120129

121130

122131
def create_auth(auth_spec):
123132
"""Creates auth body of message"""
124-
if auth_spec.type == 'none':
125-
return b''
126-
if auth_spec.type == 'direct':
127-
return auth_spec.app_name.encode('utf-8')
128-
return b''
133+
if auth_spec.type == "none":
134+
return b""
135+
if auth_spec.type == "direct":
136+
return auth_spec.app_name.encode("utf-8")
137+
return b""
129138

130139

131140
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'))
134141
print("Generating test data.")
142+
143+
specdir = os.path.abspath(os.path.join(os.path.dirname(__file__), "test_specs"))
135144
print(f"Reading test specs from {specdir}")
136-
print(f"Generating test data to {datadir}")
137145
specs = read_specs(specdir)
138146

147+
datadir = os.path.abspath(
148+
os.path.join(os.path.dirname(__file__), "../generator_output")
149+
)
150+
print(f"Generating test data to {datadir}")
139151
generate_data(specs, datadir)
140152

141153

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,12 @@
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

65

7-
def gen_list_opcodes_auth_direct():
8-
operation = protobuf.list_opcodes_pb2.Operation()
6+
def gen():
7+
operation = list_opcodes_pb2.Operation()
98
operation.provider_id = 1
109

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

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

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,12 +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 ping_pb2
54

65

7-
def gen_ping_no_auth():
8-
op = protobuf.ping_pb2.Operation()
9-
result = protobuf.ping_pb2.Result()
6+
def gen():
7+
op = ping_pb2.Operation()
8+
result = ping_pb2.Result()
109
result.wire_protocol_version_maj = 1
1110
result.wire_protocol_version_min = 0
1211

File renamed without changes.

0 commit comments

Comments
 (0)