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
34using chromeos_update_engine::test_utils::WriteFileString;
35using std::string;
36
37namespace chromeos_update_engine {
38
39class OmahaRequestParamsTest : public ::testing::Test {
40 public:
41  OmahaRequestParamsTest() : params_(&fake_system_state_) {}
42
43 protected:
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_.path().value());
51    SetLockDown(false);
52    fake_system_state_.set_prefs(&fake_prefs_);
53  }
54
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
67namespace {
68string 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
80TEST_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
86TEST_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
92TEST_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
97TEST_F(OmahaRequestParamsTest, MissingURLTest) {
98  EXPECT_TRUE(params_.Init("", "", false));
99  EXPECT_EQ(constants::kOmahaDefaultProductionURL, params_.update_url());
100}
101
102TEST_F(OmahaRequestParamsTest, DeltaOKTest) {
103  EXPECT_TRUE(params_.Init("", "", false));
104  EXPECT_TRUE(params_.delta_okay());
105}
106
107TEST_F(OmahaRequestParamsTest, NoDeltasTest) {
108  ASSERT_TRUE(WriteFileString(tempdir_.path().Append(".nodelta").value(), ""));
109  EXPECT_TRUE(params_.Init("", "", false));
110  EXPECT_FALSE(params_.delta_okay());
111}
112
113TEST_F(OmahaRequestParamsTest, SetTargetChannelTest) {
114  {
115    OmahaRequestParams params(&fake_system_state_);
116    params.set_root(tempdir_.path().value());
117    EXPECT_TRUE(params.Init("", "", false));
118    EXPECT_TRUE(params.SetTargetChannel("canary-channel", false, nullptr));
119    EXPECT_FALSE(params.is_powerwash_allowed());
120  }
121  params_.set_root(tempdir_.path().value());
122  EXPECT_TRUE(params_.Init("", "", false));
123  EXPECT_EQ("canary-channel", params_.target_channel());
124  EXPECT_FALSE(params_.is_powerwash_allowed());
125}
126
127TEST_F(OmahaRequestParamsTest, SetIsPowerwashAllowedTest) {
128  {
129    OmahaRequestParams params(&fake_system_state_);
130    params.set_root(tempdir_.path().value());
131    EXPECT_TRUE(params.Init("", "", false));
132    EXPECT_TRUE(params.SetTargetChannel("canary-channel", true, nullptr));
133    EXPECT_TRUE(params.is_powerwash_allowed());
134  }
135  params_.set_root(tempdir_.path().value());
136  EXPECT_TRUE(params_.Init("", "", false));
137  EXPECT_EQ("canary-channel", params_.target_channel());
138  EXPECT_TRUE(params_.is_powerwash_allowed());
139}
140
141TEST_F(OmahaRequestParamsTest, SetTargetChannelInvalidTest) {
142  {
143    OmahaRequestParams params(&fake_system_state_);
144    params.set_root(tempdir_.path().value());
145    SetLockDown(true);
146    EXPECT_TRUE(params.Init("", "", false));
147    string error_message;
148    EXPECT_FALSE(
149        params.SetTargetChannel("dogfood-channel", true, &error_message));
150    // The error message should include a message about the valid channels.
151    EXPECT_NE(string::npos, error_message.find("stable-channel"));
152    EXPECT_FALSE(params.is_powerwash_allowed());
153  }
154  params_.set_root(tempdir_.path().value());
155  EXPECT_TRUE(params_.Init("", "", false));
156  EXPECT_EQ("stable-channel", params_.target_channel());
157  EXPECT_FALSE(params_.is_powerwash_allowed());
158}
159
160TEST_F(OmahaRequestParamsTest, IsValidChannelTest) {
161  EXPECT_TRUE(params_.IsValidChannel("canary-channel"));
162  EXPECT_TRUE(params_.IsValidChannel("stable-channel"));
163  EXPECT_TRUE(params_.IsValidChannel("beta-channel"));
164  EXPECT_TRUE(params_.IsValidChannel("dev-channel"));
165  EXPECT_FALSE(params_.IsValidChannel("testimage-channel"));
166  EXPECT_FALSE(params_.IsValidChannel("dogfood-channel"));
167  EXPECT_FALSE(params_.IsValidChannel("some-channel"));
168  EXPECT_FALSE(params_.IsValidChannel(""));
169}
170
171TEST_F(OmahaRequestParamsTest, SetTargetChannelWorks) {
172  params_.set_target_channel("dev-channel");
173  EXPECT_EQ("dev-channel", params_.target_channel());
174
175  // When an invalid value is set, it should be ignored.
176  EXPECT_FALSE(params_.SetTargetChannel("invalid-channel", false, nullptr));
177  EXPECT_EQ("dev-channel", params_.target_channel());
178
179  // When set to a valid value, it should take effect.
180  EXPECT_TRUE(params_.SetTargetChannel("beta-channel", true, nullptr));
181  EXPECT_EQ("beta-channel", params_.target_channel());
182
183  // When set to the same value, it should be idempotent.
184  EXPECT_TRUE(params_.SetTargetChannel("beta-channel", true, nullptr));
185  EXPECT_EQ("beta-channel", params_.target_channel());
186
187  // When set to a valid value while a change is already pending, it should
188  // succeed.
189  EXPECT_TRUE(params_.SetTargetChannel("stable-channel", true, nullptr));
190  EXPECT_EQ("stable-channel", params_.target_channel());
191
192  // Set a different channel in mutable_image_props_.
193  params_.set_target_channel("stable-channel");
194
195  // When set to a valid value while a change is already pending, it should
196  // succeed.
197  params_.Init("", "", false);
198  EXPECT_TRUE(params_.SetTargetChannel("beta-channel", true, nullptr));
199  // The target channel should reflect the change, but the download channel
200  // should continue to retain the old value ...
201  EXPECT_EQ("beta-channel", params_.target_channel());
202  EXPECT_EQ("stable-channel", params_.download_channel());
203
204  // ... until we update the download channel explicitly.
205  params_.UpdateDownloadChannel();
206  EXPECT_EQ("beta-channel", params_.download_channel());
207  EXPECT_EQ("beta-channel", params_.target_channel());
208}
209
210TEST_F(OmahaRequestParamsTest, ChannelIndexTest) {
211  int canary = params_.GetChannelIndex("canary-channel");
212  int dev = params_.GetChannelIndex("dev-channel");
213  int beta = params_.GetChannelIndex("beta-channel");
214  int stable = params_.GetChannelIndex("stable-channel");
215  EXPECT_LE(canary, dev);
216  EXPECT_LE(dev, beta);
217  EXPECT_LE(beta, stable);
218
219  // testimage-channel or other names are not recognized, so index will be -1.
220  int testimage = params_.GetChannelIndex("testimage-channel");
221  int bogus = params_.GetChannelIndex("bogus-channel");
222  EXPECT_EQ(-1, testimage);
223  EXPECT_EQ(-1, bogus);
224}
225
226TEST_F(OmahaRequestParamsTest, ToMoreStableChannelFlagTest) {
227  params_.image_props_.current_channel = "canary-channel";
228  params_.download_channel_ = "stable-channel";
229  EXPECT_TRUE(params_.to_more_stable_channel());
230}
231
232TEST_F(OmahaRequestParamsTest, CollectECFWVersionsTest) {
233  params_.hwid_ = string("STUMPY ALEX 12345");
234  EXPECT_FALSE(params_.CollectECFWVersions());
235
236  params_.hwid_ = string("SNOW 12345");
237  EXPECT_TRUE(params_.CollectECFWVersions());
238
239  params_.hwid_ = string("SAMS ALEX 12345");
240  EXPECT_TRUE(params_.CollectECFWVersions());
241}
242
243}  // namespace chromeos_update_engine
244