• 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 "component_test/test_result_recorder.h"
17 
18 #include <chrono>
19 #include <ctime>
20 #include <filesystem>
21 #include <fstream>
22 #include <iomanip>
23 #include <iostream>
24 #include <regex>
25 #include <sstream>
26 #include <string>
27 #include <sys/stat.h>
28 #include <vector>
29 
30 #include "base/json/json_util.h"
31 #include "base/log/log.h"
32 #include "core/common/task_runner_adapter_factory.h"
33 
34 namespace OHOS::Ace::ComponentTest {
35 
36 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
37 const std::string file_sep = "\\";
38 #else
39 const std::string file_sep = "/";
40 #endif
41 
CreateDirectories(const std::string & filePath)42 int CreateDirectories(const std::string& filePath)
43 {
44     int result = 0;
45 #ifdef _WIN32
46     result = mkdir(filePath.data());
47 #else
48     result = mkdir(filePath.data(), S_IRUSR | S_IWUSR | S_IXUSR);
49 #endif
50     return result;
51 }
52 
FileExists(const std::string & path)53 int FileExists(const std::string& path)
54 {
55     std::ofstream outFile(path);
56     if (!outFile.is_open()) {
57         return 1;
58     }
59     return 0;
60 }
61 
SplitString(const std::string & outPath)62 std::vector<std::string> SplitString(const std::string& outPath)
63 {
64     auto p = file_sep + file_sep;
65     std::regex delimiter(p);
66     std::sregex_token_iterator iter(outPath.begin(), outPath.end(), delimiter, -1);
67     std::sregex_token_iterator end;
68     std::vector<std::string> tokens;
69     while (iter != end) {
70         tokens.push_back(*iter++);
71     }
72     return tokens;
73 }
74 
GetCurrentTime()75 std::string GetCurrentTime()
76 {
77     std::chrono::time_point<std::chrono::system_clock, std::chrono::microseconds> tpMicro =
78         std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::system_clock::now());
79     time_t totalMicroSeconds = tpMicro.time_since_epoch().count();
80     return std::to_string(totalMicroSeconds);
81 }
82 
HandleRelativeFolder(std::string & folderPath)83 std::string HandleRelativeFolder(std::string& folderPath)
84 {
85     std::string resultPath;
86     std::string relativePath;
87     std::string currentPath;
88     char tmp[PATH_MAX];
89     if (getcwd(tmp, sizeof(tmp)) == NULL) {
90         LOGE("get current directory failed!");
91     } else {
92         currentPath = std::string(tmp);
93     }
94     auto pos = folderPath.rfind("..");
95     if (pos != std::string::npos) {
96         std::string currentPathAfterSplit;
97         std::vector<std::string> splitInputResult = SplitString(folderPath);
98         int count = 0;
99         for (const auto& i : splitInputResult) {
100             if (i == "..") {
101                 count++;
102             } else {
103                 relativePath += file_sep + i;
104             }
105         }
106         std::vector<std::string> splitCurrentPathResult = SplitString(currentPath);
107         for (std::size_t i = 0; i < splitCurrentPathResult.size() - count; i++) {
108             currentPathAfterSplit += splitCurrentPathResult[i] + file_sep;
109         }
110         resultPath = currentPathAfterSplit + relativePath.substr(1, relativePath.size() - 1);
111     } else {
112         auto beginWithDot = folderPath.find(".") == 0;
113         if (!beginWithDot) {
114             resultPath = currentPath + file_sep + folderPath;
115         } else {
116             auto path = folderPath.substr(1, folderPath.size() - 1);
117             resultPath = currentPath + file_sep + path;
118         }
119     }
120     return resultPath;
121 }
122 
HandleAbsoluteFolder(std::string & folderPath)123 std::string HandleAbsoluteFolder(std::string& folderPath)
124 {
125     std::string disk;
126     std::string resultPath;
127     size_t pos = folderPath.find(file_sep);
128     if (pos != std::string::npos) {
129         disk = folderPath.substr(0, pos);
130     }
131     resultPath = disk;
132     std::vector<std::string> result = SplitString(folderPath);
133     for (std::size_t i = 1; i < result.size(); i++) {
134         resultPath += file_sep + result[i];
135     }
136     return resultPath;
137 }
138 
Initialize(const std::string & out)139 void TestResultRecorder::Initialize(const std::string& out)
140 {
141     testRecord_.result = Result::ERROR;
142     testRecord_.info = "Component test terminated unexpectedly";
143     testRecord_.position = "Unknown";
144     outPath_ = out;
145     if (outPath_ == "") {
146         return;
147     }
148     std::string absolutePath;
149     std::string resultPath;
150     auto isAbsolute = outPath_.find(":") == std::string::npos;
151     if (!isAbsolute) {
152         absolutePath = HandleAbsoluteFolder(outPath_);
153     } else {
154         absolutePath = HandleRelativeFolder(outPath_);
155     }
156     std::string disk;
157     size_t pos = absolutePath.find(file_sep);
158     if (pos != std::string::npos) {
159         disk = absolutePath.substr(0, pos);
160     }
161     resultPath = disk;
162     std::vector<std::string> result = SplitString(absolutePath);
163     for (std::size_t i = 1; i < result.size(); i++) {
164         resultPath += file_sep + result[i];
165         bool isDir = resultPath.find(".json") == std::string::npos;
166         if (isDir) {
167             CreateDirectories(resultPath);
168             if (i == (result.size() - 1)) {
169                 const std::string fileName = GetCurrentTime();
170                 resultPath += file_sep + fileName + ".json";
171             }
172         }
173         if (FileExists(resultPath) != 0) {
174             LOGE("File \"%{public}s\" not exist", resultPath.c_str());
175         }
176     }
177     outPath_ = resultPath;
178 }
179 
WriteJson()180 void TestResultRecorder::WriteJson()
181 {
182     auto jsonNode = JsonUtil::Create(true);
183     auto jsonDetail = JsonUtil::Create(true);
184     for (auto i : testRecord_.assertResults) {
185         auto jSingle = JsonUtil::Create(true);
186         jSingle->Put("position", i.position.c_str());
187         jSingle->Put("result", i.GetTestCaseResultString().c_str());
188         jSingle->Put("message", i.info.c_str());
189         jsonDetail->Put(jSingle);
190     }
191     jsonNode->Put("test_case_name", attr_.GetTestCaseName().c_str());
192     jsonNode->Put("test_case_type", attr_.GetTestCaseTypeString().c_str());
193     jsonNode->Put("test_case_size", attr_.GetTestCaseSizeString().c_str());
194     jsonNode->Put("test_case_level", attr_.GetTestCaseLevelString().c_str());
195     jsonNode->Put("message", testRecord_.info.c_str());
196     jsonNode->Put("result", testRecord_.result);
197     if (testRecord_.result > 0) {
198         jsonNode->Put("error_position", testRecord_.position.c_str());
199     }
200     jsonNode->Put("details", jsonDetail);
201     std::string str = jsonNode->ToString();
202     if (outPath_ != "") {
203         std::fstream file;
204         file.open(outPath_, std::ios::in | std::ios::out | std::ios::trunc);
205         if (file.is_open()) {
206             file << str << std::endl;
207             file.close();
208         } else {
209             LOGE("open file failed");
210         }
211     } else {
212         LOGI("Json Result: %{public}s", str.c_str());
213     }
214 }
215 
Record(const std::string & info,const std::string & position,Result result)216 void TestResultRecorder::Record(const std::string& info, const std::string& position, Result result)
217 {
218     if (result != Result::PASS) {
219         testRecord_.info = info;
220         testRecord_.result = result;
221         testRecord_.position = position;
222     }
223     testRecord_.assertResults.emplace_back(AssertResult { position, result, info });
224     WriteJson();
225 }
226 
Finish()227 void TestResultRecorder::Finish()
228 {
229     if (testRecord_.assertResults.empty()) {
230         testRecord_.result = Result::PASS;
231         testRecord_.info = "";
232         testRecord_.position = "";
233     } else {
234         auto last = testRecord_.assertResults.back();
235         if (last.result == Result::PASS) {
236             testRecord_.info = "";
237             testRecord_.position = "";
238         } else {
239             testRecord_.info = last.info;
240             testRecord_.position = last.position;
241         }
242         testRecord_.result = last.result;
243     }
244     WriteJson();
245 }
246 } // namespace OHOS::Ace::ComponentTest
247