Skip to content

Commit

Permalink
pw_transfer: Make integration tests fixture library
Browse files Browse the repository at this point in the history
Slightly refactors the integration test to be a library that can be used
to more easily stand up smaller sets of integration tests.

Cq-Include-Trybots: luci.pigweed.try:pigweed-integration-transfer
Change-Id: I3ae92f0fdf25396c4b3a0c73153b625230c32478
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/112510
Reviewed-by: Ted Pudlik <[email protected]>
Pigweed-Auto-Submit: Armando Montanez <[email protected]>
Commit-Queue: Auto-Submit <[email protected]>
  • Loading branch information
armandomontanez authored and CQ Bot Account committed Oct 5, 2022
1 parent 26cfd35 commit 24c4722
Show file tree
Hide file tree
Showing 9 changed files with 476 additions and 297 deletions.
9 changes: 5 additions & 4 deletions pw_presubmit/py/pw_presubmit/pigweed_presubmit.py
Original file line number Diff line number Diff line change
Expand Up @@ -509,10 +509,11 @@ def pw_transfer_integration_test(ctx: PresubmitContext) -> None:
This test is not part of the regular bazel build because it's slow and
intended to run in CI only.
"""
build.bazel(
ctx, 'test',
'//pw_transfer/integration_test:cross_language_integration_test',
'--test_output=errors')
build.bazel(ctx, 'test',
'//pw_transfer/integration_test:cross_language_small_test',
'//pw_transfer/integration_test:cross_language_medium_test',
'//pw_transfer/integration_test:cross_language_large_test',
'--test_output=errors')


#
Expand Down
20 changes: 16 additions & 4 deletions pw_transfer/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ pw_executable("integration_test_client") {
]
}

# TODO(b/228516801): Make this actually work; this is just a placeholder.
pw_python_script("integration_test_python_client") {
sources = [ "integration_test/python_client.py" ]
}
Expand All @@ -325,12 +326,23 @@ pw_python_script("integration_test_proxy_test") {
}

# TODO(b/228516801): Make this actually work; this is just a placeholder.
pw_python_script("cross_language_integration_test") {
sources = [ "integration_test/cross_language_integration_test.py" ]
pw_python_script("integration_test_fixture") {
sources = [ "integration_test/test_fixture.py" ]
}

# TODO(b/228516801): Make this actually work; this is just a placeholder.
pw_python_script("cross_language_small_test") {
sources = [ "integration_test/cross_language_small_test.py" ]
}

pw_python_script("cross_language_smoke_test") {
sources = [ "integration_test/cross_language_smoke_test.py" ]
# TODO(b/228516801): Make this actually work; this is just a placeholder.
pw_python_script("cross_language_medium_test") {
sources = [ "integration_test/cross_language_medium_test.py" ]
}

# TODO(b/228516801): Make this actually work; this is just a placeholder.
pw_python_script("cross_language_large_test") {
sources = [ "integration_test/cross_language_large_test.py" ]
}

pw_python_action("cpp_client_integration_test") {
Expand Down
13 changes: 10 additions & 3 deletions pw_transfer/docs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,14 @@ To run the tests on your machine, run

.. code:: bash
$ bazel run pw_transfer/integration_test:cross_language_integration_test
$ bazel test --features=c++17 \
pw_transfer/integration_test:cross_language_small_test \
pw_transfer/integration_test:cross_language_medium_test
.. note:: There is a large test that tests transfers that are megabytes in size.
These are not run automatically, but can be run manually via the
pw_transfer/integration_test:cross_language_large_test test. These are VERY
slow, but exist for manual validation of real-world use cases.

The integration tests permit injection of client/server/proxy binaries to use
when running the tests. This allows manual testing of older versions of
Expand All @@ -585,8 +592,8 @@ pw_transfer against newer versions.
# Test a newer version of pw_transfer against an old C++ client that was
# backed up to another directory.
$ bazel run pw_transfer/integration_test:cross_language_integration_test -- \
--cpp-client ../old_pw_transfer_version/cpp_client
$ bazel run pw_transfer/integration_test:cross_language_medium_test -- \
--cpp-client-binary ../old_pw_transfer_version/cpp_client
CI/CQ integration
=================
Expand Down
52 changes: 32 additions & 20 deletions pw_transfer/integration_test/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -92,44 +92,56 @@ pw_cc_binary(
],
)

py_test(
name = "cross_language_integration_test",
# Actually 1 hour, see
# https://docs.bazel.build/versions/main/test-encyclopedia.html#role-of-the-test-runner
timeout = "eternal",
srcs = ["cross_language_integration_test.py"],
py_library(
name = "integration_test_fixture",
srcs = [
"test_fixture.py",
],
data = [
":cpp_client",
":java_client",
":proxy",
":python_client",
":server",
],
# This test is not run in CQ because it's too slow.
tags = ["manual"],
deps = [
":config_pb2",
"@rules_python//python/runfiles",
],
)

py_test(
name = "cross_language_smoke_test",
name = "cross_language_large_test",
# Actually 1 hour, see
# https://docs.bazel.build/versions/main/test-encyclopedia.html#role-of-the-test-runner
timeout = "eternal",
srcs = [
"cross_language_integration_test.py",
"cross_language_smoke_test.py",
"cross_language_large_test.py",
],
data = [
":cpp_client",
":java_client",
":proxy",
":python_client",
":server",
# This test is not run in CQ because it's too slow.
tags = ["manual"],
deps = [
":integration_test_fixture",
],
)

py_test(
name = "cross_language_medium_test",
srcs = [
"cross_language_medium_test.py",
],
main = "cross_language_smoke_test.py",
deps = [
":config_pb2",
"@rules_python//python/runfiles",
":integration_test_fixture",
],
)

py_test(
name = "cross_language_small_test",
srcs = [
"cross_language_small_test.py",
],
deps = [
":integration_test_fixture",
],
)

Expand Down
132 changes: 132 additions & 0 deletions pw_transfer/integration_test/cross_language_large_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
#!/usr/bin/env python3
# Copyright 2022 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
"""Cross-language pw_transfer tests that take tens of minutes to run.
Usage:
bazel run pw_transfer/integration_test:cross_language_large_test
Command-line arguments must be provided after a double-dash:
bazel run pw_transfer/integration_test:cross_language_large_test -- \
--server-port 3304
Which tests to run can be specified as command-line arguments:
bazel run pw_transfer/integration_test:cross_language_large_test -- \
LargeTransferIntegrationTest.test_3mb_write_dropped_data_1_java
"""

from parameterized import parameterized
import random

from google.protobuf import text_format

import test_fixture
from test_fixture import (TransferConfig, TransferIntegrationTest,
TransferIntegrationTestHarness)
from pigweed.pw_transfer.integration_test import config_pb2


# TODO(b/232805936): Extend tests to use different resource IDs and do multiple
# reads/writes.
class LargeTransferIntegrationTest(TransferIntegrationTest):
# Each set of transfer tests uses a different client/server port pair to
# allow tests to be run in parallel.
HARNESS_CONFIG = TransferIntegrationTestHarness.Config(server_port=3306,
client_port=3307)

@parameterized.expand([
("cpp"),
("java"),
("python"),
])
def test_3mb_write_dropped_data(self, client_type):
server_config = config_pb2.ServerConfig(
chunk_size_bytes=216,
pending_bytes=32 * 1024,
chunk_timeout_seconds=5,
transfer_service_retries=4,
extend_window_divisor=32,
)
client_config = config_pb2.ClientConfig(
max_retries=5,
initial_chunk_timeout_ms=10000,
chunk_timeout_ms=4000,
)
proxy_config = text_format.Parse(
"""
client_filter_stack: [
{ rate_limiter: {rate: 50000} },
{ hdlc_packetizer: {} },
{ data_dropper: {rate: 0.01, seed: 1649963713563718435} }
]
server_filter_stack: [
{ rate_limiter: {rate: 50000} },
{ hdlc_packetizer: {} },
{ data_dropper: {rate: 0.01, seed: 1649963713563718436} }
]""", config_pb2.ProxyConfig())

payload = random.Random(1649963713563718437).randbytes(3 * 1024 * 1024)

resource_id = 12

config = TransferConfig(server_config, client_config, proxy_config)
self.do_single_write(client_type, config, resource_id, payload)

@parameterized.expand([
("cpp"),
("java"),
("python"),
])
def test_3mb_write_reordered_data(self, client_type):
server_config = config_pb2.ServerConfig(
chunk_size_bytes=216,
pending_bytes=32 * 1024,
chunk_timeout_seconds=5,
transfer_service_retries=4,
extend_window_divisor=32,
)
client_config = config_pb2.ClientConfig(
max_retries=5,
initial_chunk_timeout_ms=10000,
chunk_timeout_ms=4000,
)
proxy_config = text_format.Parse(
"""
client_filter_stack: [
{ rate_limiter: {rate: 50000} },
{ hdlc_packetizer: {} },
{ data_transposer: {rate: 0.005, timeout: 0.5, seed: 1649963713563718435} }
]
server_filter_stack: [
{ rate_limiter: {rate: 50000} },
{ hdlc_packetizer: {} },
{ data_transposer: {rate: 0.005, timeout: 0.5, seed: 1649963713563718435} }
]""", config_pb2.ProxyConfig())

payload = random.Random(1649963713563718437).randbytes(3 * 1024 * 1024)

resource_id = 12

config = TransferConfig(server_config, client_config, proxy_config)
self.do_single_write(client_type, config, resource_id, payload)


if __name__ == '__main__':
test_fixture.run_tests_for(LargeTransferIntegrationTest)
72 changes: 72 additions & 0 deletions pw_transfer/integration_test/cross_language_medium_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#!/usr/bin/env python3
# Copyright 2022 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
"""Cross-language pw_transfer tests that take several seconds each.
Usage:
bazel run pw_transfer/integration_test:cross_language_medium_test
Command-line arguments must be provided after a double-dash:
bazel run pw_transfer/integration_test:cross_language_medium_test -- \
--server-port 3304
Which tests to run can be specified as command-line arguments:
bazel run pw_transfer/integration_test:cross_language_medium_test -- \
MediumTransferIntegrationTest.test_medium_client_write_1_java
"""

from parameterized import parameterized
import random

import test_fixture
from test_fixture import TransferIntegrationTestHarness


# TODO(b/232805936): Extend tests to use different resource IDs and do multiple
# reads/writes.
class MediumTransferIntegrationTest(test_fixture.TransferIntegrationTest):
# Each set of transfer tests uses a different client/server port pair to
# allow tests to be run in parallel.
HARNESS_CONFIG = TransferIntegrationTestHarness.Config(server_port=3304,
client_port=3305)

@parameterized.expand([
("cpp"),
("java"),
("python"),
])
def test_medium_client_write(self, client_type):
payload = random.Random(67336391945).randbytes(512)
config = self.default_config()
resource_id = 5
self.do_single_write(client_type, config, resource_id, payload)

@parameterized.expand([
("cpp"),
("java"),
("python"),
])
def test_large_hdlc_escape_client_write(self, client_type):
payload = b"~" * 98731
config = self.default_config()
resource_id = 5
self.do_single_write(client_type, config, resource_id, payload)


if __name__ == '__main__':
test_fixture.run_tests_for(MediumTransferIntegrationTest)
Loading

0 comments on commit 24c4722

Please sign in to comment.