1 // Copyright 2017 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/feature_engagement/internal/once_condition_validator.h"
6
7 #include <string>
8
9 #include "base/feature_list.h"
10 #include "components/feature_engagement/internal/editable_configuration.h"
11 #include "components/feature_engagement/internal/event_model.h"
12 #include "components/feature_engagement/internal/never_availability_model.h"
13 #include "components/feature_engagement/internal/noop_display_lock_controller.h"
14 #include "components/feature_engagement/internal/proto/feature_event.pb.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 namespace feature_engagement {
18
19 namespace {
20
21 const base::Feature kOnceTestFeatureFoo{"test_foo",
22 base::FEATURE_DISABLED_BY_DEFAULT};
23 const base::Feature kOnceTestFeatureBar{"test_bar",
24 base::FEATURE_DISABLED_BY_DEFAULT};
25
26 FeatureConfig kValidFeatureConfig;
27 FeatureConfig kInvalidFeatureConfig;
28
29 // A EventModel that is easily configurable at runtime.
30 class OnceTestEventModel : public EventModel {
31 public:
OnceTestEventModel()32 OnceTestEventModel() : ready_(false) { kValidFeatureConfig.valid = true; }
33
Initialize(const OnModelInitializationFinished & callback,uint32_t current_day)34 void Initialize(const OnModelInitializationFinished& callback,
35 uint32_t current_day) override {}
36
IsReady() const37 bool IsReady() const override { return ready_; }
38
SetIsReady(bool ready)39 void SetIsReady(bool ready) { ready_ = ready; }
40
GetEvent(const std::string & event_name) const41 const Event* GetEvent(const std::string& event_name) const override {
42 return nullptr;
43 }
44
IncrementEvent(const std::string & event_name,uint32_t day)45 void IncrementEvent(const std::string& event_name, uint32_t day) override {}
46
47 private:
48 bool ready_;
49 };
50
51 class OnceConditionValidatorTest : public ::testing::Test {
52 public:
OnceConditionValidatorTest()53 OnceConditionValidatorTest() {
54 // By default, event model should be ready.
55 event_model_.SetIsReady(true);
56 }
57
58 protected:
59 EditableConfiguration configuration_;
60 OnceTestEventModel event_model_;
61 NeverAvailabilityModel availability_model_;
62 NoopDisplayLockController display_lock_controller_;
63 OnceConditionValidator validator_;
64
65 private:
66 DISALLOW_COPY_AND_ASSIGN(OnceConditionValidatorTest);
67 };
68
69 } // namespace
70
TEST_F(OnceConditionValidatorTest,EnabledFeatureShouldTriggerOnce)71 TEST_F(OnceConditionValidatorTest, EnabledFeatureShouldTriggerOnce) {
72 // Only the first call to MeetsConditions() should lead to enlightenment.
73 EXPECT_TRUE(validator_
74 .MeetsConditions(kOnceTestFeatureFoo, kValidFeatureConfig,
75 event_model_, availability_model_,
76 display_lock_controller_, 0u)
77 .NoErrors());
78 validator_.NotifyIsShowing(kOnceTestFeatureFoo, FeatureConfig(), {""});
79 ConditionValidator::Result result = validator_.MeetsConditions(
80 kOnceTestFeatureFoo, kValidFeatureConfig, event_model_,
81 availability_model_, display_lock_controller_, 0u);
82 EXPECT_FALSE(result.NoErrors());
83 EXPECT_FALSE(result.session_rate_ok);
84 EXPECT_FALSE(result.trigger_ok);
85 }
86
TEST_F(OnceConditionValidatorTest,BothEnabledAndDisabledFeaturesShouldTrigger)87 TEST_F(OnceConditionValidatorTest,
88 BothEnabledAndDisabledFeaturesShouldTrigger) {
89 // Only the kOnceTestFeatureFoo feature should lead to enlightenment, since
90 // kOnceTestFeatureBar is disabled. Ordering disabled feature first to ensure
91 // this captures a different behavior than the
92 // OnlyOneFeatureShouldTriggerPerSession test below.
93 EXPECT_TRUE(validator_
94 .MeetsConditions(kOnceTestFeatureBar, kValidFeatureConfig,
95 event_model_, availability_model_,
96 display_lock_controller_, 0u)
97 .NoErrors());
98 EXPECT_TRUE(validator_
99 .MeetsConditions(kOnceTestFeatureFoo, kValidFeatureConfig,
100 event_model_, availability_model_,
101 display_lock_controller_, 0u)
102 .NoErrors());
103 }
104
TEST_F(OnceConditionValidatorTest,StillTriggerWhenAllFeaturesDisabled)105 TEST_F(OnceConditionValidatorTest, StillTriggerWhenAllFeaturesDisabled) {
106 // No features should get to show enlightenment.
107 EXPECT_TRUE(validator_
108 .MeetsConditions(kOnceTestFeatureFoo, kValidFeatureConfig,
109 event_model_, availability_model_,
110 display_lock_controller_, 0u)
111 .NoErrors());
112 EXPECT_TRUE(validator_
113 .MeetsConditions(kOnceTestFeatureBar, kValidFeatureConfig,
114 event_model_, availability_model_,
115 display_lock_controller_, 0u)
116 .NoErrors());
117 }
118
TEST_F(OnceConditionValidatorTest,OnlyTriggerWhenModelIsReady)119 TEST_F(OnceConditionValidatorTest, OnlyTriggerWhenModelIsReady) {
120 event_model_.SetIsReady(false);
121 ConditionValidator::Result result = validator_.MeetsConditions(
122 kOnceTestFeatureFoo, kValidFeatureConfig, event_model_,
123 availability_model_, display_lock_controller_, 0u);
124 EXPECT_FALSE(result.NoErrors());
125 EXPECT_FALSE(result.event_model_ready_ok);
126
127 event_model_.SetIsReady(true);
128 EXPECT_TRUE(validator_
129 .MeetsConditions(kOnceTestFeatureFoo, kValidFeatureConfig,
130 event_model_, availability_model_,
131 display_lock_controller_, 0u)
132 .NoErrors());
133 }
134
TEST_F(OnceConditionValidatorTest,OnlyTriggerIfNothingElseIsShowing)135 TEST_F(OnceConditionValidatorTest, OnlyTriggerIfNothingElseIsShowing) {
136 validator_.NotifyIsShowing(kOnceTestFeatureBar, FeatureConfig(), {""});
137 ConditionValidator::Result result = validator_.MeetsConditions(
138 kOnceTestFeatureFoo, kValidFeatureConfig, event_model_,
139 availability_model_, display_lock_controller_, 0u);
140 EXPECT_FALSE(result.NoErrors());
141 EXPECT_FALSE(result.currently_showing_ok);
142
143 validator_.NotifyDismissed(kOnceTestFeatureBar);
144 EXPECT_TRUE(validator_
145 .MeetsConditions(kOnceTestFeatureFoo, kValidFeatureConfig,
146 event_model_, availability_model_,
147 display_lock_controller_, 0u)
148 .NoErrors());
149 }
150
TEST_F(OnceConditionValidatorTest,DoNotTriggerForInvalidConfig)151 TEST_F(OnceConditionValidatorTest, DoNotTriggerForInvalidConfig) {
152 ConditionValidator::Result result = validator_.MeetsConditions(
153 kOnceTestFeatureFoo, kInvalidFeatureConfig, event_model_,
154 availability_model_, display_lock_controller_, 0u);
155 EXPECT_FALSE(result.NoErrors());
156 EXPECT_FALSE(result.config_ok);
157
158 EXPECT_TRUE(validator_
159 .MeetsConditions(kOnceTestFeatureFoo, kValidFeatureConfig,
160 event_model_, availability_model_,
161 display_lock_controller_, 0u)
162 .NoErrors());
163 }
164
165 } // namespace feature_engagement
166