| OLD | NEW |
| 1 // Copyright (C) 2013 Google Inc. | 1 // Copyright (C) 2013 Google Inc. |
| 2 // | 2 // |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 // you may not use this file except in compliance with 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 | 5 // You may obtain a copy of the License at |
| 6 // | 6 // |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 // | 8 // |
| 9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 // See the License for the specific language governing permissions and | 12 // See the License for the specific language governing permissions and |
| 13 // limitations under the License. | 13 // limitations under the License. |
| 14 | 14 |
| 15 #include "retriever.h" | 15 #include "retriever.h" |
| 16 | 16 |
| 17 #include <libaddressinput/callback.h> | 17 #include <libaddressinput/callback.h> |
| 18 #include <libaddressinput/downloader.h> | 18 #include <libaddressinput/downloader.h> |
| 19 #include <libaddressinput/storage.h> |
| 19 #include <libaddressinput/util/scoped_ptr.h> | 20 #include <libaddressinput/util/scoped_ptr.h> |
| 20 | 21 |
| 22 #include <cstddef> |
| 23 #include <ctime> |
| 21 #include <string> | 24 #include <string> |
| 22 | 25 |
| 23 #include <gtest/gtest.h> | 26 #include <gtest/gtest.h> |
| 24 | 27 |
| 25 #include "fake_downloader.h" | 28 #include "fake_downloader.h" |
| 26 #include "fake_storage.h" | 29 #include "fake_storage.h" |
| 27 #include "region_data_constants.h" | 30 #include "region_data_constants.h" |
| 28 | 31 |
| 29 namespace i18n { | 32 namespace i18n { |
| 30 namespace addressinput { | 33 namespace addressinput { |
| 31 | 34 |
| 35 namespace { |
| 36 |
| 32 const char kKey[] = "data/CA/AB--fr"; | 37 const char kKey[] = "data/CA/AB--fr"; |
| 33 | 38 |
| 34 // Empty data that the downloader can return. | 39 // Empty data that the downloader can return. |
| 35 const char kEmptyData[] = "{}"; | 40 const char kEmptyData[] = "{}"; |
| 36 | 41 |
| 42 // The MD5 checksum for kEmptyData. Retriever uses MD5 to validate data |
| 43 // integrity. |
| 44 const char kEmptyDataChecksum[] = "99914b932bd37a50b983c5e7c90ae93b"; |
| 45 |
| 46 // Returns a string serialization of the current time. |
| 47 std::string BuildCurrentTimestampString() { |
| 48 time_t timestamp = time(NULL); |
| 49 char timestamp_string[2 + 3 * sizeof timestamp]; |
| 50 snprintf(timestamp_string, sizeof timestamp_string, "%ld", timestamp); |
| 51 return timestamp_string; |
| 52 } |
| 53 |
| 54 } // namespace |
| 55 |
| 37 // Tests for Retriever object. | 56 // Tests for Retriever object. |
| 38 class RetrieverTest : public testing::Test { | 57 class RetrieverTest : public testing::Test { |
| 39 protected: | 58 protected: |
| 40 RetrieverTest() | 59 RetrieverTest() |
| 41 : success_(false), | 60 : storage_(NULL), |
| 61 retriever_(), |
| 62 success_(false), |
| 42 key_(), | 63 key_(), |
| 43 data_() { | 64 data_() { |
| 44 ResetRetriever(FakeDownloader::kFakeDataUrl); | 65 ResetRetriever(FakeDownloader::kFakeDataUrl); |
| 45 } | 66 } |
| 46 | 67 |
| 47 virtual ~RetrieverTest() {} | 68 virtual ~RetrieverTest() {} |
| 48 | 69 |
| 49 scoped_ptr<Retriever::Callback> BuildCallback() { | 70 scoped_ptr<Retriever::Callback> BuildCallback() { |
| 50 return ::i18n::addressinput::BuildCallback( | 71 return ::i18n::addressinput::BuildCallback( |
| 51 this, &RetrieverTest::OnDataReady); | 72 this, &RetrieverTest::OnDataReady); |
| 52 } | 73 } |
| 53 | 74 |
| 54 void ResetRetriever(const std::string& url) { | 75 void ResetRetriever(const std::string& url) { |
| 76 storage_ = new FakeStorage; |
| 55 retriever_.reset( | 77 retriever_.reset( |
| 56 new Retriever(url, | 78 new Retriever(url, |
| 57 scoped_ptr<Downloader>(new FakeDownloader), | 79 scoped_ptr<Downloader>(new FakeDownloader), |
| 58 scoped_ptr<Storage>(new FakeStorage))); | 80 scoped_ptr<Storage>(storage_))); |
| 59 } | 81 } |
| 60 | 82 |
| 61 std::string GetUrlForKey(const std::string& key) { | 83 std::string GetUrlForKey(const std::string& key) { |
| 62 return retriever_->GetUrlForKey(key); | 84 return retriever_->GetUrlForKey(key); |
| 63 } | 85 } |
| 64 | 86 |
| 65 std::string GetKeyForUrl(const std::string& url) { | 87 std::string GetKeyForUrl(const std::string& url) { |
| 66 return retriever_->GetKeyForUrl(url); | 88 return retriever_->GetKeyForUrl(url); |
| 67 } | 89 } |
| 68 | 90 |
| 91 Storage* storage_; // Owned by |retriever_|. |
| 69 scoped_ptr<Retriever> retriever_; | 92 scoped_ptr<Retriever> retriever_; |
| 70 bool success_; | 93 bool success_; |
| 71 std::string key_; | 94 std::string key_; |
| 72 std::string data_; | 95 std::string data_; |
| 73 | 96 |
| 74 private: | 97 private: |
| 75 void OnDataReady(bool success, | 98 void OnDataReady(bool success, |
| 76 const std::string& key, | 99 const std::string& key, |
| 77 const std::string& data) { | 100 const std::string& data) { |
| 78 success_ = success; | 101 success_ = success; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 140 scoped_ptr<Storage>(new FakeStorage)); | 163 scoped_ptr<Storage>(new FakeStorage)); |
| 141 const char kFallbackDataKey[] = "data/US"; | 164 const char kFallbackDataKey[] = "data/US"; |
| 142 bad_retriever.Retrieve(kFallbackDataKey, BuildCallback()); | 165 bad_retriever.Retrieve(kFallbackDataKey, BuildCallback()); |
| 143 | 166 |
| 144 EXPECT_TRUE(success_); | 167 EXPECT_TRUE(success_); |
| 145 EXPECT_EQ(kFallbackDataKey, key_); | 168 EXPECT_EQ(kFallbackDataKey, key_); |
| 146 EXPECT_FALSE(data_.empty()); | 169 EXPECT_FALSE(data_.empty()); |
| 147 EXPECT_NE(kEmptyData, data_); | 170 EXPECT_NE(kEmptyData, data_); |
| 148 } | 171 } |
| 149 | 172 |
| 173 TEST_F(RetrieverTest, NoChecksumAndTimestampWillRedownload) { |
| 174 storage_->Put(kKey, kEmptyData); |
| 175 retriever_->Retrieve(kKey, BuildCallback()); |
| 176 EXPECT_TRUE(success_); |
| 177 EXPECT_EQ(kKey, key_); |
| 178 EXPECT_FALSE(data_.empty()); |
| 179 EXPECT_NE(kEmptyData, data_); |
| 180 } |
| 181 |
| 182 TEST_F(RetrieverTest, ChecksumAndTimestampWillNotRedownload) { |
| 183 storage_->Put(kKey, |
| 184 "timestamp=" + BuildCurrentTimestampString() + "\n" + |
| 185 "checksum=" + kEmptyDataChecksum + "\n" + |
| 186 kEmptyData); |
| 187 retriever_->Retrieve(kKey, BuildCallback()); |
| 188 EXPECT_TRUE(success_); |
| 189 EXPECT_EQ(kKey, key_); |
| 190 EXPECT_EQ(kEmptyData, data_); |
| 191 } |
| 192 |
| 193 TEST_F(RetrieverTest, OldTimestampWillRedownload) { |
| 194 storage_->Put(kKey, |
| 195 std::string("timestamp=0\n") + |
| 196 "checksum=" + kEmptyDataChecksum + "\n" + |
| 197 kEmptyData); |
| 198 retriever_->Retrieve(kKey, BuildCallback()); |
| 199 EXPECT_TRUE(success_); |
| 200 EXPECT_EQ(kKey, key_); |
| 201 EXPECT_FALSE(data_.empty()); |
| 202 EXPECT_NE(kEmptyData, data_); |
| 203 } |
| 204 |
| 205 TEST_F(RetrieverTest, OldTimestampOkIfDownloadFails) { |
| 206 storage_ = new FakeStorage; |
| 207 Retriever bad_retriever(FakeDownloader::kFakeDataUrl, |
| 208 scoped_ptr<Downloader>(new FaultyDownloader), |
| 209 scoped_ptr<Storage>(storage_)); |
| 210 storage_->Put(kKey, |
| 211 std::string("timestamp=0\n") + |
| 212 "checksum=" + kEmptyDataChecksum + "\n" + |
| 213 kEmptyData); |
| 214 bad_retriever.Retrieve(kKey, BuildCallback()); |
| 215 EXPECT_TRUE(success_); |
| 216 EXPECT_EQ(kKey, key_); |
| 217 EXPECT_EQ(kEmptyData, data_); |
| 218 } |
| 219 |
| 220 TEST_F(RetrieverTest, WrongChecksumWillRedownload) { |
| 221 static const char kNonEmptyData[] = "{\"non-empty\": \"data\"}"; |
| 222 storage_->Put(kKey, |
| 223 "timestamp=" + BuildCurrentTimestampString() + "\n" + |
| 224 "checksum=" + kEmptyDataChecksum + "\n" + |
| 225 kNonEmptyData); |
| 226 retriever_->Retrieve(kKey, BuildCallback()); |
| 227 EXPECT_TRUE(success_); |
| 228 EXPECT_EQ(kKey, key_); |
| 229 EXPECT_FALSE(data_.empty()); |
| 230 EXPECT_NE(kNonEmptyData, data_); |
| 231 } |
| 232 |
| 150 // The downloader that doesn't get back to you. | 233 // The downloader that doesn't get back to you. |
| 151 class HangingDownloader : public Downloader { | 234 class HangingDownloader : public Downloader { |
| 152 public: | 235 public: |
| 153 HangingDownloader() {} | 236 HangingDownloader() {} |
| 154 virtual ~HangingDownloader() {} | 237 virtual ~HangingDownloader() {} |
| 155 | 238 |
| 156 // Downloader implementation. | 239 // Downloader implementation. |
| 157 virtual void Download(const std::string& url, | 240 virtual void Download(const std::string& url, |
| 158 scoped_ptr<Callback> downloaded) {} | 241 scoped_ptr<Callback> downloaded) {} |
| 159 }; | 242 }; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 184 EXPECT_EQ("", GetKeyForUrl("http://www.google.com/")); | 267 EXPECT_EQ("", GetKeyForUrl("http://www.google.com/")); |
| 185 EXPECT_EQ("", GetKeyForUrl("")); | 268 EXPECT_EQ("", GetKeyForUrl("")); |
| 186 EXPECT_EQ("", GetKeyForUrl("test:///")); | 269 EXPECT_EQ("", GetKeyForUrl("test:///")); |
| 187 EXPECT_EQ("data", GetKeyForUrl("test:///data")); | 270 EXPECT_EQ("data", GetKeyForUrl("test:///data")); |
| 188 EXPECT_EQ("data/US", GetKeyForUrl("test:///data/US")); | 271 EXPECT_EQ("data/US", GetKeyForUrl("test:///data/US")); |
| 189 EXPECT_EQ("data/CA--fr", GetKeyForUrl("test:///data/CA--fr")); | 272 EXPECT_EQ("data/CA--fr", GetKeyForUrl("test:///data/CA--fr")); |
| 190 } | 273 } |
| 191 | 274 |
| 192 } // namespace addressinput | 275 } // namespace addressinput |
| 193 } // namespace i18n | 276 } // namespace i18n |
| OLD | NEW |