| // Copyright 2017 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/firmware_directory.h" |
| |
| #include <memory> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include <base/files/file.h> |
| #include <base/files/scoped_temp_dir.h> |
| #include <gtest/gtest.h> |
| |
| namespace { |
| |
| constexpr char kDeviceId[] = "device-id"; |
| |
| constexpr char kMainFirmwareFile[] = "NAND_10.20.30.40.fls"; |
| constexpr char kMainFirmwareVersion[] = "10.20.30.40"; |
| |
| constexpr char kCarrierA[] = "CarrierA"; |
| constexpr char kCarrierFirmwareFile1[] = "CarrierA_40.30.20.10.fls"; |
| constexpr char kCarrierFirmwareVersion1[] = "40.30.20.10"; |
| |
| constexpr char kCarrierB[] = "CarrierB"; |
| constexpr char kCarrierFirmwareFile2[] = "Custom_B_50_60.fls"; |
| constexpr char kCarrierFirmwareVersion2[] = "50.60.70.80"; |
| |
| constexpr char kCarrierC[] = "CarrierC"; |
| |
| constexpr char kGenericCarrierFirmwareFile[] = "Generic_V1.59.3.fls"; |
| constexpr char kGenericCarrierFirmwareVersion[] = "V1.59.3"; |
| |
| // To generate a manifest, execute the following: |
| // protoc --proto_path . --encode modemfwd.FirmwareManifest \ |
| // firmware_manifest.proto < path/to/file.prototxt | xxd -i |
| |
| // generated from find_firmware.prototxt |
| std::vector<char> kFindFirmwareManifest{ |
| 0x0a, 0x2e, 0x0a, 0x14, 0x4e, 0x41, 0x4e, 0x44, 0x5f, 0x31, 0x30, 0x2e, |
| 0x32, 0x30, 0x2e, 0x33, 0x30, 0x2e, 0x34, 0x30, 0x2e, 0x66, 0x6c, 0x73, |
| 0x12, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x2d, 0x69, 0x64, 0x1a, |
| 0x0b, 0x31, 0x30, 0x2e, 0x32, 0x30, 0x2e, 0x33, 0x30, 0x2e, 0x34, 0x30, |
| 0x12, 0x3c, 0x0a, 0x18, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x41, |
| 0x5f, 0x34, 0x30, 0x2e, 0x33, 0x30, 0x2e, 0x32, 0x30, 0x2e, 0x31, 0x30, |
| 0x2e, 0x66, 0x6c, 0x73, 0x12, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, |
| 0x2d, 0x69, 0x64, 0x1a, 0x08, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, |
| 0x41, 0x22, 0x0b, 0x34, 0x30, 0x2e, 0x33, 0x30, 0x2e, 0x32, 0x30, 0x2e, |
| 0x31, 0x30 |
| }; |
| |
| // generated from firmware_for_different_carrier.prototxt |
| std::vector<char> kDifferentCarrierManifest{ |
| 0x12, 0x3c, 0x0a, 0x18, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x41, |
| 0x5f, 0x34, 0x30, 0x2e, 0x33, 0x30, 0x2e, 0x32, 0x30, 0x2e, 0x31, 0x30, |
| 0x2e, 0x66, 0x6c, 0x73, 0x12, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, |
| 0x2d, 0x69, 0x64, 0x1a, 0x08, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, |
| 0x41, 0x22, 0x0b, 0x34, 0x30, 0x2e, 0x33, 0x30, 0x2e, 0x32, 0x30, 0x2e, |
| 0x31, 0x30 |
| }; |
| |
| // generated from firmware_for_different_device.prototxt |
| std::vector<char> kDifferentDeviceManifest{ |
| 0x0a, 0x30, 0x0a, 0x14, 0x4e, 0x41, 0x4e, 0x44, 0x5f, 0x31, 0x30, 0x2e, |
| 0x32, 0x30, 0x2e, 0x33, 0x30, 0x2e, 0x34, 0x30, 0x2e, 0x66, 0x6c, 0x73, |
| 0x12, 0x0b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x2d, 0x69, 0x64, 0x2d, |
| 0x32, 0x1a, 0x0b, 0x31, 0x30, 0x2e, 0x32, 0x30, 0x2e, 0x33, 0x30, 0x2e, |
| 0x34, 0x30 |
| }; |
| |
| // generated from multiple_carrier_firmware.prototxt |
| std::vector<char> kMultipleCarrierFirmwareManifest{ |
| 0x12, 0x3c, 0x0a, 0x18, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x41, |
| 0x5f, 0x34, 0x30, 0x2e, 0x33, 0x30, 0x2e, 0x32, 0x30, 0x2e, 0x31, 0x30, |
| 0x2e, 0x66, 0x6c, 0x73, 0x12, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, |
| 0x2d, 0x69, 0x64, 0x1a, 0x08, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, |
| 0x41, 0x22, 0x0b, 0x34, 0x30, 0x2e, 0x33, 0x30, 0x2e, 0x32, 0x30, 0x2e, |
| 0x31, 0x30, 0x12, 0x36, 0x0a, 0x12, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, |
| 0x5f, 0x42, 0x5f, 0x35, 0x30, 0x5f, 0x36, 0x30, 0x2e, 0x66, 0x6c, 0x73, |
| 0x12, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x2d, 0x69, 0x64, 0x1a, |
| 0x08, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x42, 0x22, 0x0b, 0x35, |
| 0x30, 0x2e, 0x36, 0x30, 0x2e, 0x37, 0x30, 0x2e, 0x38, 0x30 |
| }; |
| |
| // generated from generic_firmware.prototxt |
| std::vector<char> kGenericFirmwareManifest{ |
| 0x12, 0x32, 0x0a, 0x13, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, |
| 0x56, 0x31, 0x2e, 0x35, 0x39, 0x2e, 0x33, 0x2e, 0x66, 0x6c, 0x73, 0x12, |
| 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x2d, 0x69, 0x64, 0x1a, 0x07, |
| 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x22, 0x07, 0x56, 0x31, 0x2e, |
| 0x35, 0x39, 0x2e, 0x33 |
| }; |
| |
| // generated from specific_before_generic.prototxt |
| std::vector<char> kSpecificBeforeGenericManifest{ |
| 0x12, 0x32, 0x0a, 0x13, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, |
| 0x56, 0x31, 0x2e, 0x35, 0x39, 0x2e, 0x33, 0x2e, 0x66, 0x6c, 0x73, 0x12, |
| 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x2d, 0x69, 0x64, 0x1a, 0x07, |
| 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x22, 0x07, 0x56, 0x31, 0x2e, |
| 0x35, 0x39, 0x2e, 0x33, 0x12, 0x3c, 0x0a, 0x18, 0x43, 0x61, 0x72, 0x72, |
| 0x69, 0x65, 0x72, 0x41, 0x5f, 0x34, 0x30, 0x2e, 0x33, 0x30, 0x2e, 0x32, |
| 0x30, 0x2e, 0x31, 0x30, 0x2e, 0x66, 0x6c, 0x73, 0x12, 0x09, 0x64, 0x65, |
| 0x76, 0x69, 0x63, 0x65, 0x2d, 0x69, 0x64, 0x1a, 0x08, 0x43, 0x61, 0x72, |
| 0x72, 0x69, 0x65, 0x72, 0x41, 0x22, 0x0b, 0x34, 0x30, 0x2e, 0x33, 0x30, |
| 0x2e, 0x32, 0x30, 0x2e, 0x31, 0x30 |
| }; |
| |
| // generated from two_carrier_firmware.prototxt |
| std::vector<char> kTwoCarrierFirmwareManifest{ |
| 0x12, 0x46, 0x0a, 0x18, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x41, |
| 0x5f, 0x34, 0x30, 0x2e, 0x33, 0x30, 0x2e, 0x32, 0x30, 0x2e, 0x31, 0x30, |
| 0x2e, 0x66, 0x6c, 0x73, 0x12, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, |
| 0x2d, 0x69, 0x64, 0x1a, 0x08, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, |
| 0x41, 0x1a, 0x08, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x42, 0x22, |
| 0x0b, 0x34, 0x30, 0x2e, 0x33, 0x30, 0x2e, 0x32, 0x30, 0x2e, 0x31, 0x30 |
| }; |
| |
| // generated from malformed_main_firmware.prototxt |
| std::vector<char> kMalformedMainFirmwareManifest{ |
| 0x0a, 0x20, 0x0a, 0x13, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x5f, 0x66, |
| 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x66, 0x6c, 0x73, 0x12, |
| 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x2d, 0x69, 0x64 |
| }; |
| |
| // generated from malformed_carrier_firmware.prototxt |
| std::vector<char> kMalformedCarrierFirmwareManifest{ |
| 0x12, 0x1b, 0x12, 0x09, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x2d, 0x69, |
| 0x64, 0x1a, 0x08, 0x43, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x41, 0x22, |
| 0x04, 0x39, 0x30, 0x30, 0x31 |
| }; |
| |
| } // namespace |
| |
| namespace modemfwd { |
| |
| class FirmwareDirectoryTest : public ::testing::Test { |
| public: |
| FirmwareDirectoryTest() { |
| CHECK(temp_dir_.CreateUniqueTempDir()); |
| } |
| ~FirmwareDirectoryTest() override = default; |
| |
| protected: |
| void SetUpDirectory(const std::vector<char>& manifest) { |
| base::File file(temp_dir_.path().Append("manifest.proto"), |
| base::File::FLAG_CREATE | base::File::FLAG_WRITE); |
| CHECK(file.IsValid()); |
| file.WriteAtCurrentPos(manifest.data(), manifest.size()); |
| firmware_directory_ = CreateFirmwareDirectory(temp_dir_.path()); |
| } |
| |
| std::unique_ptr<FirmwareDirectory> firmware_directory_; |
| |
| private: |
| base::ScopedTempDir temp_dir_; |
| }; |
| |
| TEST_F(FirmwareDirectoryTest, FindFirmware) { |
| SetUpDirectory(kFindFirmwareManifest); |
| |
| FirmwareFileInfo info; |
| EXPECT_TRUE(firmware_directory_->FindMainFirmware(kDeviceId, &info)); |
| EXPECT_EQ(kMainFirmwareFile, info.firmware_path.BaseName().value()); |
| EXPECT_EQ(kMainFirmwareVersion, info.version); |
| std::string carrier_a(kCarrierA); |
| EXPECT_TRUE( |
| firmware_directory_->FindCarrierFirmware(kDeviceId, &carrier_a, &info)); |
| EXPECT_EQ(kCarrierA, carrier_a); |
| EXPECT_EQ(kCarrierFirmwareFile1, info.firmware_path.BaseName().value()); |
| EXPECT_EQ(kCarrierFirmwareVersion1, info.version); |
| } |
| |
| TEST_F(FirmwareDirectoryTest, NoFirmwareForDevice) { |
| SetUpDirectory({}); |
| |
| FirmwareFileInfo info; |
| EXPECT_FALSE(firmware_directory_->FindMainFirmware(kDeviceId, &info)); |
| std::string carrier_a(kCarrierA); |
| EXPECT_FALSE( |
| firmware_directory_->FindCarrierFirmware(kDeviceId, &carrier_a, &info)); |
| } |
| |
| TEST_F(FirmwareDirectoryTest, FirmwareForDifferentCarrier) { |
| SetUpDirectory(kDifferentCarrierManifest); |
| |
| FirmwareFileInfo info; |
| std::string carrier_b(kCarrierB); |
| EXPECT_FALSE( |
| firmware_directory_->FindCarrierFirmware(kDeviceId, &carrier_b, &info)); |
| } |
| |
| TEST_F(FirmwareDirectoryTest, FirmwareForDifferentDevice) { |
| SetUpDirectory(kDifferentDeviceManifest); |
| |
| FirmwareFileInfo info; |
| EXPECT_FALSE(firmware_directory_->FindMainFirmware(kDeviceId, &info)); |
| } |
| |
| TEST_F(FirmwareDirectoryTest, MultipleCarrierFirmware) { |
| SetUpDirectory(kMultipleCarrierFirmwareManifest); |
| |
| FirmwareFileInfo info; |
| std::string carrier_a(kCarrierA); |
| EXPECT_TRUE( |
| firmware_directory_->FindCarrierFirmware(kDeviceId, &carrier_a, &info)); |
| EXPECT_EQ(kCarrierA, carrier_a); |
| EXPECT_EQ(kCarrierFirmwareFile1, info.firmware_path.BaseName().value()); |
| EXPECT_EQ(kCarrierFirmwareVersion1, info.version); |
| |
| std::string carrier_b(kCarrierB); |
| EXPECT_TRUE( |
| firmware_directory_->FindCarrierFirmware(kDeviceId, &carrier_b, &info)); |
| EXPECT_EQ(kCarrierB, carrier_b); |
| EXPECT_EQ(kCarrierFirmwareFile2, info.firmware_path.BaseName().value()); |
| EXPECT_EQ(kCarrierFirmwareVersion2, info.version); |
| } |
| |
| TEST_F(FirmwareDirectoryTest, GenericFirmware) { |
| SetUpDirectory(kGenericFirmwareManifest); |
| |
| FirmwareFileInfo info; |
| std::string carrier_a(kCarrierA); |
| EXPECT_TRUE( |
| firmware_directory_->FindCarrierFirmware(kDeviceId, &carrier_a, &info)); |
| EXPECT_EQ(FirmwareDirectory::kGenericCarrierId, carrier_a); |
| EXPECT_EQ(kGenericCarrierFirmwareFile, info.firmware_path.BaseName().value()); |
| EXPECT_EQ(kGenericCarrierFirmwareVersion, info.version); |
| } |
| |
| TEST_F(FirmwareDirectoryTest, SpecificBeforeGeneric) { |
| SetUpDirectory(kSpecificBeforeGenericManifest); |
| |
| FirmwareFileInfo info; |
| std::string carrier_a(kCarrierA); |
| EXPECT_TRUE( |
| firmware_directory_->FindCarrierFirmware(kDeviceId, &carrier_a, &info)); |
| EXPECT_EQ(kCarrierA, carrier_a); |
| EXPECT_EQ(kCarrierFirmwareFile1, info.firmware_path.BaseName().value()); |
| EXPECT_EQ(kCarrierFirmwareVersion1, info.version); |
| } |
| |
| TEST_F(FirmwareDirectoryTest, FirmwareSupportsTwoCarriers) { |
| SetUpDirectory(kTwoCarrierFirmwareManifest); |
| |
| FirmwareFileInfo info; |
| std::string carrier_a(kCarrierA); |
| EXPECT_TRUE( |
| firmware_directory_->FindCarrierFirmware(kDeviceId, &carrier_a, &info)); |
| EXPECT_EQ(kCarrierA, carrier_a); |
| EXPECT_EQ(kCarrierFirmwareFile1, info.firmware_path.BaseName().value()); |
| EXPECT_EQ(kCarrierFirmwareVersion1, info.version); |
| |
| std::string carrier_b(kCarrierB); |
| EXPECT_TRUE( |
| firmware_directory_->FindCarrierFirmware(kDeviceId, &carrier_b, &info)); |
| EXPECT_EQ(kCarrierB, carrier_b); |
| EXPECT_EQ(kCarrierFirmwareFile1, info.firmware_path.BaseName().value()); |
| EXPECT_EQ(kCarrierFirmwareVersion1, info.version); |
| |
| std::string carrier_c(kCarrierC); |
| EXPECT_FALSE( |
| firmware_directory_->FindCarrierFirmware(kDeviceId, &carrier_c, &info)); |
| } |
| |
| TEST_F(FirmwareDirectoryTest, MalformedMainEntry) { |
| SetUpDirectory(kMalformedMainFirmwareManifest); |
| |
| FirmwareFileInfo info; |
| EXPECT_FALSE(firmware_directory_->FindMainFirmware(kDeviceId, &info)); |
| } |
| |
| TEST_F(FirmwareDirectoryTest, MalformedCarrierEntry) { |
| SetUpDirectory(kMalformedCarrierFirmwareManifest); |
| |
| FirmwareFileInfo info; |
| std::string carrier_a(kCarrierA); |
| EXPECT_FALSE( |
| firmware_directory_->FindCarrierFirmware(kDeviceId, &carrier_a, &info)); |
| } |
| |
| } // namespace modemfwd |