Skip to content

Commit

Permalink
Add serial port example
Browse files Browse the repository at this point in the history
Add an example connecting to a serial port and writing a message. This
is tested by creating a virtual serial port with the output written to
file.

Bazel test interaction with the filesystem prevents creation of a RW
device. As a result, `//test:virtual_serial_port_test` is defined as a
`sh_binary` that can be run with:

  bazel run //test:virtual_serial_port_test

Change-Id: I1be9cb2e8b13fa972084d66fa2c6ddffb23ae3cc
  • Loading branch information
oliverlee committed Jul 24, 2023
1 parent 8f8479a commit e4dadf4
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 1 deletion.
21 changes: 21 additions & 0 deletions WORKSPACE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,27 @@ register_toolchains(
"@gcc_12_toolchain//:toolchain",
)

ASIO_VERSION = "d6b95c0188e0359a8cdbdb6571f0cbacf11a538c"

http_archive(
name = "asio",
build_file_content = """
load("@rules_cc//cc:defs.bzl", "cc_library")
cc_library(
name = "asio",
hdrs = glob(["asio/include/**"]),
includes = ["asio/include"],
defines = [
],
visibility = ["//visibility:public"],
)
""",
sha256 = "c4eae0910b8fcf2df8d32dc0ab67b032e9876491a5968faad32d330fd41e119c",
strip_prefix = "asio-%s" % ASIO_VERSION,
url = "https://github.com/chriskohlhoff/asio/archive/%s.tar.gz" % ASIO_VERSION,
)

FMT_VERSION = "dd5a9691f992f7f257243cbecb516a4ab584dcde"

http_archive(
Expand Down
32 changes: 31 additions & 1 deletion test/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,4 +1,34 @@
load("@rules_cc//cc:defs.bzl", "cc_test")
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_test")

# With GCC and tsan:
# error: 'atomic_thread_fence' is not supported with '-fsanitize=thread' [-Werror=tsan]
config_setting(
name = "gcc_tsan",
flag_values = {"@bazel_tools//tools/cpp:compiler": "gcc"},
values = {"features": "tsan"},
)

cc_binary(
name = "serial_test",
srcs = ["serial_test.cpp"],
target_compatible_with = select({
":gcc_tsan": ["@platforms//:incompatible"],
"//conditions:default": [],
}),
deps = [
"@asio",
"@fmt",
],
)

# creating a file/device with socat will fail as a `sh_test`
# https://bazel.build/reference/test-encyclopedia#test-interaction-filesystem
sh_binary(
name = "virtual_serial_port_test",
srcs = ["test_virtual_serial_port.sh"],
args = ["$(rootpath :serial_test)"],
data = [":serial_test"],
)

cc_test(
name = "dummy_test",
Expand Down
35 changes: 35 additions & 0 deletions test/serial_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include <asio.hpp>
#include <cstdlib>
#include <fmt/core.h>
#include <stdexcept>
#include <string_view>

auto main(int argc, const char** argv) -> int
{
if (argc < 2) {
throw std::runtime_error{"device path not specified"};
}

auto ctx = asio::io_context{};

// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
auto serial = asio::serial_port{ctx, argv[1]};
{
using opt = asio::serial_port_base;

// NOLINTBEGIN(readability-magic-numbers)
serial.set_option(opt::baud_rate{115200});
serial.set_option(opt::character_size{8});
serial.set_option(opt::parity{opt::parity::none});
serial.set_option(opt::stop_bits{opt::stop_bits::one});
// NOLINTEND(readability-magic-numbers)
}

constexpr auto sv = std::string_view{"hello, world!\n"};

for (auto buf = asio::buffer(sv.data(), sv.size()); buf.size() != 0;) {
buf += serial.write_some(asio::buffer(sv.data(), sv.size()));
}

return 0;
}
25 changes: 25 additions & 0 deletions test/test_virtual_serial_port.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/env bash

set -euo pipefail

# https://bazel.build/reference/test-encyclopedia#test-interaction-filesystem
TEST_TMPDIR="${TEST_TEMPDIR:-.}"

dev="$TEST_TMPDIR/virt0"
log="$TEST_TMPDIR/out"
bin=$1

rm -f "$log"

socat PTY,link="$dev",raw,echo=0 OPEN:"$log",creat=1,excl=1 &
socat_pid=$!

while [ ! -e "$dev" ]; do
sleep 0.1
done

"$bin" "$dev"

kill "$socat_pid"

grep -q "hello, world!" "$log"

0 comments on commit e4dadf4

Please sign in to comment.