All host tests currently pass Some async refactors may not work well on device, will try later
		
			
				
	
	
		
			95 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			95 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "uart.h"
 | |
| #include "uart_async.h"
 | |
| #include "fake_uart.h"
 | |
| 
 | |
| #include <gmock/gmock.h>
 | |
| #include <gtest/gtest.h>
 | |
| 
 | |
| #include <atomic>
 | |
| #include <chrono>
 | |
| #include <semaphore>
 | |
| #include <thread>
 | |
| 
 | |
| using namespace ::testing;
 | |
| 
 | |
| namespace {
 | |
| std::atomic<bool> terminate;
 | |
| std::counting_semaphore<12345> got_stuff(0);
 | |
| 
 | |
| buffer rx;
 | |
| 
 | |
| using namespace std::literals::chrono_literals;
 | |
| }
 | |
| 
 | |
| std::string drain_n(size_t n, std::chrono::system_clock::duration timeout) {
 | |
|     std::string txtout;
 | |
|     auto begin = std::chrono::system_clock::now();
 | |
| 
 | |
|     while (std::chrono::system_clock::now() < begin + timeout) {
 | |
|         auto out = FakeUart_Drain(n);
 | |
|         if (out.data.empty()) {
 | |
|             continue;
 | |
|         }
 | |
| 
 | |
|         auto strout = std::string_view(reinterpret_cast<char*>(out.data.data()),
 | |
|                                        out.data.size());
 | |
|         n -= out.data.size();
 | |
|         txtout.append(strout);
 | |
|         if (n < 1) {
 | |
|             return txtout;
 | |
|         }
 | |
|     }
 | |
|     return "";
 | |
| }
 | |
| 
 | |
| TEST(Uart, BasicSend) {
 | |
|     FakeUart_Reset();
 | |
|     terminate = false;
 | |
| 
 | |
|     constexpr std::string_view kTestData = "blarg";
 | |
|     auto buff = std::as_bytes(std::span{kTestData});
 | |
| 
 | |
|     async::schedule(UartWrite(buff).h);
 | |
|     std::thread t(
 | |
|         []() { async::main_loop([]() -> bool { return terminate; }); });
 | |
| 
 | |
|     std::string strout = drain_n(kTestData.size(), 1s);
 | |
|     EXPECT_EQ(strout, kTestData);
 | |
| 
 | |
|     terminate = true;
 | |
|     t.join();
 | |
| }
 | |
| 
 | |
| async::task<> test_echo() {
 | |
|     async::task<uint8_t> reader = UartReadLoop();
 | |
|     async::gimme<std::span<const std::byte>> feeder;
 | |
|     async::task<> writer = UartWriteLoop(feeder);
 | |
|     writer.h.resume();  // advance to first yield
 | |
|     while (1) {
 | |
|         uint8_t c = co_await reader;
 | |
|         feeder.feed(std::as_bytes(std::span{&c, 1}));
 | |
|         got_stuff.release();
 | |
|     }
 | |
| }
 | |
| 
 | |
| TEST(Uart, Echo) {
 | |
|     FakeUart_Reset();
 | |
|     terminate = false;
 | |
| 
 | |
|     constexpr std::string_view kTestData = "blargblaektrkblalasrjkh1!!";
 | |
|     auto buff = std::as_bytes(std::span{kTestData});
 | |
| 
 | |
|     async::schedule(test_echo().h);
 | |
|     std::thread t(
 | |
|         []() { async::main_loop([]() -> bool { return terminate; }); });
 | |
| 
 | |
|     for (int j = 0; j < 100; j++) {
 | |
|         FakeUart_Feed(buff);
 | |
|         std::string txtout = drain_n(kTestData.size(), 1s);
 | |
| 
 | |
|         ASSERT_EQ(txtout, kTestData);
 | |
|     }
 | |
| 
 | |
|     terminate = true;
 | |
|     t.join();
 | |
| } |