|  | // Copyright (c) 2012 The Chromium OS Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include <string> | 
|  |  | 
|  | #include <base/string_util.h> | 
|  | #include <base/stringprintf.h> | 
|  | #include <gmock/gmock.h> | 
|  | #include <gtest/gtest.h> | 
|  | #include <metrics/metrics_library_mock.h> | 
|  |  | 
|  | #include "update_engine/certificate_checker.h" | 
|  | #include "update_engine/certificate_checker_mock.h" | 
|  | #include "update_engine/constants.h" | 
|  | #include "update_engine/mock_system_state.h" | 
|  | #include "update_engine/prefs_mock.h" | 
|  |  | 
|  | using ::testing::_; | 
|  | using ::testing::DoAll; | 
|  | using ::testing::Return; | 
|  | using ::testing::SetArgumentPointee; | 
|  | using ::testing::SetArrayArgument; | 
|  | using std::string; | 
|  |  | 
|  | namespace chromeos_update_engine { | 
|  |  | 
|  | class CertificateCheckerTest : public testing::Test { | 
|  | public: | 
|  | CertificateCheckerTest() {} | 
|  |  | 
|  | protected: | 
|  | virtual void SetUp() { | 
|  | depth_ = 0; | 
|  | length_ = 4; | 
|  | digest_[0] = 0x17; | 
|  | digest_[1] = 0x7D; | 
|  | digest_[2] = 0x07; | 
|  | digest_[3] = 0x5F; | 
|  | digest_hex_ = "177D075F"; | 
|  | diff_digest_hex_ = "1234ABCD"; | 
|  | cert_key_prefix_ = kPrefsUpdateServerCertificate; | 
|  | server_to_check_ = CertificateChecker::kUpdate; | 
|  | cert_key_ = StringPrintf("%s-%d-%d", | 
|  | cert_key_prefix_.c_str(), | 
|  | server_to_check_, | 
|  | depth_); | 
|  | kCertChanged = "Updater.ServerCertificateChanged"; | 
|  | kCertFailed = "Updater.ServerCertificateFailed"; | 
|  | CertificateChecker::set_system_state(&mock_system_state_); | 
|  | CertificateChecker::set_openssl_wrapper(&openssl_wrapper_); | 
|  | prefs_ = mock_system_state_.mock_prefs(); | 
|  | } | 
|  |  | 
|  | virtual void TearDown() {} | 
|  |  | 
|  | MockSystemState mock_system_state_; | 
|  | PrefsMock* prefs_; // shortcut to mock_system_state_.mock_prefs() | 
|  | OpenSSLWrapperMock openssl_wrapper_; | 
|  | // Parameters of our mock certificate digest. | 
|  | int depth_; | 
|  | unsigned int length_; | 
|  | unsigned char digest_[4]; | 
|  | string digest_hex_; | 
|  | string diff_digest_hex_; | 
|  | string cert_key_prefix_; | 
|  | CertificateChecker::ServerToCheck server_to_check_; | 
|  | string cert_key_; | 
|  | string kCertChanged; | 
|  | string kCertFailed; | 
|  | }; | 
|  |  | 
|  | // check certificate change, new | 
|  | TEST_F(CertificateCheckerTest, NewCertificate) { | 
|  | EXPECT_CALL(openssl_wrapper_, GetCertificateDigest(NULL, _, _, _)) | 
|  | .WillOnce(DoAll( | 
|  | SetArgumentPointee<1>(depth_), | 
|  | SetArgumentPointee<2>(length_), | 
|  | SetArrayArgument<3>(digest_, digest_ + 4), | 
|  | Return(true))); | 
|  | EXPECT_CALL(*prefs_, GetString(cert_key_, _)) | 
|  | .WillOnce(Return(false)); | 
|  | EXPECT_CALL(*prefs_, SetString(cert_key_, digest_hex_)) | 
|  | .WillOnce(Return(true)); | 
|  | ASSERT_TRUE(CertificateChecker::CheckCertificateChange( | 
|  | server_to_check_, 1, NULL)); | 
|  | } | 
|  |  | 
|  | // check certificate change, unchanged | 
|  | TEST_F(CertificateCheckerTest, SameCertificate) { | 
|  | EXPECT_CALL(openssl_wrapper_, GetCertificateDigest(NULL, _, _, _)) | 
|  | .WillOnce(DoAll( | 
|  | SetArgumentPointee<1>(depth_), | 
|  | SetArgumentPointee<2>(length_), | 
|  | SetArrayArgument<3>(digest_, digest_ + 4), | 
|  | Return(true))); | 
|  | EXPECT_CALL(*prefs_, GetString(cert_key_, _)) | 
|  | .WillOnce(DoAll( | 
|  | SetArgumentPointee<1>(digest_hex_), | 
|  | Return(true))); | 
|  | EXPECT_CALL(*prefs_, SetString(_, _)).Times(0); | 
|  | ASSERT_TRUE(CertificateChecker::CheckCertificateChange( | 
|  | server_to_check_, 1, NULL)); | 
|  | } | 
|  |  | 
|  | // check certificate change, changed | 
|  | TEST_F(CertificateCheckerTest, ChangedCertificate) { | 
|  | EXPECT_CALL(openssl_wrapper_, GetCertificateDigest(NULL, _, _, _)) | 
|  | .WillOnce(DoAll( | 
|  | SetArgumentPointee<1>(depth_), | 
|  | SetArgumentPointee<2>(length_), | 
|  | SetArrayArgument<3>(digest_, digest_ + 4), | 
|  | Return(true))); | 
|  | EXPECT_CALL(*prefs_, GetString(cert_key_, _)) | 
|  | .WillOnce(DoAll( | 
|  | SetArgumentPointee<1>(diff_digest_hex_), | 
|  | Return(true))); | 
|  | EXPECT_CALL(*prefs_, SetString(kPrefsCertificateReportToSendUpdate, | 
|  | kCertChanged)) | 
|  | .WillOnce(Return(true)); | 
|  | EXPECT_CALL(*prefs_, SetString(cert_key_, digest_hex_)) | 
|  | .WillOnce(Return(true)); | 
|  | ASSERT_TRUE(CertificateChecker::CheckCertificateChange( | 
|  | server_to_check_, 1, NULL)); | 
|  | } | 
|  |  | 
|  | // check certificate change, failed | 
|  | TEST_F(CertificateCheckerTest, FailedCertificate) { | 
|  | EXPECT_CALL(*prefs_, SetString(kPrefsCertificateReportToSendUpdate, | 
|  | kCertFailed)) | 
|  | .WillOnce(Return(true)); | 
|  | EXPECT_CALL(*prefs_, GetString(_,_)).Times(0); | 
|  | EXPECT_CALL(openssl_wrapper_, GetCertificateDigest(_,_,_,_)).Times(0); | 
|  | ASSERT_FALSE(CertificateChecker::CheckCertificateChange( | 
|  | server_to_check_, 0, NULL)); | 
|  | } | 
|  |  | 
|  | // flush send report | 
|  | TEST_F(CertificateCheckerTest, FlushReport) { | 
|  | EXPECT_CALL(*prefs_, GetString(kPrefsCertificateReportToSendUpdate, _)) | 
|  | .WillOnce(DoAll( | 
|  | SetArgumentPointee<1>(kCertChanged), | 
|  | Return(true))); | 
|  | EXPECT_CALL(*prefs_, GetString(kPrefsCertificateReportToSendDownload, _)) | 
|  | .WillOnce(Return(false)); | 
|  | EXPECT_CALL(*mock_system_state_.mock_metrics_lib(), | 
|  | SendUserActionToUMA(kCertChanged)) | 
|  | .WillOnce(Return(true)); | 
|  | EXPECT_CALL(*prefs_, Delete(kPrefsCertificateReportToSendUpdate)) | 
|  | .WillOnce(Return(true)); | 
|  | EXPECT_CALL(*prefs_, SetString(kPrefsCertificateReportToSendDownload, _)) | 
|  | .Times(0); | 
|  | CertificateChecker::FlushReport(); | 
|  | } | 
|  |  | 
|  | // flush nothing to report | 
|  | TEST_F(CertificateCheckerTest, FlushNothingToReport) { | 
|  | string empty = ""; | 
|  | EXPECT_CALL(*prefs_, GetString(kPrefsCertificateReportToSendUpdate, _)) | 
|  | .WillOnce(DoAll( | 
|  | SetArgumentPointee<1>(empty), | 
|  | Return(true))); | 
|  | EXPECT_CALL(*prefs_, GetString(kPrefsCertificateReportToSendDownload, _)) | 
|  | .WillOnce(Return(false)); | 
|  | EXPECT_CALL(*mock_system_state_.mock_metrics_lib(), | 
|  | SendUserActionToUMA(_)).Times(0); | 
|  | EXPECT_CALL(*prefs_, SetString(_,_)).Times(0); | 
|  | CertificateChecker::FlushReport(); | 
|  | } | 
|  |  | 
|  | }  // namespace chromeos_update_engine |