1 /*
2  * Copyright (C) 2023 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 <cstdarg>
17 #include <gtest/gtest.h>
18 
19 #include "command_lexer.h"
20 
21 #define SPACE_STR               " "
22 #define SINGLE_QUOTE_STR        "'"
23 #define DOUBLE_QUOTE_STR        "\""
24 
25 using namespace testing;
26 using namespace testing::ext;
27 
28 namespace OHOS {
29 namespace AppSpawn {
30 namespace {
31 
32 class CommandLexerTest : public Test {
33 protected:
WrapWith(const char * s,const char * appendage)34     static std::string WrapWith(const char *s, const char *appendage)
35     {
36         std::string wrappedStr;
37         wrappedStr += appendage;
38         wrappedStr += s;
39         wrappedStr += appendage;
40         return wrappedStr;
41     }
42 
Join(const char * separator,...)43     static std::string Join(const char *separator, ...)
44     {
45         bool firstArg = true;
46         va_list args;
47         va_start(args, separator);
48         const char *arg = nullptr;
49         std::string joinedStr;
50 
51         while ((arg = va_arg(args, const char*))) {
52             if (!firstArg) {
53                 joinedStr += separator;
54             } else {
55                 firstArg = false;
56             }
57             joinedStr += arg;
58         }
59 
60         va_end(args);
61         return joinedStr;
62     }
63 
64     std::vector<std::string> args_ {};
65 };
66 
67 HWTEST_F(CommandLexerTest, GetAllArguments, TestSize.Level0)
68 {
69     const char *filePath = "/data/local/tmp/lldb-server";
70     const char *serverMode = "platform";
71     const char *listenOpt = "--listen";
72     const char *connUrl = "unix-abstract:///lldb/platform.sock";
73     std::string command = Join(SPACE_STR,
74         filePath, serverMode, listenOpt, connUrl, nullptr);
75     CommandLexer lexer(command);
76 
77     ASSERT_TRUE(lexer.GetAllArguments(args_));
78     ASSERT_FALSE(args_.empty());
79     ASSERT_EQ(args_.size(), (size_t) 4);
80     ASSERT_EQ(args_[0], filePath);
81     ASSERT_EQ(args_[1], serverMode);
82     ASSERT_EQ(args_[2], listenOpt);
83     ASSERT_EQ(args_[3], connUrl);
84 }
85 
86 HWTEST_F(CommandLexerTest, GetAllArgumentsWithSingleQuote, TestSize.Level0)
87 {
88     const char *fileName = "echo";
89     const char *message = " aaa ";
90     std::string command = Join(SPACE_STR,
91         fileName, WrapWith(message, SINGLE_QUOTE_STR).c_str(), nullptr);
92     CommandLexer lexer(command);
93 
94     ASSERT_TRUE(lexer.GetAllArguments(args_));
95     ASSERT_FALSE(args_.empty());
96     ASSERT_EQ(args_.size(), (size_t) 2);
97     ASSERT_EQ(args_[0], fileName);
98     ASSERT_EQ(args_[1], message);
99 }
100 
101 HWTEST_F(CommandLexerTest, GetAllArgumentsWithDoubleQuote, TestSize.Level0)
102 {
103     const char *filePath = "/data/local/tmp/lldb-server";
104     const char *logOpt = "--log-channel";
105     const char *logChannels = "lldb process thread:gdb-remote packets";
106     std::string command = Join(SPACE_STR,
107         filePath, logOpt, WrapWith(logChannels, DOUBLE_QUOTE_STR).c_str(),
108         nullptr);
109     CommandLexer lexer(command);
110 
111     ASSERT_TRUE(lexer.GetAllArguments(args_));
112     ASSERT_FALSE(args_.empty());
113     ASSERT_EQ(args_.size(), (size_t) 3);
114     ASSERT_EQ(args_[0], filePath);
115     ASSERT_EQ(args_[1], logOpt);
116     ASSERT_EQ(args_[2], logChannels);
117 }
118 
119 HWTEST_F(CommandLexerTest, GetAllArgumentsFromEmptyStr, TestSize.Level0)
120 {
121     std::string command;
122     CommandLexer lexer(command);
123 
124     ASSERT_TRUE(lexer.GetAllArguments(args_));
125     ASSERT_TRUE(args_.empty());
126 }
127 
128 HWTEST_F(CommandLexerTest, GetAllArgumentsFromSpaces, TestSize.Level0)
129 {
130     std::string command = "   ";
131     CommandLexer lexer(command);
132 
133     ASSERT_TRUE(lexer.GetAllArguments(args_));
134     ASSERT_TRUE(args_.empty());
135 }
136 
137 HWTEST_F(CommandLexerTest, GetAllArgumentsWithMissingQuote, TestSize.Level0)
138 {
139     const char *fileName = "echo";
140     const char *message = DOUBLE_QUOTE_STR " aa";
141     std::string command = Join(SPACE_STR, fileName, message, nullptr);
142     CommandLexer lexer(command);
143 
144     ASSERT_FALSE(lexer.GetAllArguments(args_));
145     ASSERT_TRUE(args_.empty());
146 }
147 
148 HWTEST_F(CommandLexerTest, GetAllArgumentsWithNonLeadingQuote, TestSize.Level0)
149 {
150     const char *fileName = "mkdir";
151     const char *opt = "-p";
152     const char *dirName = "lldb-" DOUBLE_QUOTE_STR "server" DOUBLE_QUOTE_STR;
153     std::string command = Join(SPACE_STR, fileName, opt, dirName, nullptr);
154     CommandLexer lexer(command);
155 
156     ASSERT_TRUE(lexer.GetAllArguments(args_));
157     ASSERT_FALSE(args_.empty());
158     ASSERT_EQ(args_.size(), (size_t) 3);
159     ASSERT_EQ(args_[0], fileName);
160     ASSERT_EQ(args_[1], opt);
161     ASSERT_EQ(args_[2], "lldb-server");
162 }
163 
164 } // namespace
165 } // namespace AppSpawn
166 } // namespace OHOS
167