blob: b7b4ed08899ec30d94aac090c629af5a8694b454 [file] [log] [blame]
// Copyright 2015 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 "soma/soma.h"
#include <memory>
#include <string>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/files/scoped_temp_dir.h>
#include <base/json/json_reader.h>
#include <base/json/json_writer.h>
#include <base/strings/string_util.h>
#include <base/values.h>
#include <gtest/gtest.h>
#include "soma/lib/soma/annotations.h"
#include "soma/lib/soma/container_spec_reader.h"
#include "soma/lib/soma/fake_userdb.h"
#include "soma/proto_bindings/soma.pb.h"
namespace soma {
using soma::parser::ContainerSpecReader;
class SomaTest : public ::testing::Test {
public:
SomaTest() = default;
virtual ~SomaTest() = default;
void SetUp() override {
ASSERT_TRUE(tmpdir_.CreateUniqueTempDir());
}
protected:
static const char kServiceNamespace[];
static const char kServiceName[];
// Creates a ContainerSpecReader that uses a Userdb that has uid and gid
// mappings for every user and group in the given namespace.
std::unique_ptr<ContainerSpecReader> CreateReaderWithWhitelistedNamespace(
const std::string& whitelisted_namespace) {
std::unique_ptr<ContainerSpecReader> reader;
std::unique_ptr<parser::FakeUserdb> fakedb(new parser::FakeUserdb);
fakedb->set_whitelisted_namespace(whitelisted_namespace);
reader.reset(new ContainerSpecReader(std::move(fakedb)));
return std::move(reader);
}
void InjectReader(Soma* soma, std::unique_ptr<ContainerSpecReader> reader) {
soma->InjectReader(std::move(reader));
}
base::ScopedTempDir tmpdir_;
};
const char SomaTest::kServiceNamespace[] = "com.android.embedded.ping-brick";
const char SomaTest::kServiceName[] = "ping-service";
TEST_F(SomaTest, FindSpecFile) {
base::FilePath service_json =
base::FilePath(kServiceNamespace).AddExtension("json");
base::FilePath scratch_json(tmpdir_.path().Append(service_json));
ASSERT_TRUE(base::CopyFile(service_json, scratch_json));
Soma soma(base::FilePath(tmpdir_.path()));
InjectReader(&soma, CreateReaderWithWhitelistedNamespace(kServiceNamespace));
GetContainerSpecRequest request;
GetContainerSpecResponse response;
request.set_service_name(JoinString({kServiceNamespace, kServiceName}, '.'));
EXPECT_EQ(soma.GetContainerSpec(&request, &response), 0);
EXPECT_TRUE(response.has_container_spec());
}
TEST_F(SomaTest, SpecFileNotFound) {
Soma soma(base::FilePath(tmpdir_.path()));
GetContainerSpecRequest request;
GetContainerSpecResponse response;
request.set_service_name(JoinString({kServiceNamespace, kServiceName}, '.'));
EXPECT_EQ(soma.GetContainerSpec(&request, &response), 0);
EXPECT_FALSE(response.has_container_spec());
}
TEST_F(SomaTest, MalformedRequest) {
Soma soma(base::FilePath("."));
GetContainerSpecRequest request;
GetContainerSpecResponse response;
EXPECT_NE(soma.GetContainerSpec(&request, &response), 0);
request.set_service_name(".");
EXPECT_NE(soma.GetContainerSpec(&request, &response), 0);
request.set_service_name("..");
EXPECT_NE(soma.GetContainerSpec(&request, &response), 0);
request.set_service_name("../../etc/passwd");
EXPECT_NE(soma.GetContainerSpec(&request, &response), 0);
request.set_service_name("subdir/thing.json");
EXPECT_NE(soma.GetContainerSpec(&request, &response), 0);
}
TEST_F(SomaTest, GetContainerSpecs) {
base::FilePath service_json =
base::FilePath(kServiceNamespace).AddExtension("json");
base::FilePath scratch_json(tmpdir_.path().Append(service_json));
ASSERT_TRUE(base::CopyFile(service_json, scratch_json));
Soma soma(base::FilePath(tmpdir_.path()));
InjectReader(&soma, CreateReaderWithWhitelistedNamespace(kServiceNamespace));
GetPersistentContainerSpecsRequest request;
GetPersistentContainerSpecsResponse response;
EXPECT_EQ(soma.GetPersistentContainerSpecs(&request, &response), 0);
EXPECT_EQ(response.container_specs_size(), 0);
// Read in the scratch spec and add the "persistent" annotation.
base::JSONReader reader(base::JSONParserOptions::JSON_ALLOW_TRAILING_COMMAS);
std::string json;
ASSERT_TRUE(base::ReadFileToString(scratch_json, &json));
std::unique_ptr<base::Value> root(reader.ReadToValue(json));
base::DictionaryValue* spec_dict = nullptr;
ASSERT_TRUE(!!root);
ASSERT_TRUE(root->GetAsDictionary(&spec_dict));
ASSERT_TRUE(parser::annotations::AddPersistentAnnotationForTest(spec_dict));
// Now write it out to a new file name in the same directory.
base::FilePath json2 = scratch_json.InsertBeforeExtension("-2");
std::string value_string;
ASSERT_TRUE(base::JSONWriter::Write(root.get(), &value_string));
ASSERT_EQ(base::WriteFile(json2, value_string.c_str(), value_string.length()),
value_string.length());
response.Clear();
EXPECT_EQ(soma.GetPersistentContainerSpecs(&request, &response), 0);
ASSERT_EQ(response.container_specs_size(), 1);
EXPECT_EQ(response.container_specs(0).name(), json2.value());
}
} // namespace soma