xref: /aosp_15_r20/external/libchrome/components/policy/core/common/preg_parser_unittest.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "components/policy/core/common/preg_parser.h"
6 
7 #include <utility>
8 
9 #include "base/base_paths.h"
10 #include "base/bind.h"
11 #include "base/files/file_path.h"
12 #include "base/json/json_writer.h"
13 #include "base/logging.h"
14 #include "base/memory/ptr_util.h"
15 #include "base/path_service.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "base/values.h"
18 #include "components/policy/core/common/policy_load_status.h"
19 #include "components/policy/core/common/registry_dict.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 
22 namespace policy {
23 namespace preg_parser {
24 namespace {
25 
26 // Preg files are relative to |kRegistryPolBaseDir|.
27 const char kRegistryPolBaseDir[] = "chrome/test/data/policy/gpo";
28 const char kRegistryPolFile[] = "parser_test/registry.pol";
29 const char kInvalidEncodingRegistryPolFile[] = "invalid_encoding/registry.pol";
30 const char kNonExistingRegistryPolFile[] = "does_not_exist.pol";
31 
32 const char kRegistryKey[] = "SOFTWARE\\Policies\\Chromium";
33 
34 // Check whether two RegistryDicts equal each other.
RegistryDictEquals(const RegistryDict & a,const RegistryDict & b)35 testing::AssertionResult RegistryDictEquals(const RegistryDict& a,
36                                             const RegistryDict& b) {
37   auto iter_key_a = a.keys().begin();
38   auto iter_key_b = b.keys().begin();
39   for (; iter_key_a != a.keys().end() && iter_key_b != b.keys().end();
40        ++iter_key_a, ++iter_key_b) {
41     if (iter_key_a->first != iter_key_b->first) {
42       return testing::AssertionFailure() << "Key mismatch " << iter_key_a->first
43                                          << " vs. " << iter_key_b->first;
44     }
45     testing::AssertionResult result =
46         RegistryDictEquals(*iter_key_a->second, *iter_key_b->second);
47     if (!result)
48       return result;
49   }
50   if (iter_key_a != a.keys().end())
51     return testing::AssertionFailure()
52            << "key mismatch, a has extra key " << iter_key_a->first;
53   if (iter_key_b != b.keys().end())
54     return testing::AssertionFailure()
55            << "key mismatch, b has extra key " << iter_key_b->first;
56 
57   auto iter_value_a = a.values().begin();
58   auto iter_value_b = b.values().begin();
59   for (; iter_value_a != a.values().end() && iter_value_b != b.values().end();
60        ++iter_value_a, ++iter_value_b) {
61     if (iter_value_a->first != iter_value_b->first ||
62         *iter_value_a->second != *iter_value_b->second) {
63       return testing::AssertionFailure()
64              << "Value mismatch " << iter_value_a->first << "="
65              << *iter_value_a->second << " vs. " << iter_value_b->first << "="
66              << *iter_value_b->second;
67     }
68   }
69   if (iter_value_a != a.values().end())
70     return testing::AssertionFailure()
71            << "Value mismatch, a has extra value " << iter_value_a->first << "="
72            << *iter_value_a->second;
73   if (iter_value_b != b.values().end())
74     return testing::AssertionFailure()
75            << "Value mismatch, b has extra value " << iter_value_b->first << "="
76            << *iter_value_b->second;
77 
78   return testing::AssertionSuccess();
79 }
80 
SetInteger(RegistryDict * dict,const std::string & name,int value)81 void SetInteger(RegistryDict* dict, const std::string& name, int value) {
82   dict->SetValue(name, base::WrapUnique<base::Value>(new base::Value(value)));
83 }
84 
SetString(RegistryDict * dict,const std::string & name,const std::string & value)85 void SetString(RegistryDict* dict,
86                const std::string& name,
87                const std::string& value) {
88   dict->SetValue(name, base::WrapUnique<base::Value>(new base::Value(value)));
89 }
90 
91 class PRegParserTest : public testing::Test {
92  protected:
SetUp()93   void SetUp() override {
94     ASSERT_TRUE(base::PathService::Get(base::DIR_SOURCE_ROOT, &test_data_dir_));
95     test_data_dir_ = test_data_dir_.AppendASCII(kRegistryPolBaseDir);
96   }
97 
98   base::FilePath test_data_dir_;
99 };
100 
TEST_F(PRegParserTest,TestParseFile)101 TEST_F(PRegParserTest, TestParseFile) {
102   // Prepare the test dictionary with some data so the test can check that the
103   // PReg action triggers work, i.e. remove these items.
104   RegistryDict dict;
105   SetInteger(&dict, "DeleteValuesTest1", 1);
106   SetString(&dict, "DeleteValuesTest2", "2");
107   dict.SetKey("DeleteKeysTest1", std::make_unique<RegistryDict>());
108   std::unique_ptr<RegistryDict> delete_keys_test(new RegistryDict());
109   SetInteger(delete_keys_test.get(), "DeleteKeysTest2Entry", 1);
110   dict.SetKey("DeleteKeysTest2", std::move(delete_keys_test));
111   SetInteger(&dict, "DelTest", 1);
112   std::unique_ptr<RegistryDict> subdict(new RegistryDict());
113   SetInteger(subdict.get(), "DelValsTest1", 1);
114   SetString(subdict.get(), "DelValsTest2", "2");
115   subdict->SetKey("DelValsTest3", std::make_unique<RegistryDict>());
116   dict.SetKey("DelValsTest", std::move(subdict));
117 
118   // Run the parser.
119   base::FilePath test_file(test_data_dir_.AppendASCII(kRegistryPolFile));
120   PolicyLoadStatusUmaReporter status;
121   ASSERT_TRUE(preg_parser::ReadFile(test_file, base::ASCIIToUTF16(kRegistryKey),
122                                     &dict, &status));
123 
124   // Build the expected output dictionary.
125   RegistryDict expected;
126   std::unique_ptr<RegistryDict> del_vals_dict(new RegistryDict());
127   del_vals_dict->SetKey("DelValsTest3", std::make_unique<RegistryDict>());
128   expected.SetKey("DelValsTest", std::move(del_vals_dict));
129   SetInteger(&expected, "HomepageIsNewTabPage", 1);
130   SetString(&expected, "HomepageLocation", "http://www.example.com");
131   SetInteger(&expected, "RestoreOnStartup", 4);
132   std::unique_ptr<RegistryDict> startup_urls(new RegistryDict());
133   SetString(startup_urls.get(), "1", "http://www.chromium.org");
134   SetString(startup_urls.get(), "2", "http://www.example.com");
135   expected.SetKey("RestoreOnStartupURLs", std::move(startup_urls));
136   SetInteger(&expected, "ShowHomeButton", 1);
137   SetString(&expected, "Snowman", "\xE2\x98\x83");
138   SetString(&expected, "Empty", "");
139 
140   EXPECT_TRUE(RegistryDictEquals(dict, expected));
141 }
142 
TEST_F(PRegParserTest,SubstringRootInvalid)143 TEST_F(PRegParserTest, SubstringRootInvalid) {
144   // A root of "Aa/Bb/Cc" should not be considered a valid root for a
145   // key like "Aa/Bb/C".
146   base::FilePath test_file(test_data_dir_.AppendASCII(kRegistryPolFile));
147   RegistryDict empty;
148   PolicyLoadStatusUmaReporter status;
149 
150   // No data should be loaded for partial roots ("Aa/Bb/C").
151   RegistryDict dict1;
152   ASSERT_TRUE(preg_parser::ReadFile(
153       test_file, base::ASCIIToUTF16("SOFTWARE\\Policies\\Chro"), &dict1,
154       &status));
155   EXPECT_TRUE(RegistryDictEquals(dict1, empty));
156 
157   // Safety check with kRegistryKey (dict should not be empty).
158   RegistryDict dict2;
159   ASSERT_TRUE(preg_parser::ReadFile(test_file, base::ASCIIToUTF16(kRegistryKey),
160                                     &dict2, &status));
161   EXPECT_FALSE(RegistryDictEquals(dict2, empty));
162 }
163 
TEST_F(PRegParserTest,RejectInvalidStrings)164 TEST_F(PRegParserTest, RejectInvalidStrings) {
165   // Tests whether strings with invalid characters are rejected.
166   base::FilePath test_file(
167       test_data_dir_.AppendASCII(kInvalidEncodingRegistryPolFile));
168   PolicyLoadStatusUmaReporter status;
169   RegistryDict dict;
170   ASSERT_TRUE(preg_parser::ReadFile(test_file, base::ASCIIToUTF16(kRegistryKey),
171                                     &dict, &status));
172 
173   RegistryDict empty;
174   EXPECT_TRUE(RegistryDictEquals(dict, empty));
175 }
176 
TEST_F(PRegParserTest,LoadStatusSampling)177 TEST_F(PRegParserTest, LoadStatusSampling) {
178   // Tests load status sampling.
179   PolicyLoadStatusUmaReporter status;
180   RegistryDict dict;
181   base::FilePath test_file(
182       test_data_dir_.AppendASCII(kNonExistingRegistryPolFile));
183   ASSERT_FALSE(preg_parser::ReadFile(
184       test_file, base::ASCIIToUTF16(kRegistryKey), &dict, &status));
185 
186   PolicyLoadStatusSampler::StatusSet expected_status_set;
187   expected_status_set[POLICY_LOAD_STATUS_STARTED] = true;
188   expected_status_set[POLICY_LOAD_STATUS_READ_ERROR] = true;
189   EXPECT_EQ(expected_status_set, status.GetStatusSet());
190 }
191 
192 }  // namespace
193 }  // namespace preg_parser
194 }  // namespace policy
195