Index: net/dns/mdns_cache_unittest.cc |
diff --git a/net/dns/mdns_cache_unittest.cc b/net/dns/mdns_cache_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..358461a51ec866a59f2755989c619c631507f265 |
--- /dev/null |
+++ b/net/dns/mdns_cache_unittest.cc |
@@ -0,0 +1,215 @@ |
+// Copyright (c) 2013 The Chromium 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 "net/dns/dns_response.h" |
+#include "net/dns/dns_test_util.h" |
+#include "net/dns/mdns_cache.h" |
+#include "net/dns/record_parsed.h" |
+#include "net/dns/record_rdata.h" |
+#include "testing/gmock/include/gmock/gmock.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+using ::testing::Return; |
+using ::testing::NiceMock; |
+ |
+namespace net { |
+ |
+static const uint8 kTestResposesDifferentAnswers[] = { |
+ // Answer 1 |
+ // ghs.l.google.com in DNS format. |
+ 0x03, 'g', 'h', 's', |
+ 0x01, 'l', |
+ 0x06, 'g', 'o', 'o', 'g', 'l', 'e', |
+ 0x03, 'c', 'o', 'm', |
+ 0x00, |
+ 0x00, 0x01, // TYPE is A. |
+ 0x00, 0x01, // CLASS is IN. |
+ 0x00, 0x00, // TTL (4 bytes) is 53 seconds. |
+ 0x00, 0x35, |
+ 0x00, 0x04, // RDLENGTH is 4 bytes. |
+ 0x4a, 0x7d, // RDATA is the IP: 74.125.95.121 |
+ 0x5f, 0x79, |
+ |
+ // Answer 2 |
+ // Pointer to answer 1 |
+ 0xc0, 0x00, |
+ 0x00, 0x01, // TYPE is A. |
+ 0x00, 0x01, // CLASS is IN. |
+ 0x00, 0x00, // TTL (4 bytes) is 53 seconds. |
+ 0x00, 0x35, |
+ 0x00, 0x04, // RDLENGTH is 4 bytes. |
+ 0x4a, 0x7d, // RDATA is the IP: 74.125.95.122 |
+ 0x5f, 0x80, |
+}; |
+ |
+static const uint8 kTestResposesSameAnswers[] = { |
+ // Answer 1 |
+ // ghs.l.google.com in DNS format. |
+ 0x03, 'g', 'h', 's', |
+ 0x01, 'l', |
+ 0x06, 'g', 'o', 'o', 'g', 'l', 'e', |
+ 0x03, 'c', 'o', 'm', |
+ 0x00, |
+ 0x00, 0x01, // TYPE is A. |
+ 0x00, 0x01, // CLASS is IN. |
+ 0x00, 0x00, // TTL (4 bytes) is 53 seconds. |
+ 0x00, 0x35, |
+ 0x00, 0x04, // RDLENGTH is 4 bytes. |
+ 0x4a, 0x7d, // RDATA is the IP: 74.125.95.121 |
+ 0x5f, 0x79, |
+ |
+ // Answer 2 |
+ // Pointer to answer 1 |
+ 0xc0, 0x00, |
+ 0x00, 0x01, // TYPE is A. |
+ 0x00, 0x01, // CLASS is IN. |
+ 0x00, 0x00, // TTL (4 bytes) is 112 seconds. |
+ 0x00, 0x70, |
+ 0x00, 0x04, // RDLENGTH is 4 bytes. |
+ 0x4a, 0x7d, // RDATA is the IP: 74.125.95.121 |
+ 0x5f, 0x79, |
+}; |
+ |
+class MDnsCacheTest : public ::testing::Test { |
+ public: |
+ MDnsCacheTest() : default_time_(base::Time::FromDoubleT(1234.0)) {} |
+ virtual ~MDnsCacheTest() {} |
+ |
+ protected: |
+ base::Time default_time_; |
+ MDnsCache cache_; |
+}; |
+ |
+TEST_F(MDnsCacheTest, InsertLookupSingle) { |
+ DnsRecordParser parser(kT1ResponseDatagram, sizeof(kT1ResponseDatagram), |
+ sizeof(dns_protocol::Header)); |
+ parser.SkipQuestion(); |
+ scoped_ptr<const RecordParsed> record1; |
+ scoped_ptr<const RecordParsed> record2; |
+ std::list<const RecordParsed*> results; |
+ |
+ record1 = RecordParsed::CreateFrom(&parser, default_time_); |
+ record2 = RecordParsed::CreateFrom(&parser, default_time_); |
+ |
+ EXPECT_EQ(MDnsCache::RecordAdded, cache_.UpdateDnsRecord(record1.release())); |
+ |
+ EXPECT_EQ(MDnsCache::RecordAdded, cache_.UpdateDnsRecord(record2.release())); |
+ |
+ MDnsCache::TypeNameQuery query_success( |
+ ARecordRdata::kType, "ghs.l.google.com"); |
+ |
+ EXPECT_TRUE(cache_.FindDnsRecords(query_success, &results, default_time_)); |
+ EXPECT_EQ(1u, results.size()); |
+ EXPECT_EQ(default_time_, results.front()->time_created()); |
+ |
+ EXPECT_EQ("ghs.l.google.com", results.front()->name()); |
+ |
+ MDnsCache::TypeNameQuery query_failure( |
+ PtrRecordRdata::kType, "ghs.l.google.com"); |
+ |
+ EXPECT_FALSE(cache_.FindDnsRecords(query_failure, &results, default_time_)); |
+} |
+ |
+TEST_F(MDnsCacheTest, Expiration) { |
+ DnsRecordParser parser(kT1ResponseDatagram, sizeof(kT1ResponseDatagram), |
+ sizeof(dns_protocol::Header)); |
+ parser.SkipQuestion(); |
+ scoped_ptr<const RecordParsed> record1; |
+ scoped_ptr<const RecordParsed> record2; |
+ |
+ std::list<const RecordParsed*> results; |
+ std::list<linked_ptr<const RecordParsed> > removed; |
+ |
+ record1 = RecordParsed::CreateFrom(&parser, default_time_); |
+ base::TimeDelta ttl1 = base::TimeDelta::FromSeconds(record1->ttl()); |
+ |
+ record2 = RecordParsed::CreateFrom(&parser, default_time_); |
+ base::TimeDelta ttl2 = base::TimeDelta::FromSeconds(record2->ttl()); |
+ |
+ EXPECT_EQ(MDnsCache::RecordAdded, cache_.UpdateDnsRecord(record1.release())); |
+ EXPECT_EQ(MDnsCache::RecordAdded, cache_.UpdateDnsRecord(record2.release())); |
+ |
+ MDnsCache::TypeNameQuery query_expired( |
+ ARecordRdata::kType, "ghs.l.google.com"); |
+ |
+ EXPECT_TRUE(cache_.FindDnsRecords(query_expired, &results, default_time_)); |
+ |
+ EXPECT_EQ(default_time_ + ttl2, cache_.GetNextExpiration()); |
+ |
+ EXPECT_FALSE(cache_.FindDnsRecords(query_expired, &results, |
+ default_time_ + ttl2)); |
+ |
+ cache_.CleanupRecords(&removed, default_time_ + ttl2); |
+ |
+ EXPECT_EQ(1u, removed.size()); |
+ |
+ EXPECT_EQ(removed.front()->name(), "ghs.l.google.com"); |
+ |
+ // To make sure that we've indeed removed them from the map, check no funny |
+ // business happens once they're deleted for good. |
+ removed.empty(); |
+ |
+ EXPECT_EQ(default_time_ + ttl1, cache_.GetNextExpiration()); |
+ EXPECT_FALSE(cache_.FindDnsRecords(query_expired, &results, |
+ default_time_ + ttl2)); |
+} |
+ |
+TEST_F(MDnsCacheTest, RecordChange) { |
+ DnsRecordParser parser(kTestResposesDifferentAnswers, |
+ sizeof(kTestResposesDifferentAnswers), |
+ 0); |
+ |
+ scoped_ptr<const RecordParsed> record1; |
+ scoped_ptr<const RecordParsed> record2; |
+ std::list<const RecordParsed*> results; |
+ std::list<linked_ptr<const RecordParsed> > removed; |
+ |
+ record1 = RecordParsed::CreateFrom(&parser, default_time_); |
+ record2 = RecordParsed::CreateFrom(&parser, default_time_); |
+ |
+ EXPECT_EQ(MDnsCache::RecordAdded, cache_.UpdateDnsRecord(record1.release())); |
+ EXPECT_EQ(MDnsCache::RecordChanged, |
+ cache_.UpdateDnsRecord(record2.release())); |
+} |
+ |
+TEST_F(MDnsCacheTest, RecordNoChange) { |
+ DnsRecordParser parser(kTestResposesSameAnswers, |
+ sizeof(kTestResposesSameAnswers), |
+ 0); |
+ |
+ scoped_ptr<const RecordParsed> record1; |
+ scoped_ptr<const RecordParsed> record2; |
+ std::list<const RecordParsed*> results; |
+ std::list<linked_ptr<const RecordParsed> > removed; |
+ |
+ record1 = RecordParsed::CreateFrom(&parser, default_time_); |
+ record2 = RecordParsed::CreateFrom(&parser, default_time_ + |
+ base::TimeDelta::FromSeconds(1)); |
+ |
+ EXPECT_EQ(MDnsCache::RecordAdded, cache_.UpdateDnsRecord(record1.release())); |
+ EXPECT_EQ(MDnsCache::NoChange, cache_.UpdateDnsRecord(record2.release())); |
+} |
+ |
+TEST_F(MDnsCacheTest, RecordPreemptExpirationTime) { |
+ DnsRecordParser parser(kTestResposesSameAnswers, |
+ sizeof(kTestResposesSameAnswers), |
+ 0); |
+ |
+ scoped_ptr<const RecordParsed> record1; |
+ scoped_ptr<const RecordParsed> record2; |
+ std::list<const RecordParsed*> results; |
+ std::list<linked_ptr<const RecordParsed> > removed; |
+ |
+ record1 = RecordParsed::CreateFrom(&parser, default_time_); |
+ record2 = RecordParsed::CreateFrom(&parser, default_time_); |
+ base::TimeDelta ttl1 = base::TimeDelta::FromSeconds(record1->ttl()); |
+ base::TimeDelta ttl2 = base::TimeDelta::FromSeconds(record2->ttl()); |
+ |
+ EXPECT_EQ(base::Time(), cache_.GetNextExpiration()); |
+ EXPECT_EQ(MDnsCache::RecordAdded, cache_.UpdateDnsRecord(record2.release())); |
+ EXPECT_EQ(default_time_ + ttl2, cache_.GetNextExpiration()); |
+ EXPECT_EQ(MDnsCache::NoChange, cache_.UpdateDnsRecord(record1.release())); |
+ EXPECT_EQ(default_time_ + ttl1, cache_.GetNextExpiration()); |
+} |
+} |