1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "components/autofill_assistant/browser/trigger_scripts/trigger_script.h"
6 
7 #include "base/test/gmock_callback_support.h"
8 #include "base/test/mock_callback.h"
9 #include "components/autofill_assistant/browser/service.pb.h"
10 #include "components/autofill_assistant/browser/trigger_scripts/dynamic_trigger_conditions.h"
11 #include "components/autofill_assistant/browser/trigger_scripts/mock_dynamic_trigger_conditions.h"
12 #include "components/autofill_assistant/browser/trigger_scripts/mock_static_trigger_conditions.h"
13 #include "components/autofill_assistant/browser/trigger_scripts/static_trigger_conditions.h"
14 #include "testing/gmock/include/gmock/gmock.h"
15 
16 namespace autofill_assistant {
17 
18 using ::testing::NiceMock;
19 using ::testing::Return;
20 
21 class TriggerScriptTest : public testing::Test {
22  public:
TriggerScriptTest()23   TriggerScriptTest() : trigger_script_(TriggerScriptProto()) {}
24   ~TriggerScriptTest() override = default;
25 
GetProtoForTest()26   TriggerScriptProto* GetProtoForTest() { return &trigger_script_.proto_; }
27 
28  protected:
29   TriggerScript trigger_script_;
30   NiceMock<MockStaticTriggerConditions> mock_static_trigger_conditions_;
31   NiceMock<MockDynamicTriggerConditions> mock_dynamic_trigger_conditions_;
32 };
33 
TEST_F(TriggerScriptTest,NoTriggerConditionSucceeds)34 TEST_F(TriggerScriptTest, NoTriggerConditionSucceeds) {
35   EXPECT_TRUE(trigger_script_.EvaluateTriggerConditions(
36       mock_static_trigger_conditions_, mock_dynamic_trigger_conditions_));
37 }
38 
TEST_F(TriggerScriptTest,EmptyTriggerConditionSucceeds)39 TEST_F(TriggerScriptTest, EmptyTriggerConditionSucceeds) {
40   GetProtoForTest()->mutable_trigger_condition();
41   EXPECT_TRUE(trigger_script_.EvaluateTriggerConditions(
42       mock_static_trigger_conditions_, mock_dynamic_trigger_conditions_));
43 }
44 
TEST_F(TriggerScriptTest,AllOfSucceedsIfEmpty)45 TEST_F(TriggerScriptTest, AllOfSucceedsIfEmpty) {
46   GetProtoForTest()->mutable_trigger_condition()->mutable_all_of();
47   EXPECT_TRUE(trigger_script_.EvaluateTriggerConditions(
48       mock_static_trigger_conditions_, mock_dynamic_trigger_conditions_));
49 }
50 
TEST_F(TriggerScriptTest,AllOfFailsIfOnlySomeConditionsAreTrue)51 TEST_F(TriggerScriptTest, AllOfFailsIfOnlySomeConditionsAreTrue) {
52   auto* all_of =
53       GetProtoForTest()->mutable_trigger_condition()->mutable_all_of();
54   *all_of->add_conditions()->mutable_selector() = ToSelectorProto("a");
55   *all_of->add_conditions()->mutable_selector() = ToSelectorProto("b");
56   *all_of->add_conditions()->mutable_selector() = ToSelectorProto("c");
57 
58   EXPECT_CALL(mock_dynamic_trigger_conditions_,
59               GetSelectorMatches(Selector(ToSelectorProto("a"))))
60       .WillOnce(Return(true));
61   EXPECT_CALL(mock_dynamic_trigger_conditions_,
62               GetSelectorMatches(Selector(ToSelectorProto("b"))))
63       .WillOnce(Return(false));
64   // "b" already fails, "c" does not need to be evaluated.
65   EXPECT_CALL(mock_dynamic_trigger_conditions_,
66               GetSelectorMatches(Selector(ToSelectorProto("c"))))
67       .Times(0);
68 
69   EXPECT_FALSE(trigger_script_.EvaluateTriggerConditions(
70       mock_static_trigger_conditions_, mock_dynamic_trigger_conditions_));
71 }
72 
TEST_F(TriggerScriptTest,AllOfSucceedsIfAllConditionsAreTrue)73 TEST_F(TriggerScriptTest, AllOfSucceedsIfAllConditionsAreTrue) {
74   auto* all_of =
75       GetProtoForTest()->mutable_trigger_condition()->mutable_all_of();
76   *all_of->add_conditions()->mutable_selector() = ToSelectorProto("a");
77   *all_of->add_conditions()->mutable_selector() = ToSelectorProto("b");
78   *all_of->add_conditions()->mutable_selector() = ToSelectorProto("c");
79 
80   EXPECT_CALL(mock_dynamic_trigger_conditions_,
81               GetSelectorMatches(Selector(ToSelectorProto("a"))))
82       .WillOnce(Return(true));
83   EXPECT_CALL(mock_dynamic_trigger_conditions_,
84               GetSelectorMatches(Selector(ToSelectorProto("b"))))
85       .WillOnce(Return(true));
86   EXPECT_CALL(mock_dynamic_trigger_conditions_,
87               GetSelectorMatches(Selector(ToSelectorProto("c"))))
88       .WillOnce(Return(true));
89 
90   EXPECT_TRUE(trigger_script_.EvaluateTriggerConditions(
91       mock_static_trigger_conditions_, mock_dynamic_trigger_conditions_));
92 }
93 
TEST_F(TriggerScriptTest,AnyOfFailsIfEmpty)94 TEST_F(TriggerScriptTest, AnyOfFailsIfEmpty) {
95   GetProtoForTest()->mutable_trigger_condition()->mutable_any_of();
96   EXPECT_FALSE(trigger_script_.EvaluateTriggerConditions(
97       mock_static_trigger_conditions_, mock_dynamic_trigger_conditions_));
98 }
99 
TEST_F(TriggerScriptTest,AnyOfSucceedsIfSomeConditionsAreTrue)100 TEST_F(TriggerScriptTest, AnyOfSucceedsIfSomeConditionsAreTrue) {
101   auto* any_of =
102       GetProtoForTest()->mutable_trigger_condition()->mutable_any_of();
103   *any_of->add_conditions()->mutable_selector() = ToSelectorProto("a");
104   *any_of->add_conditions()->mutable_selector() = ToSelectorProto("b");
105   *any_of->add_conditions()->mutable_selector() = ToSelectorProto("c");
106 
107   EXPECT_CALL(mock_dynamic_trigger_conditions_,
108               GetSelectorMatches(Selector(ToSelectorProto("a"))))
109       .WillOnce(Return(false));
110   EXPECT_CALL(mock_dynamic_trigger_conditions_,
111               GetSelectorMatches(Selector(ToSelectorProto("b"))))
112       .WillOnce(Return(true));
113   // "b" already succeeds, "c" does not need to be evaluated.
114   EXPECT_CALL(mock_dynamic_trigger_conditions_,
115               GetSelectorMatches(Selector(ToSelectorProto("c"))))
116       .Times(0);
117 
118   EXPECT_TRUE(trigger_script_.EvaluateTriggerConditions(
119       mock_static_trigger_conditions_, mock_dynamic_trigger_conditions_));
120 }
121 
TEST_F(TriggerScriptTest,AnyOfFailsIfAllConditionsAreFalse)122 TEST_F(TriggerScriptTest, AnyOfFailsIfAllConditionsAreFalse) {
123   auto* any_of =
124       GetProtoForTest()->mutable_trigger_condition()->mutable_any_of();
125   *any_of->add_conditions()->mutable_selector() = ToSelectorProto("a");
126   *any_of->add_conditions()->mutable_selector() = ToSelectorProto("b");
127   *any_of->add_conditions()->mutable_selector() = ToSelectorProto("c");
128 
129   EXPECT_CALL(mock_dynamic_trigger_conditions_,
130               GetSelectorMatches(Selector(ToSelectorProto("a"))))
131       .WillOnce(Return(false));
132   EXPECT_CALL(mock_dynamic_trigger_conditions_,
133               GetSelectorMatches(Selector(ToSelectorProto("b"))))
134       .WillOnce(Return(false));
135   EXPECT_CALL(mock_dynamic_trigger_conditions_,
136               GetSelectorMatches(Selector(ToSelectorProto("c"))))
137       .WillOnce(Return(false));
138 
139   EXPECT_FALSE(trigger_script_.EvaluateTriggerConditions(
140       mock_static_trigger_conditions_, mock_dynamic_trigger_conditions_));
141 }
142 
TEST_F(TriggerScriptTest,NoneOfSucceedsIfEmpty)143 TEST_F(TriggerScriptTest, NoneOfSucceedsIfEmpty) {
144   GetProtoForTest()->mutable_trigger_condition()->mutable_none_of();
145   EXPECT_TRUE(trigger_script_.EvaluateTriggerConditions(
146       mock_static_trigger_conditions_, mock_dynamic_trigger_conditions_));
147 }
148 
TEST_F(TriggerScriptTest,NoneOfFailsIfSomeConditionsAreTrue)149 TEST_F(TriggerScriptTest, NoneOfFailsIfSomeConditionsAreTrue) {
150   auto* none_of =
151       GetProtoForTest()->mutable_trigger_condition()->mutable_none_of();
152   *none_of->add_conditions()->mutable_selector() = ToSelectorProto("a");
153   *none_of->add_conditions()->mutable_selector() = ToSelectorProto("b");
154   *none_of->add_conditions()->mutable_selector() = ToSelectorProto("c");
155 
156   EXPECT_CALL(mock_dynamic_trigger_conditions_,
157               GetSelectorMatches(Selector(ToSelectorProto("a"))))
158       .WillOnce(Return(false));
159   EXPECT_CALL(mock_dynamic_trigger_conditions_,
160               GetSelectorMatches(Selector(ToSelectorProto("b"))))
161       .WillOnce(Return(true));
162   // "b" already succeeds, "c" does not need to be evaluated.
163   EXPECT_CALL(mock_dynamic_trigger_conditions_,
164               GetSelectorMatches(Selector(ToSelectorProto("c"))))
165       .Times(0);
166 
167   EXPECT_FALSE(trigger_script_.EvaluateTriggerConditions(
168       mock_static_trigger_conditions_, mock_dynamic_trigger_conditions_));
169 }
170 
TEST_F(TriggerScriptTest,NoneOfSucceedsIfAllConditionsAreFalse)171 TEST_F(TriggerScriptTest, NoneOfSucceedsIfAllConditionsAreFalse) {
172   auto* none_of =
173       GetProtoForTest()->mutable_trigger_condition()->mutable_none_of();
174   *none_of->add_conditions()->mutable_selector() = ToSelectorProto("a");
175   *none_of->add_conditions()->mutable_selector() = ToSelectorProto("b");
176   *none_of->add_conditions()->mutable_selector() = ToSelectorProto("c");
177 
178   EXPECT_CALL(mock_dynamic_trigger_conditions_,
179               GetSelectorMatches(Selector(ToSelectorProto("a"))))
180       .WillOnce(Return(false));
181   EXPECT_CALL(mock_dynamic_trigger_conditions_,
182               GetSelectorMatches(Selector(ToSelectorProto("b"))))
183       .WillOnce(Return(false));
184   EXPECT_CALL(mock_dynamic_trigger_conditions_,
185               GetSelectorMatches(Selector(ToSelectorProto("c"))))
186       .WillOnce(Return(false));
187 
188   EXPECT_TRUE(trigger_script_.EvaluateTriggerConditions(
189       mock_static_trigger_conditions_, mock_dynamic_trigger_conditions_));
190 }
191 
TEST_F(TriggerScriptTest,ComplexConditions)192 TEST_F(TriggerScriptTest, ComplexConditions) {
193   // Tests the condition a && (b || !(c)).
194   auto* all_of =
195       GetProtoForTest()->mutable_trigger_condition()->mutable_all_of();
196   *all_of->add_conditions()->mutable_selector() = ToSelectorProto("a");
197   auto* any_of = all_of->add_conditions()->mutable_any_of();
198   *any_of->add_conditions()->mutable_selector() = ToSelectorProto("b");
199   auto* none_of = any_of->add_conditions()->mutable_none_of();
200   *none_of->add_conditions()->mutable_selector() = ToSelectorProto("c");
201 
202   // a == false, b == *, c == * -> false
203   EXPECT_CALL(mock_dynamic_trigger_conditions_,
204               GetSelectorMatches(Selector(ToSelectorProto("a"))))
205       .WillOnce(Return(false));
206   EXPECT_CALL(mock_dynamic_trigger_conditions_,
207               GetSelectorMatches(Selector(ToSelectorProto("b"))))
208       .Times(0);
209   EXPECT_CALL(mock_dynamic_trigger_conditions_,
210               GetSelectorMatches(Selector(ToSelectorProto("c"))))
211       .Times(0);
212   EXPECT_FALSE(trigger_script_.EvaluateTriggerConditions(
213       mock_static_trigger_conditions_, mock_dynamic_trigger_conditions_));
214 
215   // a == true, b == true, c == * -> true
216   EXPECT_CALL(mock_dynamic_trigger_conditions_,
217               GetSelectorMatches(Selector(ToSelectorProto("a"))))
218       .WillOnce(Return(true));
219   EXPECT_CALL(mock_dynamic_trigger_conditions_,
220               GetSelectorMatches(Selector(ToSelectorProto("b"))))
221       .WillOnce(Return(true));
222   EXPECT_CALL(mock_dynamic_trigger_conditions_,
223               GetSelectorMatches(Selector(ToSelectorProto("c"))))
224       .Times(0);
225   EXPECT_TRUE(trigger_script_.EvaluateTriggerConditions(
226       mock_static_trigger_conditions_, mock_dynamic_trigger_conditions_));
227 
228   // a == true, b == false, c == true -> false
229   EXPECT_CALL(mock_dynamic_trigger_conditions_,
230               GetSelectorMatches(Selector(ToSelectorProto("a"))))
231       .WillOnce(Return(true));
232   EXPECT_CALL(mock_dynamic_trigger_conditions_,
233               GetSelectorMatches(Selector(ToSelectorProto("b"))))
234       .WillOnce(Return(false));
235   EXPECT_CALL(mock_dynamic_trigger_conditions_,
236               GetSelectorMatches(Selector(ToSelectorProto("c"))))
237       .WillOnce(Return(true));
238   EXPECT_FALSE(trigger_script_.EvaluateTriggerConditions(
239       mock_static_trigger_conditions_, mock_dynamic_trigger_conditions_));
240 
241   // a == true, b == false, c == false -> true
242   EXPECT_CALL(mock_dynamic_trigger_conditions_,
243               GetSelectorMatches(Selector(ToSelectorProto("a"))))
244       .WillOnce(Return(true));
245   EXPECT_CALL(mock_dynamic_trigger_conditions_,
246               GetSelectorMatches(Selector(ToSelectorProto("b"))))
247       .WillOnce(Return(false));
248   EXPECT_CALL(mock_dynamic_trigger_conditions_,
249               GetSelectorMatches(Selector(ToSelectorProto("c"))))
250       .WillOnce(Return(false));
251   EXPECT_TRUE(trigger_script_.EvaluateTriggerConditions(
252       mock_static_trigger_conditions_, mock_dynamic_trigger_conditions_));
253 }
254 
TEST_F(TriggerScriptTest,StaticTriggerConditions)255 TEST_F(TriggerScriptTest, StaticTriggerConditions) {
256   auto* all_of =
257       GetProtoForTest()->mutable_trigger_condition()->mutable_all_of();
258   all_of->add_conditions()->mutable_stored_login_credentials();
259   all_of->add_conditions()->mutable_is_first_time_user();
260   all_of->add_conditions()->set_experiment_id(12);
261 
262   EXPECT_CALL(mock_static_trigger_conditions_, is_first_time_user)
263       .WillOnce(Return(true));
264   EXPECT_CALL(mock_static_trigger_conditions_, has_stored_login_credentials)
265       .WillOnce(Return(true));
266   EXPECT_CALL(mock_static_trigger_conditions_, is_in_experiment(12))
267       .WillOnce(Return(true));
268   EXPECT_TRUE(trigger_script_.EvaluateTriggerConditions(
269       mock_static_trigger_conditions_, mock_dynamic_trigger_conditions_));
270 }
271 
272 }  // namespace autofill_assistant
273