blob: 0d21cf304e65ce21af7bd33574310390f47d3bde [file] [log] [blame]
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <flashupdate/config.hpp>
#include <nlohmann/json.hpp>
#include <stdplus/gtest/tmp.hpp>
#include <fstream>
#include <string>
#include <gtest/gtest.h>
namespace flashupdate
{
class ConfigTest : public stdplus::gtest::TestWithTmp
{};
TEST_F(ConfigTest, EmptyConfig)
{
std::ofstream testfile;
std::string emptyFilename = CaseTmpDir() + "/empty.json";
testfile.open(emptyFilename, std::ios::out);
auto empty = R"({})"_json;
testfile << empty.dump();
testfile.flush();
EXPECT_THROW(createConfig(emptyFilename, 0),
nlohmann::detail::out_of_range);
}
TEST_F(ConfigTest, ValidConfigWithMissingPirmaryMuxSelect)
{
std::ofstream testfile;
std::string missingPrimaryMuxFilename =
CaseTmpDir() + "/missing_primary_mux.json";
testfile.open(missingPrimaryMuxFilename, std::ios::out);
auto valid = R"(
{
"flash": {
"validation_key": ["prod.pem", "dev.pem"],
"primary": {
"location": "mtd,primary",
"mux_select": null
},
"secondary": [
{
"location": "mtd,secondary0",
"mux_select": null
}
],
"device_id": "device_id",
"driver": "/tmp/driver"
},
"metadata": {
"path": "fake,type=simple,erase=0,metadata",
"offset": 0
},
"cr51": null
}
)"_json;
testfile << valid.dump();
testfile.flush();
EXPECT_THROW(createConfig(missingPrimaryMuxFilename, 0),
std::runtime_error);
}
TEST_F(ConfigTest, ValidConfigWithMissingCR51Property)
{
std::ofstream testfile;
std::string missingCr51Filename = CaseTmpDir() + "/missing_cr51.json";
testfile.open(missingCr51Filename, std::ios::out);
auto valid = R"(
{
"flash": {
"validation_key": ["prod.pem", "dev.pem"],
"primary": {
"location": "mtd,primary",
"mux_select": null
},
"secondary": [
{
"location": "mtd,secondary0",
"mux_select": null
}
],
"device_id": "device_id",
"driver": "/tmp/driver"
},
"metadata": {
"path": "fake,type=simple,erase=0,metadata",
"offset": 0
},
"cr51": {
"prod_to_dev": false,
"image_family": 3
}
}
)"_json;
testfile << valid.dump();
testfile.flush();
EXPECT_THROW(createConfig(missingCr51Filename, 0), std::runtime_error);
}
TEST_F(ConfigTest, ValidConfig)
{
std::ofstream testfile;
std::string validFilename = CaseTmpDir() + "/valid.json";
// Example, validFilename should be /tmp/valid.json
// name = "valid"
// configPath = CaseTmpDir()
std::string configPath = CaseTmpDir() + "/";
size_t index = configPath.size(); // /tmp/
std::string name =
validFilename.substr(index, validFilename.size() - index - /*.json*/ 5);
testfile.open(validFilename, std::ios::out);
auto valid = R"(
{
"flash": {
"validation_key": ["prod.pem", "dev.pem"],
"primary": {
"location": "mtd,primary",
"mux_select": 1
},
"secondary": [
{
"location": "mtd,secondary0",
"mux_select": null
},
{
"location": "mtd,secondary1",
"mux_select": 2
}
],
"device_id": "device_id",
"driver": "/tmp/driver"
},
"metadata": {
"path": "fake,type=simple,erase=0,metadata",
"offset": 128
},
"cr51": {
"prod_to_dev": false,
"production_mode": true,
"unsigned_to_dev": true,
"image_family": 3
},
"supported_version": [{
"min": {
"major": 10,
"minor": 10,
"point": 10,
"subpoint": 10
}
},
{
"max": {
"major": 10,
"minor": 10,
"point": 10,
"subpoint": 10
}
}]
}
)"_json;
testfile << valid.dump();
testfile.flush();
std::vector<std::string> expectedKey = {"prod.pem", "dev.pem"};
// Test auto config finding with wrong path
EXPECT_THROW(createConfig(name, 0, "/bad/"), std::runtime_error);
// Test Invalid secondary index
// secondary index > count(secondaries)
EXPECT_THROW(createConfig(validFilename, 3), std::runtime_error);
// Test Validate Json Config
auto config = createConfig(validFilename, 1);
// Test auto config finding
auto config1 = createConfig(name, 1, configPath);
EXPECT_EQ(config, config1);
// BIOS
EXPECT_EQ(config.flash.deviceId, "device_id");
EXPECT_EQ(config.flash.driver, "/tmp/driver");
EXPECT_EQ(config.flash.stagingIndex, 1);
// BIOS Public Key
EXPECT_TRUE(config.flash.validationKey == expectedKey);
// BIOS Primary
EXPECT_EQ(config.flash.primary.location, "mtd,primary");
EXPECT_EQ(config.flash.primary.muxSelect, 1);
// BIOS Secondary
ASSERT_EQ(config.flash.secondary.size(), 2);
EXPECT_EQ(config.flash.secondary[0].location, "mtd,secondary0");
EXPECT_EQ(config.flash.secondary[0].muxSelect, std::nullopt);
EXPECT_EQ(config.flash.secondary[1].location, "mtd,secondary1");
EXPECT_EQ(config.flash.secondary[1].muxSelect, 2);
// METADATA
EXPECT_EQ(config.metadata.offset, 128);
EXPECT_EQ(config.metadata.path, "fake,type=simple,erase=0,metadata");
// CR51 Config
EXPECT_EQ(config.cr51->imageFamily, 3);
EXPECT_FALSE(config.cr51->prodToDev);
EXPECT_TRUE(config.cr51->productionMode);
EXPECT_TRUE(config.cr51->unsignedToDev);
// CR51 Config
std::string versionStr = "10.10.10.10";
auto version = version::Version(versionStr);
ASSERT_NE(config.supportedVersion, std::nullopt);
ASSERT_EQ(config.supportedVersion->size(), 2);
EXPECT_EQ((*config.supportedVersion)[0].min, version);
EXPECT_EQ((*config.supportedVersion)[0].max, std::nullopt);
EXPECT_EQ((*config.supportedVersion)[1].min, std::nullopt);
EXPECT_EQ((*config.supportedVersion)[1].max, version);
}
} // namespace flashupdate