blob: 8f2e03f20dd07644ce600be8b62663a6b62cd9b0 [file] [log] [blame]
// Copyright 2018 The Fuchsia 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 <sstream>
#include <gtest/gtest.h>
#include "build/tools/json_merge/json_merge.h"
namespace {
class JsonMerge : public ::testing::Test {
protected:
void AddInput(const std::string& filename, const std::string& input) {
inputs.push_back({.name = filename, .contents = std::make_unique<std::istringstream>(input)});
}
int Merge(const MergeConfig& config = {}) { return JSONMerge(inputs, output, errors, config); }
std::string Output() { return output.str(); }
std::string Errors() { return errors.str(); }
void ExpectNoErrors() { EXPECT_TRUE(Errors().empty()); }
void ExpectError(const std::string& expected_error) { EXPECT_EQ(Errors(), expected_error); }
private:
std::vector<input_file> inputs;
std::ostringstream output;
std::ostringstream errors;
};
TEST_F(JsonMerge, MergeOne) {
const std::string input = R"JSON({
"key1": {
"key2": [
"value1",
"value2",
"value3"
],
"key3": "value4"
}
})JSON";
AddInput("file1.json", input);
EXPECT_EQ(Merge(), 0);
EXPECT_EQ(Output(), input);
ExpectNoErrors();
}
TEST_F(JsonMerge, MergeOneAndMinify) {
const std::string input = R"JSON({
"key1": {
"key2": [
"value1",
"value2",
"value3"
],
"key3": "value4"
}
})JSON";
AddInput("file1.json", input);
EXPECT_EQ(Merge({.minify = true}), 0);
const std::string output =
R"JSON({"key1":{"key2":["value1","value2","value3"],"key3":"value4"}})JSON";
EXPECT_EQ(Output(), output);
ExpectNoErrors();
}
TEST_F(JsonMerge, MergeThree) {
const std::string input1 = R"JSON({
"key1": "value1"
})JSON";
AddInput("file1.json", input1);
const std::string input2 = R"JSON({
"key2": "value2"
})JSON";
AddInput("file2.json", input2);
const std::string input3 = R"JSON({
"key3": "value3"
})JSON";
AddInput("file3.json", input3);
EXPECT_EQ(Merge(), 0);
const std::string output = R"JSON({
"key1": "value1",
"key2": "value2",
"key3": "value3"
})JSON";
EXPECT_EQ(Output(), output);
ExpectNoErrors();
}
TEST_F(JsonMerge, MergeConflict) {
const std::string input1 = R"JSON({
"key1": "value1"
})JSON";
AddInput("file1.json", input1);
const std::string input2 = R"JSON({
"key1": "value2"
})JSON";
AddInput("file2.json", input2);
EXPECT_NE(Merge(), 0);
ExpectError("file2.json has a conflicting value for key \"key1\"!\n");
}
TEST_F(JsonMerge, DeepMerge) {
const std::string input1 = R"JSON({"key1": { "subkey1": 1 }})JSON";
AddInput("file1.json", input1);
const std::string input2 = R"JSON({"key1": { "subkey2": 2 }})JSON";
AddInput("file2.json", input2);
EXPECT_EQ(Merge({.deep_merge = true, .minify = true}), 0);
EXPECT_EQ(Output(), R"JSON({"key1":{"subkey1":1,"subkey2":2}})JSON");
ExpectNoErrors();
}
TEST_F(JsonMerge, DefaultNoTrailingComma) {
const std::string input1 = R"JSON({"key1":"value",})JSON";
AddInput("file1.json", input1);
// Should fail to parse the input with a trailing comma.
EXPECT_NE(Merge(), 0);
}
TEST_F(JsonMerge, DefaultNoComments) {
const std::string input1 = R"JSON({"key1":"value" /*comment*/})JSON";
AddInput("file1.json", input1);
// Should fail to parse the input with a comment.
EXPECT_NE(Merge(), 0);
}
TEST_F(JsonMerge, Relaxed) {
const std::string input1 = R"JSON({
"key1":"value",
"key2":{/*comment*/}, // <-traling comma
})JSON";
AddInput("file1.json", input1);
EXPECT_EQ(Merge({.relaxed_input = true}), 0) << Errors();
EXPECT_EQ(Output(), R"JSON({
"key1": "value",
"key2": {}
})JSON");
ExpectNoErrors();
}
TEST_F(JsonMerge, RelaxedMinify) {
const std::string input1 = R"JSON({"key1":"value",/*comment*/})JSON";
AddInput("file1.json", input1);
EXPECT_EQ(Merge({.relaxed_input = true, .minify = true}), 0);
EXPECT_EQ(Output(), R"JSON({"key1":"value"})JSON");
ExpectNoErrors();
}
} // namespace