| // Copyright 2018 The Chromium OS 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 <fcntl.h> |
| #include <poll.h> |
| #include <sys/stat.h> |
| #include <unistd.h> |
| #include <cstdint> |
| |
| #include <base/bind.h> |
| #include <base/files/file_util.h> |
| #include <base/files/scoped_file.h> |
| #include <base/files/scoped_temp_dir.h> |
| #include <base/message_loop/message_loop.h> |
| #include <base/run_loop.h> |
| #include <gmock/gmock.h> |
| #include <gtest/gtest.h> |
| |
| #include "diagnostics/diagnosticsd/bind_utils.h" |
| #include "diagnostics/diagnosticsd/diagnosticsd_ec_event_service.h" |
| #include "diagnostics/diagnosticsd/ec_constants.h" |
| |
| using testing::_; |
| using testing::Invoke; |
| using testing::StrictMock; |
| |
| namespace diagnostics { |
| |
| namespace { |
| |
| class MockDiagnosticsdEcEventServiceDelegate |
| : public DiagnosticsdEcEventService::Delegate { |
| public: |
| MOCK_METHOD1(SendGrpcEcEventToDiagnosticsProcessor, |
| void(const DiagnosticsdEcEventService::EcEvent& ec_event)); |
| }; |
| |
| class DiagnosticsdEcEventServiceTest : public testing::Test { |
| protected: |
| DiagnosticsdEcEventServiceTest() : service_(&delegate_) {} |
| |
| void SetUp() override { |
| ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
| service()->set_root_dir_for_testing(temp_dir_.GetPath()); |
| service()->set_event_fd_events_for_testing(POLLIN); |
| } |
| |
| void TearDown() override { |
| base::RunLoop run_loop; |
| service_.Shutdown(run_loop.QuitClosure()); |
| run_loop.Run(); |
| } |
| |
| void CreateSysfsFile() { |
| base::FilePath file_path = sysfs_file_path(); |
| ASSERT_TRUE(base::CreateDirectory(file_path.DirName())); |
| ASSERT_EQ(mkfifo(file_path.value().c_str(), 0600), 0); |
| } |
| |
| base::FilePath sysfs_file_path() { |
| return temp_dir_.GetPath().Append(kEcEventSysfsPath); |
| } |
| |
| // Must be open only after |service_->Start()| call. Otherwise, it will |
| // block thread. |
| void InitFifoWriteEnd() { |
| ASSERT_EQ(fifo_write_end_.get(), -1); |
| fifo_write_end_.reset(open(sysfs_file_path().value().c_str(), O_WRONLY)); |
| ASSERT_NE(fifo_write_end_.get(), -1); |
| } |
| |
| void WriteEventToSysfsFile( |
| const DiagnosticsdEcEventService::EcEvent& ec_event, |
| const base::RepeatingClosure& callback) { |
| ASSERT_EQ(write(fifo_write_end_.get(), &ec_event, sizeof(ec_event)), |
| sizeof(ec_event)); |
| |
| EXPECT_CALL(delegate_, SendGrpcEcEventToDiagnosticsProcessor(ec_event)) |
| .WillOnce(Invoke( |
| [callback](const DiagnosticsdEcEventService::EcEvent& ec_event) { |
| callback.Run(); |
| })); |
| } |
| |
| MockDiagnosticsdEcEventServiceDelegate* delegate() { return &delegate_; } |
| |
| DiagnosticsdEcEventService* service() { return &service_; } |
| |
| private: |
| base::MessageLoop message_loop_; |
| StrictMock<MockDiagnosticsdEcEventServiceDelegate> delegate_; |
| DiagnosticsdEcEventService service_; |
| |
| base::ScopedTempDir temp_dir_; |
| |
| base::ScopedFD fifo_write_end_; |
| }; |
| |
| } // namespace |
| |
| TEST_F(DiagnosticsdEcEventServiceTest, Start) { |
| CreateSysfsFile(); |
| ASSERT_TRUE(service()->Start()); |
| } |
| |
| TEST_F(DiagnosticsdEcEventServiceTest, StartFailure) { |
| ASSERT_FALSE(service()->Start()); |
| } |
| |
| TEST_F(DiagnosticsdEcEventServiceTest, ReadEvent) { |
| CreateSysfsFile(); |
| ASSERT_TRUE(service()->Start()); |
| |
| InitFifoWriteEnd(); |
| |
| base::RunLoop run_loop; |
| const uint16_t data[6] = {0xaaaa, 0xbbbb, 0xcccc, 0xdddd, 0xeeee, 0xffff}; |
| WriteEventToSysfsFile( |
| DiagnosticsdEcEventService::EcEvent(0x8888, 0x9999, data), |
| run_loop.QuitClosure()); |
| run_loop.Run(); |
| } |
| |
| TEST_F(DiagnosticsdEcEventServiceTest, ReadManyEvent) { |
| CreateSysfsFile(); |
| ASSERT_TRUE(service()->Start()); |
| |
| InitFifoWriteEnd(); |
| |
| base::RunLoop run_loop; |
| base::RepeatingClosure callback = BarrierClosure( |
| 2 /* num_closures */, run_loop.QuitClosure() /* done closure */); |
| const uint16_t data1[6] = {0xaaaa, 0xbbbb, 0xcccc, 0xdddd, 0xeeee, 0xffff}; |
| WriteEventToSysfsFile( |
| DiagnosticsdEcEventService::EcEvent(0x8888, 0x9999, data1), callback); |
| const uint16_t data2[6] = {0x0000, 0x1111, 0x2222, 0x3333, 0x4444, 0x5555}; |
| WriteEventToSysfsFile( |
| DiagnosticsdEcEventService::EcEvent(0x6666, 0x7777, data2), callback); |
| run_loop.Run(); |
| } |
| |
| } // namespace diagnostics |