| // 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 "modemfwd/journal.h" |
| |
| #include <memory> |
| #include <string> |
| #include <vector> |
| |
| #include <base/check.h> |
| #include <base/check_op.h> |
| #include <base/files/file_path.h> |
| #include <base/files/file_util.h> |
| #include <chromeos/switches/modemfwd_switches.h> |
| #include <gtest/gtest.h> |
| |
| #include "modemfwd/firmware_directory_stub.h" |
| #include "modemfwd/mock_modem_helper.h" |
| #include "modemfwd/modem_helper_directory_stub.h" |
| #include "modemfwd/scoped_temp_file.h" |
| |
| using ::testing::_; |
| using ::testing::Return; |
| |
| namespace modemfwd { |
| |
| namespace { |
| |
| constexpr char kDeviceId[] = "foobar"; |
| constexpr char kCarrierId[] = "carrier"; |
| |
| constexpr char kMainFirmwarePath[] = "main_firmware.fls"; |
| constexpr char kMainFirmwareVersion[] = "1.0"; |
| |
| constexpr char kOemFirmwarePath[] = "oem_cust.fls"; |
| constexpr char kOemFirmwareVersion[] = "1.0"; |
| |
| constexpr char kCarrierFirmwarePath[] = "carrier_firmware.fls"; |
| constexpr char kCarrierFirmwareVersion[] = "1.0"; |
| |
| } // namespace |
| |
| class JournalTest : public ::testing::Test { |
| public: |
| JournalTest() |
| : journal_file_(ScopedTempFile::Create()), |
| firmware_directory_(new FirmwareDirectoryStub), |
| modem_helper_directory_(new ModemHelperDirectoryStub) { |
| CHECK(journal_file_); |
| EXPECT_CALL(modem_helper_, GetFirmwareInfo(_)).Times(0); |
| modem_helper_directory_->AddHelper(kDeviceId, &modem_helper_); |
| } |
| |
| protected: |
| void SetUpJournal(const std::string& journal_text) { |
| CHECK_EQ(base::WriteFile(journal_file_->path(), journal_text.data(), |
| journal_text.size()), |
| journal_text.size()); |
| } |
| |
| std::unique_ptr<Journal> GetJournal() { |
| return OpenJournal(journal_file_->path(), firmware_directory_.get(), |
| modem_helper_directory_.get()); |
| } |
| |
| void AddMainFirmwareFile(const base::FilePath& firmware_path, |
| const std::string& version) { |
| FirmwareFileInfo firmware_info(firmware_path, version); |
| firmware_directory_->AddMainFirmware(kDeviceId, firmware_info); |
| } |
| |
| void AddOemFirmwareFile(const base::FilePath& firmware_path, |
| const std::string& version) { |
| FirmwareFileInfo firmware_info(firmware_path, version); |
| firmware_directory_->AddOemFirmware(kDeviceId, firmware_info); |
| } |
| |
| void AddCarrierFirmwareFile(const base::FilePath& firmware_path, |
| const std::string& version) { |
| FirmwareFileInfo firmware_info(firmware_path, version); |
| firmware_directory_->AddCarrierFirmware(kDeviceId, kCarrierId, |
| firmware_info); |
| } |
| |
| MockModemHelper modem_helper_; |
| |
| private: |
| std::unique_ptr<ScopedTempFile> journal_file_; |
| std::unique_ptr<FirmwareDirectoryStub> firmware_directory_; |
| std::unique_ptr<ModemHelperDirectoryStub> modem_helper_directory_; |
| }; |
| |
| TEST_F(JournalTest, EmptyJournal) { |
| EXPECT_CALL(modem_helper_, FlashFirmwares(_)).Times(0); |
| GetJournal(); |
| } |
| |
| TEST_F(JournalTest, PriorRunWasNotInterrupted_Main) { |
| auto journal = GetJournal(); |
| journal->MarkStartOfFlashingFirmware({kFwMain}, kDeviceId, kCarrierId); |
| journal->MarkEndOfFlashingFirmware(kDeviceId, kCarrierId); |
| |
| EXPECT_CALL(modem_helper_, FlashFirmwares(_)).Times(0); |
| // Getting a new journal simulates a crash or shutdown. |
| journal = GetJournal(); |
| } |
| |
| TEST_F(JournalTest, PriorRunWasInterrupted_Main) { |
| const base::FilePath main_fw_path(kMainFirmwarePath); |
| AddMainFirmwareFile(main_fw_path, kMainFirmwareVersion); |
| |
| auto journal = GetJournal(); |
| journal->MarkStartOfFlashingFirmware({kFwMain}, kDeviceId, kCarrierId); |
| |
| const std::vector<FirmwareConfig> main_cfg = { |
| {kFwMain, main_fw_path, kMainFirmwareVersion}}; |
| EXPECT_CALL(modem_helper_, FlashFirmwares(main_cfg)).WillOnce(Return(true)); |
| journal = GetJournal(); |
| |
| // Test that the journal is cleared afterwards, so we don't try to |
| // flash a second time if we crash again. |
| EXPECT_CALL(modem_helper_, FlashFirmwares(_)).Times(0); |
| journal = GetJournal(); |
| } |
| |
| TEST_F(JournalTest, PriorRunWasNotInterrupted_Oem) { |
| auto journal = GetJournal(); |
| journal->MarkStartOfFlashingFirmware({kFwOem}, kDeviceId, kCarrierId); |
| journal->MarkEndOfFlashingFirmware(kDeviceId, kCarrierId); |
| |
| EXPECT_CALL(modem_helper_, FlashFirmwares(_)).Times(0); |
| // Getting a new journal simulates a crash or shutdown. |
| journal = GetJournal(); |
| } |
| |
| TEST_F(JournalTest, PriorRunWasInterrupted_Oem) { |
| const base::FilePath oem_fw_path(kOemFirmwarePath); |
| AddOemFirmwareFile(oem_fw_path, kOemFirmwareVersion); |
| |
| auto journal = GetJournal(); |
| journal->MarkStartOfFlashingFirmware({kFwOem}, kDeviceId, kCarrierId); |
| |
| const std::vector<FirmwareConfig> oem_cfg = { |
| {kFwOem, oem_fw_path, kOemFirmwareVersion}}; |
| EXPECT_CALL(modem_helper_, FlashFirmwares(oem_cfg)).WillOnce(Return(true)); |
| journal = GetJournal(); |
| |
| // Test that the journal is cleared afterwards, so we don't try to |
| // flash a second time if we crash again. |
| EXPECT_CALL(modem_helper_, FlashFirmwares(_)).Times(0); |
| journal = GetJournal(); |
| } |
| |
| TEST_F(JournalTest, PriorRunWasNotInterrupted_Carrier) { |
| auto journal = GetJournal(); |
| journal->MarkStartOfFlashingFirmware({kFwCarrier}, kDeviceId, kCarrierId); |
| journal->MarkEndOfFlashingFirmware(kDeviceId, kCarrierId); |
| |
| EXPECT_CALL(modem_helper_, FlashFirmwares(_)).Times(0); |
| // Getting a new journal simulates a crash or shutdown. |
| journal = GetJournal(); |
| } |
| |
| TEST_F(JournalTest, PriorRunWasInterrupted_Carrier) { |
| const base::FilePath carrier_fw_path(kCarrierFirmwarePath); |
| AddCarrierFirmwareFile(carrier_fw_path, kCarrierFirmwareVersion); |
| |
| auto journal = GetJournal(); |
| journal->MarkStartOfFlashingFirmware({kFwCarrier}, kDeviceId, kCarrierId); |
| |
| const std::vector<FirmwareConfig> carrier_cfg = { |
| {kFwCarrier, carrier_fw_path, kCarrierFirmwareVersion}}; |
| EXPECT_CALL(modem_helper_, FlashFirmwares(carrier_cfg)) |
| .WillOnce(Return(true)); |
| journal = GetJournal(); |
| |
| // Test that the journal is cleared afterwards, so we don't try to |
| // flash a second time if we crash again. |
| EXPECT_CALL(modem_helper_, FlashFirmwares(_)).Times(0); |
| journal = GetJournal(); |
| } |
| |
| TEST_F(JournalTest, PriorRunWasInterrupted_MultipleFirmwares) { |
| const base::FilePath main_fw_path(kMainFirmwarePath); |
| AddMainFirmwareFile(main_fw_path, kMainFirmwareVersion); |
| const base::FilePath oem_fw_path(kOemFirmwarePath); |
| AddOemFirmwareFile(oem_fw_path, kOemFirmwareVersion); |
| const base::FilePath carrier_fw_path(kCarrierFirmwarePath); |
| AddCarrierFirmwareFile(carrier_fw_path, kCarrierFirmwareVersion); |
| |
| auto journal = GetJournal(); |
| journal->MarkStartOfFlashingFirmware({kFwMain, kFwOem, kFwCarrier}, kDeviceId, |
| kCarrierId); |
| |
| const std::vector<FirmwareConfig> all_cfg = { |
| {kFwMain, main_fw_path, kMainFirmwareVersion}, |
| {kFwOem, oem_fw_path, kOemFirmwareVersion}, |
| {kFwCarrier, carrier_fw_path, kCarrierFirmwareVersion}}; |
| EXPECT_CALL(modem_helper_, FlashFirmwares(all_cfg)).WillOnce(Return(true)); |
| journal = GetJournal(); |
| |
| // Test that the journal is cleared afterwards, so we don't try to |
| // flash a second time if we crash again. |
| EXPECT_CALL(modem_helper_, FlashFirmwares(_)).Times(0); |
| journal = GetJournal(); |
| } |
| |
| TEST_F(JournalTest, IgnoreMalformedJournalEntries) { |
| SetUpJournal("blahblah"); |
| EXPECT_CALL(modem_helper_, FlashFirmwares(_)).Times(0); |
| GetJournal(); |
| } |
| |
| TEST_F(JournalTest, MultipleEntries) { |
| auto journal = GetJournal(); |
| journal->MarkStartOfFlashingFirmware({kFwMain}, kDeviceId, kCarrierId); |
| journal->MarkEndOfFlashingFirmware(kDeviceId, kCarrierId); |
| journal->MarkStartOfFlashingFirmware({kFwCarrier}, kDeviceId, kCarrierId); |
| journal->MarkEndOfFlashingFirmware(kDeviceId, kCarrierId); |
| |
| EXPECT_CALL(modem_helper_, FlashFirmwares(_)).Times(0); |
| journal = GetJournal(); |
| } |
| |
| } // namespace modemfwd |