| // Copyright 2023 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. |
| |
| // clang-format off |
| #include "pw_rpc/internal/log_config.h" // PW_LOG_* macros must be first. |
| // clang-format on |
| |
| #include <cstring> |
| |
| #include "pw_log/log.h" |
| #include "pw_rpc/fuzz/argparse.h" |
| #include "pw_rpc/fuzz/engine.h" |
| #include "pw_rpc/integration_testing.h" |
| |
| namespace pw::rpc::fuzz { |
| namespace { |
| |
| int FuzzClient(int argc, char** argv) { |
| // TODO(aarongreen): Incorporate descriptions into usage message. |
| Vector<ArgParserVariant, 5> parsers{ |
| // Enables additional logging. |
| BoolParser("-v", "--verbose").set_default(false), |
| |
| // The number of actions to perform as part of the test. A value of 0 runs |
| // indefinitely. |
| UnsignedParser<size_t>("-n", "--num-actions").set_default(256), |
| |
| // The seed value for the PRNG. A value of 0 generates a seed. |
| UnsignedParser<uint64_t>("-s", "--seed").set_default(0), |
| |
| // The time, in milliseconds, that can elapse without triggering an error. |
| UnsignedParser<size_t>("-t", "--timeout").set_default(5000), |
| |
| // The port use to connect to the `test_rpc_server`. |
| UnsignedParser<uint16_t>("port").set_default(48000)}; |
| |
| if (!ParseArgs(parsers, argc, argv).ok()) { |
| PrintUsage(parsers, argv[0]); |
| return 1; |
| } |
| |
| bool verbose; |
| size_t num_actions; |
| uint64_t seed; |
| size_t timeout_ms; |
| uint16_t port; |
| if (!GetArg(parsers, "--verbose", &verbose).ok() || |
| !GetArg(parsers, "--num-actions", &num_actions).ok() || |
| !GetArg(parsers, "--seed", &seed).ok() || |
| !GetArg(parsers, "--timeout", &timeout_ms).ok() || |
| !GetArg(parsers, "port", &port).ok()) { |
| return 1; |
| } |
| |
| if (!seed) { |
| seed = chrono::SystemClock::now().time_since_epoch().count(); |
| } |
| |
| if (auto status = integration_test::InitializeClient(port); !status.ok()) { |
| PW_LOG_ERROR("Failed to initialize client: %s", pw_StatusString(status)); |
| return 1; |
| } |
| |
| if (num_actions == 0) { |
| num_actions = std::numeric_limits<size_t>::max(); |
| } |
| |
| Fuzzer fuzzer(integration_test::client(), integration_test::kChannelId); |
| fuzzer.set_verbose(verbose); |
| fuzzer.set_timeout(std::chrono::milliseconds(timeout_ms)); |
| fuzzer.Run(seed, num_actions); |
| integration_test::TerminateClient(); |
| return 0; |
| } |
| |
| } // namespace |
| } // namespace pw::rpc::fuzz |
| |
| int main(int argc, char** argv) { |
| return pw::rpc::fuzz::FuzzClient(argc, argv); |
| } |