xref: /aosp_15_r20/external/cronet/net/dns/record_parsed_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2013 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/dns/record_parsed.h"
6 
7 #include <memory>
8 
9 #include "base/time/time.h"
10 #include "net/dns/dns_response.h"
11 #include "net/dns/dns_test_util.h"
12 #include "net/dns/public/dns_protocol.h"
13 #include "net/dns/record_rdata.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 
16 namespace net {
17 
18 static const uint8_t kT1ResponseWithCacheFlushBit[] = {
19     0x0a, 'c', 'o', 'd', 'e', 'r', 'e', 'v', 'i', 'e', 'w', 0x08, 'c', 'h', 'r',
20     'o', 'm', 'i', 'u', 'm', 0x03, 'o', 'r', 'g', 0x00, 0x00,
21     0x05,        // TYPE is CNAME.
22     0x80, 0x01,  // CLASS is IN with cache flush bit set.
23     0x00, 0x01,  // TTL (4 bytes) is 20 hours, 47 minutes, 48 seconds.
24     0x24, 0x74, 0x00, 0x12,  // RDLENGTH is 18 bytes.
25     // ghs.l.google.com in DNS format.
26     0x03, 'g', 'h', 's', 0x01, 'l', 0x06, 'g', 'o', 'o', 'g', 'l', 'e', 0x03,
27     'c', 'o', 'm', 0x00};
28 
TEST(RecordParsedTest,ParseSingleRecord)29 TEST(RecordParsedTest, ParseSingleRecord) {
30   DnsRecordParser parser(kT1ResponseDatagram, sizeof(kT1ResponseDatagram),
31                          sizeof(dns_protocol::Header), kT1RecordCount);
32   std::unique_ptr<const RecordParsed> record;
33   const CnameRecordRdata* rdata;
34 
35   std::string dotted_qname;
36   uint16_t qtype;
37   parser.ReadQuestion(dotted_qname, qtype);
38 
39   record = RecordParsed::CreateFrom(&parser, base::Time());
40   EXPECT_TRUE(record != nullptr);
41 
42   ASSERT_EQ("codereview.chromium.org", record->name());
43   ASSERT_EQ(dns_protocol::kTypeCNAME, record->type());
44   ASSERT_EQ(dns_protocol::kClassIN, record->klass());
45 
46   rdata = record->rdata<CnameRecordRdata>();
47   ASSERT_TRUE(rdata != nullptr);
48   ASSERT_EQ(kT1CanonName, rdata->cname());
49 
50   ASSERT_FALSE(record->rdata<SrvRecordRdata>());
51   ASSERT_TRUE(record->IsEqual(record.get(), true));
52 }
53 
TEST(RecordParsedTest,CacheFlushBitCompare)54 TEST(RecordParsedTest, CacheFlushBitCompare) {
55   DnsRecordParser parser1(kT1ResponseDatagram, sizeof(kT1ResponseDatagram),
56                           sizeof(dns_protocol::Header), kT1RecordCount);
57   std::string dotted_qname;
58   uint16_t qtype;
59   parser1.ReadQuestion(dotted_qname, qtype);
60 
61   std::unique_ptr<const RecordParsed> record1 =
62       RecordParsed::CreateFrom(&parser1, base::Time());
63 
64   DnsRecordParser parser2(kT1ResponseWithCacheFlushBit,
65                           sizeof(kT1ResponseWithCacheFlushBit), 0,
66                           kT1RecordCount);
67 
68   std::unique_ptr<const RecordParsed> record2 =
69       RecordParsed::CreateFrom(&parser2, base::Time());
70 
71   EXPECT_FALSE(record1->IsEqual(record2.get(), false));
72   EXPECT_TRUE(record1->IsEqual(record2.get(), true));
73   EXPECT_FALSE(record2->IsEqual(record1.get(), false));
74   EXPECT_TRUE(record2->IsEqual(record1.get(), true));
75 }
76 
TEST(RecordParsedTest,ParseUnknownRdata)77 TEST(RecordParsedTest, ParseUnknownRdata) {
78   static const char kRecordData[] =
79       // NAME="foo.test"
80       "\003foo\004test\000"
81       // TYPE=MD (an obsolete type that will likely never be recognized by
82       // Chrome)
83       "\000\003"
84       // CLASS=IN
85       "\000\001"
86       // TTL=30 seconds
87       "\000\000\000\036"
88       // RDLENGTH=12 bytes
89       "\000\014"
90       // RDATA="garbage data"
91       "garbage data";
92   DnsRecordParser parser(kRecordData, sizeof(kRecordData) - 1, 0 /* offset */,
93                          /*num_records=*/1);
94 
95   std::unique_ptr<const RecordParsed> record =
96       RecordParsed::CreateFrom(&parser, base::Time());
97 
98   ASSERT_TRUE(record);
99   EXPECT_EQ(record->name(), "foo.test");
100   EXPECT_EQ(record->type(), 3u);
101   EXPECT_EQ(record->klass(), dns_protocol::kClassIN);
102   EXPECT_EQ(record->ttl(), 30u);
103   EXPECT_FALSE(record->rdata<ARecordRdata>());
104   EXPECT_FALSE(record->rdata_for_testing());
105 }
106 
TEST(RecordParsedTest,EqualityHandlesUnknownRdata)107 TEST(RecordParsedTest, EqualityHandlesUnknownRdata) {
108   static constexpr char kData[] =
109       // NAME="foo.test"
110       "\003foo\004test\000"
111       // TYPE=MD (an obsolete type that will likely never be recognized by
112       // Chrome)
113       "\000\003"
114       // CLASS=IN
115       "\000\001"
116       // TTL=30 seconds
117       "\000\000\000\036"
118       // RDLENGTH=12 bytes
119       "\000\014"
120       // RDATA="garbage data"
121       "garbage data"
122       // NAME="foo.test"
123       "\003foo\004test\000"
124       // TYPE=A
125       "\000\001"
126       // CLASS=IN
127       "\000\001"
128       // TTL=30 seconds
129       "\000\000\000\036"
130       // RDLENGTH=4 bytes
131       "\000\004"
132       // RDATA=8.8.8.8
133       "\010\010\010\010";
134   DnsRecordParser parser(kData, sizeof(kData) - 1, 0 /* offset */,
135                          /*num_records=*/2);
136 
137   std::unique_ptr<const RecordParsed> unknown_record =
138       RecordParsed::CreateFrom(&parser, base::Time());
139   ASSERT_TRUE(unknown_record);
140   ASSERT_FALSE(unknown_record->rdata_for_testing());
141 
142   std::unique_ptr<const RecordParsed> known_record =
143       RecordParsed::CreateFrom(&parser, base::Time());
144   ASSERT_TRUE(known_record);
145   ASSERT_TRUE(known_record->rdata_for_testing());
146 
147   EXPECT_TRUE(
148       unknown_record->IsEqual(unknown_record.get(), false /* is_mdns */));
149   EXPECT_TRUE(
150       unknown_record->IsEqual(unknown_record.get(), true /* is_mdns */));
151   EXPECT_TRUE(known_record->IsEqual(known_record.get(), false /* is_mdns */));
152   EXPECT_TRUE(known_record->IsEqual(known_record.get(), true /* is_mdns */));
153   EXPECT_FALSE(
154       unknown_record->IsEqual(known_record.get(), false /* is_mdns */));
155   EXPECT_FALSE(unknown_record->IsEqual(known_record.get(), true /* is_mdns */));
156   EXPECT_FALSE(
157       known_record->IsEqual(unknown_record.get(), false /* is_mdns */));
158   EXPECT_FALSE(known_record->IsEqual(unknown_record.get(), true /* is_mdns */));
159 }
160 
TEST(RecordParsedTest,RejectMalformedRdata)161 TEST(RecordParsedTest, RejectMalformedRdata) {
162   static const char kRecordData[] =
163       // NAME="foo.test"
164       "\003foo\004test\000"
165       // TYPE=PTR
166       "\000\014"
167       // CLASS=IN
168       "\000\001"
169       // TTL=31 seconds
170       "\000\000\000\037"
171       // RDLENGTH=1 byte
172       "\000\001"
173       // RDATA=truncated name
174       "\001";
175   DnsRecordParser parser(kRecordData, sizeof(kRecordData) - 1, 0 /* offset */,
176                          /*num_records=*/1);
177 
178   std::unique_ptr<const RecordParsed> record =
179       RecordParsed::CreateFrom(&parser, base::Time());
180 
181   EXPECT_FALSE(record);
182 }
183 
184 }  // namespace net
185