1 // Copyright (C) 2013 Google Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "retriever.h" 16 17 #include <libaddressinput/callback.h> 18 #include <libaddressinput/null_storage.h> 19 #include <libaddressinput/storage.h> 20 #include <libaddressinput/util/basictypes.h> 21 #include <libaddressinput/util/scoped_ptr.h> 22 23 #include <cstddef> 24 #include <string> 25 26 #include <gtest/gtest.h> 27 28 #include "mock_source.h" 29 #include "testdata_source.h" 30 31 #define CHECKSUM "dd63dafcbd4d5b28badfcaf86fb6fcdb" 32 #define DATA "{'foo': 'bar'}" 33 #define OLD_TIMESTAMP "0" 34 35 namespace { 36 37 using i18n::addressinput::BuildCallback; 38 using i18n::addressinput::MockSource; 39 using i18n::addressinput::NullStorage; 40 using i18n::addressinput::Retriever; 41 using i18n::addressinput::scoped_ptr; 42 using i18n::addressinput::Storage; 43 using i18n::addressinput::TestdataSource; 44 45 const char kKey[] = "data/CA/AB--fr"; 46 47 // Empty data that the source can return. 48 const char kEmptyData[] = "{}"; 49 50 // The value of the data that the stale storage returns. 51 const char kStaleData[] = DATA; 52 53 // The actual data that the stale storage returns. 54 const char kStaleWrappedData[] = "timestamp=" OLD_TIMESTAMP "\n" 55 "checksum=" CHECKSUM "\n" 56 DATA; 57 58 // Tests for Retriever object. 59 class RetrieverTest : public testing::Test { 60 protected: 61 RetrieverTest() 62 : retriever_(new TestdataSource(false), new NullStorage), 63 success_(false), 64 key_(), 65 data_(), 66 data_ready_(BuildCallback(this, &RetrieverTest::OnDataReady)) {} 67 68 Retriever retriever_; 69 bool success_; 70 std::string key_; 71 std::string data_; 72 const scoped_ptr<const Retriever::Callback> data_ready_; 73 74 private: 75 void OnDataReady(bool success, 76 const std::string& key, 77 const std::string& data) { 78 success_ = success; 79 key_ = key; 80 data_ = data; 81 } 82 83 DISALLOW_COPY_AND_ASSIGN(RetrieverTest); 84 }; 85 86 TEST_F(RetrieverTest, RetrieveData) { 87 retriever_.Retrieve(kKey, *data_ready_); 88 89 EXPECT_TRUE(success_); 90 EXPECT_EQ(kKey, key_); 91 EXPECT_FALSE(data_.empty()); 92 EXPECT_NE(kEmptyData, data_); 93 } 94 95 TEST_F(RetrieverTest, ReadDataFromStorage) { 96 retriever_.Retrieve(kKey, *data_ready_); 97 retriever_.Retrieve(kKey, *data_ready_); 98 99 EXPECT_TRUE(success_); 100 EXPECT_EQ(kKey, key_); 101 EXPECT_FALSE(data_.empty()); 102 EXPECT_NE(kEmptyData, data_); 103 } 104 105 TEST_F(RetrieverTest, MissingKeyReturnsEmptyData) { 106 static const char kMissingKey[] = "junk"; 107 108 retriever_.Retrieve(kMissingKey, *data_ready_); 109 110 EXPECT_TRUE(success_); 111 EXPECT_EQ(kMissingKey, key_); 112 EXPECT_EQ(kEmptyData, data_); 113 } 114 115 TEST_F(RetrieverTest, FaultySource) { 116 // An empty MockSource will fail for any request. 117 Retriever bad_retriever(new MockSource, new NullStorage); 118 119 bad_retriever.Retrieve(kKey, *data_ready_); 120 121 EXPECT_FALSE(success_); 122 EXPECT_EQ(kKey, key_); 123 EXPECT_TRUE(data_.empty()); 124 } 125 126 // The storage that always returns stale data. 127 class StaleStorage : public Storage { 128 public: 129 StaleStorage() : data_updated_(false) {} 130 virtual ~StaleStorage() {} 131 132 // Storage implementation. 133 virtual void Get(const std::string& key, const Callback& data_ready) const { 134 data_ready(true, key, new std::string(kStaleWrappedData)); 135 } 136 137 virtual void Put(const std::string& key, std::string* value) { 138 ASSERT_TRUE(value != NULL); 139 data_updated_ = true; 140 delete value; 141 } 142 143 bool data_updated_; 144 145 private: 146 DISALLOW_COPY_AND_ASSIGN(StaleStorage); 147 }; 148 149 TEST_F(RetrieverTest, UseStaleDataWhenSourceFails) { 150 // Owned by |resilient_retriver|. 151 StaleStorage* stale_storage = new StaleStorage; 152 // An empty MockSource will fail for any request. 153 Retriever resilient_retriever(new MockSource, stale_storage); 154 155 resilient_retriever.Retrieve(kKey, *data_ready_); 156 157 EXPECT_TRUE(success_); 158 EXPECT_EQ(kKey, key_); 159 EXPECT_EQ(kStaleData, data_); 160 EXPECT_FALSE(stale_storage->data_updated_); 161 } 162 163 TEST_F(RetrieverTest, DoNotUseStaleDataWhenSourceSucceeds) { 164 // Owned by |resilient_retriver|. 165 StaleStorage* stale_storage = new StaleStorage; 166 Retriever resilient_retriever(new TestdataSource(false), stale_storage); 167 168 resilient_retriever.Retrieve(kKey, *data_ready_); 169 170 EXPECT_TRUE(success_); 171 EXPECT_EQ(kKey, key_); 172 EXPECT_FALSE(data_.empty()); 173 EXPECT_NE(kEmptyData, data_); 174 EXPECT_NE(kStaleData, data_); 175 EXPECT_TRUE(stale_storage->data_updated_); 176 } 177 178 } // namespace 179