blob: 0e64cf94b5c952b287a6a2981f050f1eed607a47 [file] [log] [blame]
// Copyright 2021 The Chromium 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 <memory>
#include <string>
#include <vector>
#include "base/json/json_parser.h"
#include "base/json/json_string_value_serializer.h"
#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
#include "base/values.h"
#include "chrome/browser/extensions/system_display/system_display_serialization.h"
#include "chromeos/crosapi/mojom/system_display.mojom.h"
#include "extensions/common/api/system_display.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
// Converts |obj| to a JSON string, assuming T::ToValue() is defined.
template <class T>
std::string ObjectToString(const T& obj) {
std::unique_ptr<base::Value> value = obj.ToValue();
std::string json_string;
JSONStringValueSerializer serializer(&json_string);
EXPECT_TRUE(serializer.Serialize(*value));
return json_string;
}
// Converts JSON string to |obj|, assuming static T::FromValue() is defined.
template <class T>
std::unique_ptr<T> StringToObject(const std::string& json_string) {
JSONStringValueDeserializer deserializer(json_string);
int err_code = 0;
std::string err_message;
std::unique_ptr<base::Value> value =
deserializer.Deserialize(&err_code, &err_message);
EXPECT_EQ(base::ValueDeserializer::kErrorCodeNoError, err_code)
<< "Unexpected error: " << err_message;
EXPECT_NE(nullptr, value.get());
std::unique_ptr<T> obj = T::FromValue(*value);
EXPECT_NE(nullptr, obj.get());
return obj;
}
// Returns a valid JSON string by concatenating a list of strings while making
// the following transforms:
// * Remove all prettifying double spaces.
// * Replace all prettifying "'" with "\"",
// * If |include_optional == false| the ignore all lines starting with "??".
// Otherwise just strip "??".
std::string MakeJsonString(const std::vector<std::string>& lines,
bool include_optional) {
std::vector<std::string> used_lines;
for (const std::string& line : lines) {
if (include_optional || line.substr(0, 2) != "??")
used_lines.push_back(line);
}
std::string ret = base::StrCat(used_lines);
base::ReplaceSubstringsAfterOffset(&ret, 0, "??", "");
base::ReplaceSubstringsAfterOffset(&ret, 0, "'", "\"");
base::ReplaceSubstringsAfterOffset(&ret, 0, " ", "");
return ret;
}
} // namespace
namespace extensions {
namespace api {
namespace system_display {
// This test fails if extensions::api::system_display::DisplayMode changes.
// To fix, update |original_json_string|, and fix SerializeDisplayMode() and
// DeserializeDisplayMode().
TEST(SystemDisplaySerialization, DisplayMode) {
std::vector<std::string> test_lines = {
"{",
" 'deviceScaleFactor':3.14159,",
" 'height':487,",
" 'heightInNativePixels':512,",
"??'isInterlaced':true,",
" 'isNative':true,",
" 'isSelected':true,",
" 'refreshRate':59.5,",
" 'width':640,",
" 'widthInNativePixels':671",
"}",
};
for (int iter = 0; iter < 2; ++iter) {
std::string original_json_string =
MakeJsonString(test_lines, /*include_optional=*/iter > 0);
auto original_obj = StringToObject<DisplayMode>(original_json_string);
crosapi::mojom::DisplayModePtr serialized_obj =
SerializeDisplayMode(*original_obj);
DisplayMode copied_obj;
DeserializeDisplayMode(*serialized_obj, &copied_obj);
std::string copied_json_string = ObjectToString(copied_obj);
EXPECT_EQ(original_json_string, copied_json_string);
}
}
// This test fails if extensions::api::system_display::Edid changes. To fix,
// update |original_json_string|, and fix SerializeEdid() and DeserializeEdid().
TEST(SystemDisplaySerialization, Edid) {
std::vector<std::string> test_lines = {
"{",
" 'manufacturerId':'ACME Display 3000',",
" 'productId':'ABC-123-XYZ',",
" 'yearOfManufacture':2038",
"}",
};
std::string original_json_string = MakeJsonString(test_lines, true);
auto original_obj = StringToObject<Edid>(original_json_string);
crosapi::mojom::EdidPtr serialized_obj = SerializeEdid(*original_obj);
Edid copied_obj;
DeserializeEdid(*serialized_obj, &copied_obj);
std::string copied_json_string = ObjectToString(copied_obj);
EXPECT_EQ(original_json_string, copied_json_string);
}
// This test fails if extensions::api::system_display::DisplayUnitInfo changes.
// To fix, update |original_json_string|, and fix SerializeDisplayUnitInfo()
// and DeserializeDisplayUnitInfo().
TEST(SystemDisplaySerialization, DisplayUnitInfo) {
// Prettified lines used to create test cases. This was created by first
// taking the output form running the following:
//
// LOG(ERROR) << ObjectToString(DisplayUnitInfo());
//
// followed by populating lists and adding optional fields, obtained by
// inspecting system_display.idl.
std::vector<std::string> test_lines = {
"{",
" 'availableDisplayZoomFactors':[",
"?? 0.8,",
"?? 1.2,",
"?? 1.0",
" ],",
" 'bounds':{",
" 'height':749,",
" 'left':7,",
" 'top':11,",
" 'width':1024",
" },",
" 'displayZoomFactor':1.0,",
" 'dpiX':90.0,",
" 'dpiY':88.25,",
"??'edid':{",
"?? 'manufacturerId':'ACME Display 3000',",
"?? 'productId':'ABC-123-XYZ',",
"?? 'yearOfManufacture':2038",
"??},",
" 'hasAccelerometerSupport':true,",
" 'hasTouchSupport':true,",
" 'id':'AWESOME-display-ID',",
"??'isAutoRotationAllowed':true,",
" 'isEnabled':true,",
" 'isInternal':true,",
" 'isPrimary':true,",
" 'isUnified':true,",
" 'mirroringDestinationIds':[",
" 'DEST-ID-2',",
" 'DEST-ID-1',",
" 'DEST-ID-3'",
" ],",
" 'mirroringSourceId':'SOURCE-ID-0',",
" 'modes':[",
"?? {",
"?? 'deviceScaleFactor':3.14159,",
"?? 'height':487,",
"?? 'heightInNativePixels':512,",
"?? 'isNative':true,",
"?? 'isSelected':true,",
"?? 'refreshRate':59.5,",
"?? 'width':640,",
"?? 'widthInNativePixels':671",
"?? },",
"?? {",
"?? 'deviceScaleFactor':2.71828,",
"?? 'height':30,",
"?? 'heightInNativePixels':30,",
"?? 'isInterlaced':true,",
"?? 'isNative':false,",
"?? 'isSelected':false,",
"?? 'refreshRate':122.0,",
"?? 'width':50,",
"?? 'widthInNativePixels':50",
"?? }",
" ],",
" 'name':'Display--123456789',",
" 'overscan':{",
" 'bottom':6,",
" 'left':7,",
" 'right':8,",
" 'top':9",
" },",
" 'rotation':90,",
" 'workArea':{",
" 'height':300,",
" 'left':11,",
" 'top':23,",
" 'width':400",
" }",
"}",
};
for (int iter = 0; iter < 2; ++iter) {
std::string original_json_string =
MakeJsonString(test_lines, /*include_optional=*/iter > 0);
auto original_obj = StringToObject<DisplayUnitInfo>(original_json_string);
crosapi::mojom::DisplayUnitInfoPtr serialized_obj =
SerializeDisplayUnitInfo(*original_obj);
DisplayUnitInfo copied_obj;
DeserializeDisplayUnitInfo(*serialized_obj, &copied_obj);
std::string copied_json_string = ObjectToString(copied_obj);
EXPECT_EQ(original_json_string, copied_json_string);
}
}
} // namespace system_display
} // namespace api
} // namespace extensions