• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (C) 2022 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 
16 #include <iostream>
17 
18 #include <gtest/gtest.h>
19 
20 #include "host/commands/cvd/selector/arguments_lexer.h"
21 #include "host/commands/cvd/unittests/selector/client_lexer_helper.h"
22 
23 namespace cuttlefish {
24 namespace selector {
25 namespace {
26 
27 const LexerFlagsSpecification empty_known_flags;
28 const LexerFlagsSpecification boolean_known_flags{
29     .known_boolean_flags = {"clean"}};
30 const LexerFlagsSpecification non_boolean_known_flags{
31     .known_value_flags = {"group_name"}};
32 const LexerFlagsSpecification both_known_flags{
33     .known_boolean_flags = {"clean"}, .known_value_flags = {"group_name"}};
34 
35 }  // namespace
36 
TEST_P(EmptyArgsLexTest,SuccessExpectedTest)37 TEST_P(EmptyArgsLexTest, SuccessExpectedTest) {
38   auto lexer_gen_result = ArgumentsLexerBuilder::Build(known_flags_);
39   std::unique_ptr<ArgumentsLexer> lexer =
40       lexer_gen_result.ok() ? std::move(*lexer_gen_result) : nullptr;
41   if (!lexer) {
42     GTEST_SKIP() << "Memory allocation failed but it is not in the test scope.";
43   }
44   auto tokenized_result = lexer->Tokenize(lex_input_);
45 
46   ASSERT_TRUE(tokenized_result.ok()) << tokenized_result.error().Trace();
47   ASSERT_EQ(*tokenized_result, *expected_tokens_);
48 }
49 
50 INSTANTIATE_TEST_SUITE_P(
51     ClientSpecificOptionParser, EmptyArgsLexTest,
52     testing::Values(LexerInputOutput{.known_flags_ = empty_known_flags,
53                                      .lex_input_ = "",
54                                      .expected_tokens_ = Tokens{}},
55                     LexerInputOutput{.known_flags_ = boolean_known_flags,
56                                      .lex_input_ = "",
57                                      .expected_tokens_ = Tokens{}},
58                     LexerInputOutput{.known_flags_ = non_boolean_known_flags,
59                                      .lex_input_ = "",
60                                      .expected_tokens_ = Tokens{}},
61                     LexerInputOutput{.known_flags_ = both_known_flags,
62                                      .lex_input_ = "",
63                                      .expected_tokens_ = Tokens{}}));
64 
TEST_P(NonBooleanArgsTest,SuccessExpectedTest)65 TEST_P(NonBooleanArgsTest, SuccessExpectedTest) {
66   auto lexer_gen_result = ArgumentsLexerBuilder::Build(known_flags_);
67   std::unique_ptr<ArgumentsLexer> lexer =
68       lexer_gen_result.ok() ? std::move(*lexer_gen_result) : nullptr;
69   if (!lexer) {
70     GTEST_SKIP() << "Memory allocation failed but it is not in the test scope.";
71   }
72   auto tokenized_result = lexer->Tokenize(lex_input_);
73 
74   ASSERT_TRUE(tokenized_result.ok()) << tokenized_result.error().Trace();
75   ASSERT_EQ(*tokenized_result, *expected_tokens_);
76 }
77 
78 INSTANTIATE_TEST_SUITE_P(
79     ClientSpecificOptionParser, NonBooleanArgsTest,
80     testing::Values(
81         LexerInputOutput{
82             .known_flags_ = non_boolean_known_flags,
83             .lex_input_ = "cvd --group_name=yumi",
84             .expected_tokens_ = Tokens{ArgToken{ArgType::kPositional, "cvd"},
85                                        ArgToken{ArgType::kKnownFlagAndValue,
86                                                 "--group_name=yumi"}}},
87         LexerInputOutput{
88             .known_flags_ = non_boolean_known_flags,
89             .lex_input_ = "cvd --group_name yumi",
90             .expected_tokens_ = Tokens{ArgToken{ArgType::kPositional, "cvd"},
91                                        ArgToken{ArgType::kKnownValueFlag,
92                                                 "--group_name"},
93                                        ArgToken{ArgType::kPositional, "yumi"}}},
94         LexerInputOutput{.known_flags_ = non_boolean_known_flags,
95                          .lex_input_ = "cvd --group_name yumi start --daemon",
96                          .expected_tokens_ = Tokens{
97                              ArgToken{ArgType::kPositional, "cvd"},
98                              ArgToken{ArgType::kKnownValueFlag, "--group_name"},
99                              ArgToken{ArgType::kPositional, "yumi"},
100                              ArgToken{ArgType::kPositional, "start"},
101                              ArgToken{ArgType::kUnknownFlag, "--daemon"}}}));
102 
TEST_P(BooleanArgsTest,SuccessExpectedTest)103 TEST_P(BooleanArgsTest, SuccessExpectedTest) {
104   auto lexer_gen_result = ArgumentsLexerBuilder::Build(known_flags_);
105   std::unique_ptr<ArgumentsLexer> lexer =
106       lexer_gen_result.ok() ? std::move(*lexer_gen_result) : nullptr;
107   if (!lexer) {
108     GTEST_SKIP() << "Memory allocation failed but it is not in the test scope.";
109   }
110   auto tokenized_result = lexer->Tokenize(lex_input_);
111 
112   ASSERT_TRUE(tokenized_result.ok()) << tokenized_result.error().Trace();
113   ASSERT_EQ(*tokenized_result, *expected_tokens_);
114 }
115 
116 INSTANTIATE_TEST_SUITE_P(
117     ClientSpecificOptionParser, BooleanArgsTest,
118     testing::Values(
119         LexerInputOutput{
120             .known_flags_ = boolean_known_flags,
121             .lex_input_ = "cvd --clean",
122             .expected_tokens_ = Tokens{ArgToken{ArgType::kPositional, "cvd"},
123                                        ArgToken{ArgType::kKnownBoolFlag,
124                                                 "--clean"}}},
125         LexerInputOutput{
126             .known_flags_ = boolean_known_flags,
127             .lex_input_ = "cvd --clean=TrUe",
128             .expected_tokens_ = Tokens{ArgToken{ArgType::kPositional, "cvd"},
129                                        ArgToken{ArgType::kKnownBoolFlag,
130                                                 "--clean"}}},
131         LexerInputOutput{
132             .known_flags_ = boolean_known_flags,
133             .lex_input_ = "cvd --noclean",
134             .expected_tokens_ = Tokens{ArgToken{ArgType::kPositional, "cvd"},
135                                        ArgToken{ArgType::kKnownBoolNoFlag,
136                                                 "--noclean"}}},
137         LexerInputOutput{
138             .known_flags_ = boolean_known_flags,
139             .lex_input_ = "cvd --noclean=redundant",
140             .expected_tokens_ = Tokens{ArgToken{ArgType::kPositional, "cvd"},
141                                        ArgToken{ArgType::kKnownBoolNoFlag,
142                                                 "--noclean"}}},
143         LexerInputOutput{
144             .known_flags_ = boolean_known_flags,
145             .lex_input_ = "cvd --clean=no --norandom=y",
146             .expected_tokens_ = Tokens{
147                 ArgToken{ArgType::kPositional, "cvd"},
148                 ArgToken{ArgType::kKnownBoolNoFlag, "--noclean"},
149                 ArgToken{ArgType::kUnknownFlag, "--norandom=y"}}}));
150 
TEST_P(BothArgsTest,SuccessExpectedTest)151 TEST_P(BothArgsTest, SuccessExpectedTest) {
152   auto lexer_gen_result = ArgumentsLexerBuilder::Build(known_flags_);
153   std::unique_ptr<ArgumentsLexer> lexer =
154       lexer_gen_result.ok() ? std::move(*lexer_gen_result) : nullptr;
155   if (!lexer) {
156     GTEST_SKIP() << "Memory allocation failed but it is not in the test scope.";
157   }
158   auto tokenized_result = lexer->Tokenize(lex_input_);
159 
160   ASSERT_TRUE(tokenized_result.ok()) << tokenized_result.error().Trace();
161   ASSERT_EQ(*tokenized_result, *expected_tokens_);
162 }
163 
164 INSTANTIATE_TEST_SUITE_P(
165     ClientSpecificOptionParser, BothArgsTest,
166     testing::Values(
167         LexerInputOutput{
168             .known_flags_ = both_known_flags,
169             .lex_input_ = "cvd --clean -group_name=yumi",
170             .expected_tokens_ = Tokens{ArgToken{ArgType::kPositional, "cvd"},
171                                        ArgToken{ArgType::kKnownBoolFlag,
172                                                 "--clean"},
173                                        ArgToken{ArgType::kKnownFlagAndValue,
174                                                 "-group_name=yumi"}}},
175         LexerInputOutput{
176             .known_flags_ = both_known_flags,
177             .lex_input_ = "cvd --group_name -noclean",
178             .expected_tokens_ = Tokens{
179                 ArgToken{ArgType::kPositional, "cvd"},
180                 ArgToken{ArgType::kKnownValueFlag, "--group_name"},
181                 ArgToken{ArgType::kKnownBoolNoFlag, "-noclean"}}}));
182 
TEST_P(BooleanBadArgsTest,FailureExpectedTest)183 TEST_P(BooleanBadArgsTest, FailureExpectedTest) {
184   auto lexer_gen_result = ArgumentsLexerBuilder::Build(known_flags_);
185   std::unique_ptr<ArgumentsLexer> lexer =
186       lexer_gen_result.ok() ? std::move(*lexer_gen_result) : nullptr;
187   if (!lexer) {
188     GTEST_SKIP() << "Memory allocation failed but it is not in the test scope.";
189   }
190   auto tokenized_result = lexer->Tokenize(lex_input_);
191 
192   if (!expected_tokens_) {
193     ASSERT_FALSE(tokenized_result.ok())
194         << "Lexing " << lex_input_ << " should have failed.";
195     return;
196   }
197   ASSERT_TRUE(tokenized_result.ok()) << tokenized_result.error().Trace();
198   ASSERT_EQ(*tokenized_result, *expected_tokens_);
199 }
200 
201 INSTANTIATE_TEST_SUITE_P(
202     ClientSpecificOptionParser, BooleanBadArgsTest,
203     testing::Values(
204         LexerInputOutput{
205             .known_flags_ = boolean_known_flags,
206             .lex_input_ = "cvd --yesclean",
207             .expected_tokens_ = Tokens{ArgToken{ArgType::kPositional, "cvd"},
208                                        ArgToken{ArgType::kUnknownFlag,
209                                                 "--yesclean"}}},
210         LexerInputOutput{.known_flags_ = boolean_known_flags,
211                          .lex_input_ = "cvd --clean=Hello",
212                          .expected_tokens_ = std::nullopt},
213         LexerInputOutput{.known_flags_ = boolean_known_flags,
214                          .lex_input_ = "cvd --clean false",
215                          .expected_tokens_ = Tokens{
216                              ArgToken{ArgType::kPositional, "cvd"},
217                              ArgToken{ArgType::kKnownBoolFlag, "--clean"},
218                              ArgToken{ArgType::kPositional, "false"}}}));
219 
220 }  // namespace selector
221 }  // namespace cuttlefish
222