| // Copyright 2019 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "console.h" |
| |
| #include <lib/fidl/cpp/wire/client.h> |
| |
| #include <fbl/string_buffer.h> |
| #include <zxtest/zxtest.h> |
| |
| namespace { |
| |
| // Verify that calling Read() returns data from the RxSource |
| TEST(ConsoleTestCase, Read) { |
| constexpr size_t kReadSize = 10; |
| constexpr size_t kWriteCount = kReadSize - 1; |
| constexpr uint8_t kWrittenByte = 3; |
| |
| sync_completion_t rx_source_done; |
| Console::RxSource rx_source = [write_count = kWriteCount, |
| &rx_source_done](uint8_t* byte) mutable { |
| if (write_count == 0) { |
| sync_completion_signal(&rx_source_done); |
| return ZX_ERR_SHOULD_WAIT; |
| } |
| |
| *byte = kWrittenByte; |
| write_count--; |
| return ZX_OK; |
| }; |
| Console::TxSink tx_sink = [](const uint8_t* buffer, size_t length) { return ZX_OK; }; |
| |
| auto [client_end, server_end] = fidl::Endpoints<fuchsia_hardware_pty::Device>::Create(); |
| |
| async::Loop loop(&kAsyncLoopConfigNeverAttachToThread); |
| zx::eventpair event1, event2; |
| ASSERT_OK(zx::eventpair::create(0, &event1, &event2)); |
| Console console(loop.dispatcher(), std::move(event1), std::move(event2), std::move(rx_source), |
| std::move(tx_sink)); |
| ASSERT_OK(sync_completion_wait_deadline(&rx_source_done, ZX_TIME_INFINITE)); |
| fidl::BindServer(loop.dispatcher(), std::move(server_end), |
| static_cast<fidl::WireServer<fuchsia_hardware_pty::Device>*>(&console)); |
| fidl::WireClient client(std::move(client_end), loop.dispatcher()); |
| |
| client->Read(kReadSize).ThenExactlyOnce( |
| [kWriteCount, |
| kWrittenByte](fidl::WireUnownedResult<fuchsia_hardware_pty::Device::Read>& result) { |
| ASSERT_OK(result.status()); |
| fit::result response = result.value(); |
| ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value())); |
| ASSERT_EQ(response.value()->data.count(), kWriteCount); |
| for (uint8_t byte : response.value()->data) { |
| ASSERT_EQ(byte, kWrittenByte); |
| } |
| }); |
| ASSERT_OK(loop.RunUntilIdle()); |
| } |
| |
| // Verify that calling Write() writes data to the TxSink |
| TEST(ConsoleTestCase, Write) { |
| uint8_t kExpectedBuffer[] = "Hello World"; |
| size_t kExpectedLength = sizeof(kExpectedBuffer) - 1; |
| |
| // Cause the RX thread to exit |
| Console::RxSource rx_source = [](uint8_t* byte) { return ZX_ERR_NOT_SUPPORTED; }; |
| Console::TxSink tx_sink = [kExpectedLength, &kExpectedBuffer](const uint8_t* buffer, |
| size_t length) { |
| EXPECT_EQ(length, kExpectedLength); |
| EXPECT_BYTES_EQ(buffer, kExpectedBuffer, length); |
| return ZX_OK; |
| }; |
| |
| auto [client_end, server_end] = fidl::Endpoints<fuchsia_hardware_pty::Device>::Create(); |
| |
| async::Loop loop(&kAsyncLoopConfigNeverAttachToThread); |
| zx::eventpair event1, event2; |
| ASSERT_OK(zx::eventpair::create(0, &event1, &event2)); |
| Console console(loop.dispatcher(), std::move(event1), std::move(event2), std::move(rx_source), |
| std::move(tx_sink)); |
| fidl::BindServer(loop.dispatcher(), std::move(server_end), |
| static_cast<fidl::WireServer<fuchsia_hardware_pty::Device>*>(&console)); |
| fidl::WireClient client(std::move(client_end), loop.dispatcher()); |
| |
| client->Write(fidl::VectorView<uint8_t>::FromExternal(kExpectedBuffer, kExpectedLength)) |
| .ThenExactlyOnce( |
| [kExpectedLength](fidl::WireUnownedResult<fuchsia_hardware_pty::Device::Write>& result) { |
| ASSERT_OK(result.status()); |
| fit::result response = result.value(); |
| ASSERT_TRUE(response.is_ok(), "%s", zx_status_get_string(response.error_value())); |
| ASSERT_EQ(response.value()->actual_count, kExpectedLength); |
| }); |
| ASSERT_OK(loop.RunUntilIdle()); |
| } |
| |
| } // namespace |