1 //
2 // Copyright (C) 2011 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 
17 #include "update_engine/omaha_request_params.h"
18 
19 #include <stdio.h>
20 
21 #include <string>
22 
23 #include <base/files/file_util.h>
24 #include <base/files/scoped_temp_dir.h>
25 #include <gtest/gtest.h>
26 
27 #include "update_engine/common/constants.h"
28 #include "update_engine/common/fake_prefs.h"
29 #include "update_engine/common/platform_constants.h"
30 #include "update_engine/common/test_utils.h"
31 #include "update_engine/common/utils.h"
32 #include "update_engine/fake_system_state.h"
33 
34 using chromeos_update_engine::test_utils::WriteFileString;
35 using std::string;
36 
37 namespace chromeos_update_engine {
38 
39 class OmahaRequestParamsTest : public ::testing::Test {
40  public:
OmahaRequestParamsTest()41   OmahaRequestParamsTest() : params_(&fake_system_state_) {}
42 
43  protected:
SetUp()44   void SetUp() override {
45     // Create a uniquely named test directory.
46     ASSERT_TRUE(tempdir_.CreateUniqueTempDir());
47     // Create a fresh copy of the params for each test, so there's no
48     // unintended reuse of state across tests.
49     params_ = OmahaRequestParams(&fake_system_state_);
50     params_.set_root(tempdir_.GetPath().value());
51     SetLockDown(false);
52     fake_system_state_.set_prefs(&fake_prefs_);
53   }
54 
SetLockDown(bool locked_down)55   void SetLockDown(bool locked_down) {
56     fake_system_state_.fake_hardware()->SetIsOfficialBuild(locked_down);
57     fake_system_state_.fake_hardware()->SetIsNormalBootMode(locked_down);
58   }
59 
60   OmahaRequestParams params_;
61   FakeSystemState fake_system_state_;
62   FakePrefs fake_prefs_;
63 
64   base::ScopedTempDir tempdir_;
65 };
66 
67 namespace {
GetMachineType()68 string GetMachineType() {
69   string machine_type;
70   if (!utils::ReadPipe("uname -m", &machine_type))
71     return "";
72   // Strip anything from the first newline char.
73   size_t newline_pos = machine_type.find('\n');
74   if (newline_pos != string::npos)
75     machine_type.erase(newline_pos);
76   return machine_type;
77 }
78 }  // namespace
79 
TEST_F(OmahaRequestParamsTest,MissingChannelTest)80 TEST_F(OmahaRequestParamsTest, MissingChannelTest) {
81   EXPECT_TRUE(params_.Init("", "", false));
82   // By default, if no channel is set, we should track the stable-channel.
83   EXPECT_EQ("stable-channel", params_.target_channel());
84 }
85 
TEST_F(OmahaRequestParamsTest,ForceVersionTest)86 TEST_F(OmahaRequestParamsTest, ForceVersionTest) {
87   EXPECT_TRUE(params_.Init("ForcedVersion", "", false));
88   EXPECT_EQ(string("ForcedVersion_") + GetMachineType(), params_.os_sp());
89   EXPECT_EQ("ForcedVersion", params_.app_version());
90 }
91 
TEST_F(OmahaRequestParamsTest,ForcedURLTest)92 TEST_F(OmahaRequestParamsTest, ForcedURLTest) {
93   EXPECT_TRUE(params_.Init("", "http://forced.google.com", false));
94   EXPECT_EQ("http://forced.google.com", params_.update_url());
95 }
96 
TEST_F(OmahaRequestParamsTest,MissingURLTest)97 TEST_F(OmahaRequestParamsTest, MissingURLTest) {
98   EXPECT_TRUE(params_.Init("", "", false));
99   EXPECT_EQ(constants::kOmahaDefaultProductionURL, params_.update_url());
100 }
101 
TEST_F(OmahaRequestParamsTest,DeltaOKTest)102 TEST_F(OmahaRequestParamsTest, DeltaOKTest) {
103   EXPECT_TRUE(params_.Init("", "", false));
104   EXPECT_TRUE(params_.delta_okay());
105 }
106 
TEST_F(OmahaRequestParamsTest,NoDeltasTest)107 TEST_F(OmahaRequestParamsTest, NoDeltasTest) {
108   ASSERT_TRUE(
109       WriteFileString(tempdir_.GetPath().Append(".nodelta").value(), ""));
110   EXPECT_TRUE(params_.Init("", "", false));
111   EXPECT_FALSE(params_.delta_okay());
112 }
113 
TEST_F(OmahaRequestParamsTest,SetTargetChannelTest)114 TEST_F(OmahaRequestParamsTest, SetTargetChannelTest) {
115   {
116     OmahaRequestParams params(&fake_system_state_);
117     params.set_root(tempdir_.GetPath().value());
118     EXPECT_TRUE(params.Init("", "", false));
119     EXPECT_TRUE(params.SetTargetChannel("canary-channel", false, nullptr));
120     EXPECT_FALSE(params.mutable_image_props_.is_powerwash_allowed);
121   }
122   params_.set_root(tempdir_.GetPath().value());
123   EXPECT_TRUE(params_.Init("", "", false));
124   EXPECT_EQ("canary-channel", params_.target_channel());
125   EXPECT_FALSE(params_.mutable_image_props_.is_powerwash_allowed);
126 }
127 
TEST_F(OmahaRequestParamsTest,SetIsPowerwashAllowedTest)128 TEST_F(OmahaRequestParamsTest, SetIsPowerwashAllowedTest) {
129   {
130     OmahaRequestParams params(&fake_system_state_);
131     params.set_root(tempdir_.GetPath().value());
132     EXPECT_TRUE(params.Init("", "", false));
133     EXPECT_TRUE(params.SetTargetChannel("canary-channel", true, nullptr));
134     EXPECT_TRUE(params.mutable_image_props_.is_powerwash_allowed);
135   }
136   params_.set_root(tempdir_.GetPath().value());
137   EXPECT_TRUE(params_.Init("", "", false));
138   EXPECT_EQ("canary-channel", params_.target_channel());
139   EXPECT_TRUE(params_.mutable_image_props_.is_powerwash_allowed);
140 }
141 
TEST_F(OmahaRequestParamsTest,SetTargetChannelInvalidTest)142 TEST_F(OmahaRequestParamsTest, SetTargetChannelInvalidTest) {
143   {
144     OmahaRequestParams params(&fake_system_state_);
145     params.set_root(tempdir_.GetPath().value());
146     SetLockDown(true);
147     EXPECT_TRUE(params.Init("", "", false));
148     params.image_props_.allow_arbitrary_channels = false;
149     string error_message;
150     EXPECT_FALSE(
151         params.SetTargetChannel("dogfood-channel", true, &error_message));
152     // The error message should include a message about the valid channels.
153     EXPECT_NE(string::npos, error_message.find("stable-channel"));
154     EXPECT_FALSE(params.mutable_image_props_.is_powerwash_allowed);
155   }
156   params_.set_root(tempdir_.GetPath().value());
157   EXPECT_TRUE(params_.Init("", "", false));
158   EXPECT_EQ("stable-channel", params_.target_channel());
159   EXPECT_FALSE(params_.mutable_image_props_.is_powerwash_allowed);
160 }
161 
TEST_F(OmahaRequestParamsTest,IsValidChannelTest)162 TEST_F(OmahaRequestParamsTest, IsValidChannelTest) {
163   EXPECT_TRUE(params_.IsValidChannel("canary-channel"));
164   EXPECT_TRUE(params_.IsValidChannel("stable-channel"));
165   EXPECT_TRUE(params_.IsValidChannel("beta-channel"));
166   EXPECT_TRUE(params_.IsValidChannel("dev-channel"));
167   EXPECT_FALSE(params_.IsValidChannel("testimage-channel"));
168   EXPECT_FALSE(params_.IsValidChannel("dogfood-channel"));
169   EXPECT_FALSE(params_.IsValidChannel("some-channel"));
170   EXPECT_FALSE(params_.IsValidChannel(""));
171   params_.image_props_.allow_arbitrary_channels = true;
172   EXPECT_TRUE(params_.IsValidChannel("some-channel"));
173   EXPECT_FALSE(params_.IsValidChannel("wrong-suffix"));
174   EXPECT_FALSE(params_.IsValidChannel(""));
175 }
176 
TEST_F(OmahaRequestParamsTest,SetTargetChannelWorks)177 TEST_F(OmahaRequestParamsTest, SetTargetChannelWorks) {
178   params_.set_target_channel("dev-channel");
179   EXPECT_EQ("dev-channel", params_.target_channel());
180 
181   // When an invalid value is set, it should be ignored.
182   EXPECT_FALSE(params_.SetTargetChannel("invalid-channel", false, nullptr));
183   EXPECT_EQ("dev-channel", params_.target_channel());
184 
185   // When set to a valid value, it should take effect.
186   EXPECT_TRUE(params_.SetTargetChannel("beta-channel", true, nullptr));
187   EXPECT_EQ("beta-channel", params_.target_channel());
188 
189   // When set to the same value, it should be idempotent.
190   EXPECT_TRUE(params_.SetTargetChannel("beta-channel", true, nullptr));
191   EXPECT_EQ("beta-channel", params_.target_channel());
192 
193   // When set to a valid value while a change is already pending, it should
194   // succeed.
195   EXPECT_TRUE(params_.SetTargetChannel("stable-channel", true, nullptr));
196   EXPECT_EQ("stable-channel", params_.target_channel());
197 
198   // Set a different channel in mutable_image_props_.
199   params_.set_target_channel("stable-channel");
200 
201   // When set to a valid value while a change is already pending, it should
202   // succeed.
203   params_.Init("", "", false);
204   EXPECT_TRUE(params_.SetTargetChannel("beta-channel", true, nullptr));
205   // The target channel should reflect the change, but the download channel
206   // should continue to retain the old value ...
207   EXPECT_EQ("beta-channel", params_.target_channel());
208   EXPECT_EQ("stable-channel", params_.download_channel());
209 
210   // ... until we update the download channel explicitly.
211   params_.UpdateDownloadChannel();
212   EXPECT_EQ("beta-channel", params_.download_channel());
213   EXPECT_EQ("beta-channel", params_.target_channel());
214 }
215 
TEST_F(OmahaRequestParamsTest,ChannelIndexTest)216 TEST_F(OmahaRequestParamsTest, ChannelIndexTest) {
217   int canary = params_.GetChannelIndex("canary-channel");
218   int dev = params_.GetChannelIndex("dev-channel");
219   int beta = params_.GetChannelIndex("beta-channel");
220   int stable = params_.GetChannelIndex("stable-channel");
221   EXPECT_LE(canary, dev);
222   EXPECT_LE(dev, beta);
223   EXPECT_LE(beta, stable);
224 
225   // testimage-channel or other names are not recognized, so index will be -1.
226   int testimage = params_.GetChannelIndex("testimage-channel");
227   int bogus = params_.GetChannelIndex("bogus-channel");
228   EXPECT_EQ(-1, testimage);
229   EXPECT_EQ(-1, bogus);
230 }
231 
TEST_F(OmahaRequestParamsTest,ToMoreStableChannelFlagTest)232 TEST_F(OmahaRequestParamsTest, ToMoreStableChannelFlagTest) {
233   params_.image_props_.current_channel = "canary-channel";
234   params_.download_channel_ = "stable-channel";
235   EXPECT_TRUE(params_.ToMoreStableChannel());
236   params_.image_props_.current_channel = "stable-channel";
237   EXPECT_FALSE(params_.ToMoreStableChannel());
238   params_.download_channel_ = "beta-channel";
239   EXPECT_FALSE(params_.ToMoreStableChannel());
240 }
241 
TEST_F(OmahaRequestParamsTest,ShouldPowerwashTest)242 TEST_F(OmahaRequestParamsTest, ShouldPowerwashTest) {
243   params_.mutable_image_props_.is_powerwash_allowed = false;
244   EXPECT_FALSE(params_.ShouldPowerwash());
245   params_.mutable_image_props_.is_powerwash_allowed = true;
246   params_.image_props_.allow_arbitrary_channels = true;
247   params_.image_props_.current_channel = "foo-channel";
248   params_.download_channel_ = "bar-channel";
249   EXPECT_TRUE(params_.ShouldPowerwash());
250   params_.image_props_.allow_arbitrary_channels = false;
251   params_.image_props_.current_channel = "canary-channel";
252   params_.download_channel_ = "stable-channel";
253   EXPECT_TRUE(params_.ShouldPowerwash());
254 }
255 
TEST_F(OmahaRequestParamsTest,CollectECFWVersionsTest)256 TEST_F(OmahaRequestParamsTest, CollectECFWVersionsTest) {
257   params_.hwid_ = string("STUMPY ALEX 12345");
258   EXPECT_FALSE(params_.CollectECFWVersions());
259 
260   params_.hwid_ = string("SNOW 12345");
261   EXPECT_TRUE(params_.CollectECFWVersions());
262 
263   params_.hwid_ = string("SAMS ALEX 12345");
264   EXPECT_TRUE(params_.CollectECFWVersions());
265 }
266 
267 }  // namespace chromeos_update_engine
268