• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 
16 #include "abc2program_test_utils.h"
17 #include <algorithm>
18 #include <filesystem>
19 #include <fstream>
20 #include <regex>
21 #include <vector>
22 
23 #include "common/abc_file_utils.h"
24 #include "dump_utils.h"
25 
26 namespace panda::abc2program {
27 
28 std::set<std::string> Abc2ProgramTestUtils::helloworld_expected_program_strings_ = {"",
29                                                                                     ".#*#add",
30                                                                                     ".#*#asyncArrowFunc",
31                                                                                     ".#*#asyncGenerateFunc",
32                                                                                     ".#*#asyncSendableFunction",
33                                                                                     ".#*#foo",
34                                                                                     ".#*#generateFunc",
35                                                                                     ".#*#goo",
36                                                                                     ".#*#hoo",
37                                                                                     ".#*#sendableFunction",
38                                                                                     ".#~@0=#HelloWorld",
39                                                                                     ".#~@1=#Lit",
40                                                                                     ".#~@2=#NestedLiteralArray",
41                                                                                     "HelloWorld",
42                                                                                     "error",
43                                                                                     "hello",
44                                                                                     "inner catch",
45                                                                                     "masg",
46                                                                                     "max",
47                                                                                     "min",
48                                                                                     "msg",
49                                                                                     "null",
50                                                                                     "num",
51                                                                                     "outter catch",
52                                                                                     "print",
53                                                                                     "prototype",
54                                                                                     "str",
55                                                                                     "string",
56                                                                                     "toString",
57                                                                                     "varA",
58                                                                                     "x"};
59 std::vector<std::string> Abc2ProgramTestUtils::helloworld_expected_record_names_ = {
60     "_ESExpectedPropertyCountAnnotation",
61     "_ESModuleRecord",
62     "_ESSlotNumberAnnotation",
63     "_ESScopeNamesRecord",
64     "_GLOBAL"
65 };
66 std::vector<std::string> Abc2ProgramTestUtils::helloworld_expected_literal_array_keys_ = {
67     "_ESModuleRecord",
68     "_ESScopeNamesRecord",
69     "_GLOBAL",
70     "_GLOBAL",
71     "_GLOBAL",
72     "_GLOBAL",
73     "_GLOBAL"
74 };
75 
76 std::set<size_t> Abc2ProgramTestUtils::helloworld_expected_literals_sizes_ = {2, 6, 8, 10, 21};
77 
78 template <typename T>
ValidateStrings(const T & strings,const T & expected_strings)79 bool Abc2ProgramTestUtils::ValidateStrings(const T &strings, const T &expected_strings)
80 {
81     if (strings.size() != expected_strings.size()) {
82         return false;
83     }
84     for (const std::string &expected_string : expected_strings) {
85         const auto string_iter = std::find(strings.begin(), strings.end(), expected_string);
86         if (string_iter == strings.end()) {
87             return false;
88         }
89     }
90     return true;
91 }
92 
ValidateProgramStrings(const std::set<std::string> & program_strings)93 bool Abc2ProgramTestUtils::ValidateProgramStrings(const std::set<std::string> &program_strings)
94 {
95     return ValidateStrings(program_strings, helloworld_expected_program_strings_);
96 }
97 
ValidateRecordNames(const std::vector<std::string> & record_names)98 bool Abc2ProgramTestUtils::ValidateRecordNames(const std::vector<std::string> &record_names)
99 {
100     return ValidateStrings(record_names, helloworld_expected_record_names_);
101 }
102 
ValidateLiteralArrayKeys(const std::vector<std::string> & literal_array_keys)103 bool Abc2ProgramTestUtils::ValidateLiteralArrayKeys(const std::vector<std::string> &literal_array_keys)
104 {
105     if (literal_array_keys.size() != helloworld_expected_literal_array_keys_.size()) {
106         return false;
107     }
108     for (size_t i = 0; i < literal_array_keys.size(); ++i) {
109         if (literal_array_keys[i].find(helloworld_expected_literal_array_keys_[i]) != 0) {
110             return false;
111         }
112     }
113     return true;
114 }
115 
ValidateLiteralsSizes(const std::set<size_t> & literal_array_sizes)116 bool Abc2ProgramTestUtils::ValidateLiteralsSizes(const std::set<size_t> &literal_array_sizes)
117 {
118     return (literal_array_sizes == helloworld_expected_literals_sizes_);
119 }
120 
ValidateDumpResult(const std::string & result_file_name,const std::string & expected_file_name)121 bool Abc2ProgramTestUtils::ValidateDumpResult(
122     const std::string &result_file_name, const std::string &expected_file_name)
123 {
124     std::ifstream result_file(result_file_name);
125     if (!result_file.is_open()) {
126         return false;
127     }
128     std::ifstream expected_file(expected_file_name);
129     if (!expected_file.is_open()) {
130         return false;
131     }
132     bool is_same = true;
133     std::string result_line;
134     std::string expected_line;
135     // Validate each line of dump results file, including empty lines.
136     while (!result_file.eof() && !expected_file.eof()) {
137         std::getline(result_file, result_line);
138         std::getline(expected_file, expected_line);
139         if (result_line != expected_line && !ValidateLine(result_line, expected_line)) {
140             is_same = false;
141             break;
142         }
143     }
144     bool is_eof = result_file.eof() && expected_file.eof();
145     result_file.close();
146     expected_file.close();
147     return is_same && is_eof;
148 }
149 
ValidateLine(const std::string & result_line,const std::string & expected_line)150 bool Abc2ProgramTestUtils::ValidateLine(const std::string &result_line, const std::string &expected_line)
151 {
152     // Split input strings by white spaces.
153     std::regex white_space("\\s+");
154     std::vector<std::string> result_substrs(
155         std::sregex_token_iterator(result_line.begin(), result_line.end(), white_space, -1),
156         std::sregex_token_iterator());
157     std::vector<std::string> expected_substrs(
158         std::sregex_token_iterator(expected_line.begin(), expected_line.end(), white_space, -1),
159         std::sregex_token_iterator());
160     // Compare all divived sub-strings.
161     if (result_substrs.size() != expected_substrs.size()) {
162         return false;
163     }
164     for (size_t i = 0; i != result_substrs.size(); ++i) {
165         /* It's acceptable if:
166          * 0. the sub-strings are same.
167          * 1. the sub-string is a regular file path, for example, path of the input abc file, which
168          *    could be different on different computers.
169          * 2. the sub-strings are literal array names with offset, offset could be modified when
170          *    abc file version changed.
171          */
172         if (result_substrs[i] != expected_substrs[i] &&
173             !std::filesystem::is_regular_file(std::filesystem::path(result_substrs[i])) &&
174             !ValidateLiteralArrayName(result_substrs[i], expected_substrs[i])) {
175             return false;
176         }
177     }
178     return true;
179 }
180 
ValidateLiteralArrayName(const std::string & result,const std::string & expected)181 bool Abc2ProgramTestUtils::ValidateLiteralArrayName(const std::string &result, const std::string &expected)
182 {
183     // Extract the record name from a literal array name, for example, extract "_GLOBAL" from "_GLOBAL_1466".
184     // The record name of input string 'result' should be same as that of 'expected'.
185     auto res_end_pos = result.rfind(UNDERLINE);
186     auto exp_end_pos = expected.rfind(UNDERLINE);
187     if (res_end_pos == std::string::npos || exp_end_pos == std::string::npos || res_end_pos != exp_end_pos) {
188         return false;
189     }
190     auto res_start_pos = result.rfind(DUMP_CONTENT_COLON, res_end_pos) + 1;
191     auto exp_start_pos = expected.rfind(DUMP_CONTENT_COLON, exp_end_pos) + 1;
192     if (res_start_pos != exp_start_pos) {
193         return false;
194     }
195     auto res_name = result.substr(res_start_pos, res_end_pos - res_start_pos);
196     if (std::find(helloworld_expected_literal_array_keys_.begin(),
197                   helloworld_expected_literal_array_keys_.end(),
198                   res_name) == helloworld_expected_literal_array_keys_.end()) {
199         return false;
200     }
201     auto exp_name = expected.substr(exp_start_pos, exp_end_pos - exp_start_pos);
202     return res_name == exp_name;
203 }
204 
RemoveDumpResultFile(const std::string & file_name)205 void Abc2ProgramTestUtils::RemoveDumpResultFile(const std::string &file_name)
206 {
207     std::filesystem::remove(std::filesystem::path(file_name));
208 }
209 }  // namespace panda::abc2program
210