• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include <gmock/gmock.h>
16 #include <gtest/gtest.h>
17 
18 #include <base/containers/unordered_map.h>
19 #include <core/io/intf_file_manager.h>
20 
21 #include <meta/api/make_callback.h>
22 #include <meta/api/object.h>
23 #include <meta/interface/builtin_objects.h>
24 #include <meta/interface/loaders/intf_file_content_loader.h>
25 
26 #include "TestRunner.h"
27 
28 using namespace testing;
29 using namespace testing::ext;
30 
31 META_BEGIN_NAMESPACE()
32 
33 MATCHER_P(HasProperty, name, "")
34 {
35     const META_NS::IObject::Ptr& object = arg;
36     auto meta = interface_cast<META_NS::IMetadata>(object);
37     bool found = false;
38 
39     if (!meta || !object) {
40         *result_listener << "where object type is invalid";
41         return false;
42     }
43 
44     for (auto prop : meta->GetProperties()) {
45         if (prop->GetName() == name) {
46             found = true;
47             break;
48         }
49     }
50 
51     if (!found) {
52         *result_listener << "where object did not have property '" << name.data() << "'";
53     }
54     return found;
55 }
56 
57 constexpr BASE_NS::string_view TRANSLATION_STRING_KEY = "strings";
58 
59 class CsvLoaderTest : public ::testing::Test {
60 protected:
SetUp()61     void SetUp() override
62     {
63         loader_ = META_NS::GetObjectRegistry().Create<IFileContentLoader>(ClassId::CsvStringResourceLoader);
64         ASSERT_NE(loader_, nullptr);
65     }
66 
67     using CsvContentItemType = BASE_NS::pair<BASE_NS::string, BASE_NS::vector<BASE_NS::string>>;
68     using CsvContentType = BASE_NS::vector<CsvContentItemType>;
69 
CheckTranslations(const BASE_NS::string & path,const BASE_NS::vector<BASE_NS::string> & keys,const CsvContentType & content)70     void CheckTranslations(
71         const BASE_NS::string& path, const BASE_NS::vector<BASE_NS::string>& keys, const CsvContentType& content)
72     {
73         loader_->SetFile(CORE_NS::GetPluginRegister().GetFileManager().OpenFile(path));
74         Object object(loader_->Create({}));
75         ASSERT_TRUE(object);
76         ASSERT_NE(object.GetPtr(), nullptr);
77 
78         // Object should have a "strings" property
79         ASSERT_THAT(object, HasProperty(TRANSLATION_STRING_KEY));
80         auto stringsProp = Metadata(object).GetProperty<IObject::Ptr>(TRANSLATION_STRING_KEY);
81         ASSERT_TRUE(stringsProp);
82         Object strings(stringsProp->GetValue());
83         ASSERT_TRUE(strings);
84         EXPECT_EQ(Metadata(strings).GetProperties().size(), content.size());
85 
86         // Go through our expected content and chech that the object has all of the languages and
87         // corresponding strings
88         for (const auto& item : content) {
89             BASE_NS::string_view lang(item.first);
90             ASSERT_THAT(strings, HasProperty(lang));
91 
92             auto translationsProp = Metadata(strings).GetProperty<IObject::Ptr>(lang);
93             ASSERT_TRUE(translationsProp);
94             Object translations(translationsProp->GetValue());
95             ASSERT_TRUE(translations);
96 
97             // Must contain expected amount of translation strings
98             const auto& expectedTranslations = item.second;
99             ASSERT_EQ(Metadata(translations).GetProperties().size(), expectedTranslations.size());
100             ASSERT_EQ(keys.size(), expectedTranslations.size());
101 
102             // Check that each translation found in the object matches our expected translation table
103             for (size_t i = 0; i < expectedTranslations.size(); i++) {
104                 auto prop = Metadata(translations).GetProperty<BASE_NS::string>(keys[i]);
105                 ASSERT_TRUE(prop) << "lang: " << item.first.data() << ", index: " << i;
106                 ASSERT_EQ(prop->GetValue(), expectedTranslations[i])
107                     << "lang: " << item.first.data() << ", index: " << i;
108             }
109         }
110     }
111 
112     IFileContentLoader::Ptr loader_;
113 };
114 
115 /**
116  * @tc.name: Basic
117  * @tc.desc: test Basic
118  * @tc.type: FUNC
119  */
120 HWTEST_F(CsvLoaderTest, Basic, TestSize.Level1)
121 {
122     constexpr auto path = "file:///data/local/test_data/csv/basic.csv";
123     static BASE_NS::vector<BASE_NS::string> keys = { "First string", "Second string", "Click me" };
124     static CsvContentType content = { { "fi", { "Eka merkkijono", "Toka merkkijono", "Klikkaa mua" } },
125         { "en", { "First string", "Second string", "Click me" } },
126         { "zh", { "第一个字符串", "第二个字符串", "点我" } } };
127 
128     CheckTranslations(path, keys, content);
129 }
130 
131 /**
132  * @tc.name: Quotes
133  * @tc.desc: test Quotes
134  * @tc.type: FUNC
135  */
136 HWTEST_F(CsvLoaderTest, Quotes, TestSize.Level1)
137 {
138     constexpr auto path = "file:///data/local/test_data/csv/quotes.csv";
139     // The CSV file contains quoted strings with commas, double quotes and also leading and
140     // trailing whitespace between opening/closing quote and the delimiter. Those should be
141     // handled correctly.
142     static BASE_NS::vector<BASE_NS::string> keys = { "Click,me", "Click,\"12" };
143     static CsvContentType content = { { "fi", { "Klikkaa,mua", "Klikkaa,\"12" } },
144         { "en", { "Click,me", "Click,\"12" } }, { "zh", { "点,我", "点,12" } } };
145 
146     CheckTranslations(path, keys, content);
147 }
148 
149 /**
150  * @tc.name: Multiline
151  * @tc.desc: test Multiline
152  * @tc.type: FUNC
153  */
154 HWTEST_F(CsvLoaderTest, Multiline, TestSize.Level1)
155 {
156     constexpr auto path = "file:///data/local/test_data/csv/multiline.csv";
157     // These strings/keys should match the values in above csv file
158     static BASE_NS::vector<BASE_NS::string> keys = { "First string", "Click me" };
159     static CsvContentType content = { { "fi", { "Eka \nmerkkijono", "Klikkaa mua" } },
160         { "en", { "First \nstring", "Click me" } }, { "zh", { "第一\n个字符串", "点我" } } };
161 
162     CheckTranslations(path, keys, content);
163 }
164 
165 /**
166  * @tc.name: Complex
167  * @tc.desc: test Complex
168  * @tc.type: FUNC
169  */
170 HWTEST_F(CsvLoaderTest, Complex, TestSize.Level1)
171 {
172     constexpr auto path = "file:///data/local/test_data/csv/complex.csv";
173     // These strings/keys should match the values in above csv file
174     static BASE_NS::vector<BASE_NS::string> keys = { "1991", "1992", "1993", "1994" };
175     static CsvContentType content = { { "make", { "Ford", "Chevy", "Chevy", "Jeep" } },
176         { "model",
177             { "E350", "Venture \"Extended Edition\"", "Venture \"Extended Edition, Very Large\"", "Grand Cherokee" } },
178         { "description", { "ac, abs, moon", "", "", "MUST SELL!\nair, moon roof, loaded" } },
179         { "price", { "3000.00", "4900.00", "5000.00", "4799.00" } } };
180 
181     CheckTranslations(path, keys, content);
182 }
183 
184 /**
185  * @tc.name: CsvInvalid
186  * @tc.desc: test CsvInvalid
187  * @tc.type: FUNC
188  */
189 HWTEST_F(CsvLoaderTest, CsvInvalid, TestSize.Level1)
190 {
191     constexpr auto path1 = "file:///data/local/test_data/csv/invalid_content.csv";
192     constexpr auto path2 = "file:///data/local/test_data/csv/invalid_structure.csv";
193     constexpr auto path3 = "file:///data/local/test_data/csv/invalid_header.csv";
194     constexpr auto path4 = "file:///data/local/test_data/csv/invalid_empty.csv";
195     constexpr auto path5 = "file:///data/local/test_data/csv/invalid_file_doesnt_exist.csv";
196     int changed = 0;
197 
__anon0442e47f0102null198     loader_->ContentChanged()->AddHandler(META_NS::MakeCallback<META_NS::IOnChanged>([&changed] { changed++; }));
199 
200     loader_->SetFile(CORE_NS::GetPluginRegister().GetFileManager().OpenFile(path1));
201     EXPECT_EQ(loader_->Create({}), nullptr);
202     loader_->SetFile(CORE_NS::GetPluginRegister().GetFileManager().OpenFile(path2));
203     EXPECT_EQ(loader_->Create({}), nullptr);
204     loader_->SetFile(CORE_NS::GetPluginRegister().GetFileManager().OpenFile(path3));
205     EXPECT_EQ(loader_->Create({}), nullptr);
206     loader_->SetFile(CORE_NS::GetPluginRegister().GetFileManager().OpenFile(path4));
207     EXPECT_EQ(loader_->Create({}), nullptr);
208     loader_->SetFile(CORE_NS::GetPluginRegister().GetFileManager().OpenFile(path5));
209     EXPECT_EQ(loader_->Create({}), nullptr);
210 
211     EXPECT_EQ(changed, 5);
212 }
213 
214 META_END_NAMESPACE()
215