123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403 |
- // Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
- //
- // Permission to use, copy, modify, and/or distribute this software for any
- // purpose with or without fee is hereby granted, provided that the above
- // copyright notice and this permission notice appear in all copies.
- //
- // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
- // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
- // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
- // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- // PERFORMANCE OF THIS SOFTWARE.
- #include <dns/labelsequence.h>
- #include <dns/name.h>
- #include <exceptions/exceptions.h>
- #include <gtest/gtest.h>
- #include <boost/functional/hash.hpp>
- #include <string>
- #include <set>
- using namespace isc::dns;
- using namespace std;
- namespace {
- class LabelSequenceTest : public ::testing::Test {
- public:
- LabelSequenceTest() : n1("example.org"), n2("example.com"),
- n3("example.org"), n4("foo.bar.test.example"),
- n5("example.ORG"), n6("ExAmPlE.org"),
- n7("."), n8("foo.example.org.bar"),
- n9("\\000xample.org"),
- n10("\\000xample.org"),
- n11("\\000xample.com"),
- n12("\\000xamplE.com"),
- ls1(n1), ls2(n2), ls3(n3), ls4(n4), ls5(n5),
- ls6(n6), ls7(n7), ls8(n8),
- ls9(n9), ls10(n10), ls11(n11), ls12(n12)
- {};
- // Need to keep names in scope for at least the lifetime of
- // the labelsequences
- Name n1, n2, n3, n4, n5, n6, n7, n8;
- Name n9, n10, n11, n12;
- LabelSequence ls1, ls2, ls3, ls4, ls5, ls6, ls7, ls8;
- LabelSequence ls9, ls10, ls11, ls12;
- };
- // Basic equality tests
- TEST_F(LabelSequenceTest, equals_sensitive) {
- EXPECT_TRUE(ls1.equals(ls1, true));
- EXPECT_FALSE(ls1.equals(ls2, true));
- EXPECT_TRUE(ls1.equals(ls3, true));
- EXPECT_FALSE(ls1.equals(ls4, true));
- EXPECT_FALSE(ls1.equals(ls5, true));
- EXPECT_FALSE(ls1.equals(ls6, true));
- EXPECT_FALSE(ls1.equals(ls7, true));
- EXPECT_FALSE(ls1.equals(ls8, true));
- EXPECT_FALSE(ls2.equals(ls1, true));
- EXPECT_TRUE(ls2.equals(ls2, true));
- EXPECT_FALSE(ls2.equals(ls3, true));
- EXPECT_FALSE(ls2.equals(ls4, true));
- EXPECT_FALSE(ls2.equals(ls5, true));
- EXPECT_FALSE(ls2.equals(ls6, true));
- EXPECT_FALSE(ls2.equals(ls7, true));
- EXPECT_FALSE(ls2.equals(ls8, true));
- EXPECT_FALSE(ls4.equals(ls1, true));
- EXPECT_FALSE(ls4.equals(ls2, true));
- EXPECT_FALSE(ls4.equals(ls3, true));
- EXPECT_TRUE(ls4.equals(ls4, true));
- EXPECT_FALSE(ls4.equals(ls5, true));
- EXPECT_FALSE(ls4.equals(ls6, true));
- EXPECT_FALSE(ls4.equals(ls7, true));
- EXPECT_FALSE(ls4.equals(ls8, true));
- EXPECT_FALSE(ls5.equals(ls1, true));
- EXPECT_FALSE(ls5.equals(ls2, true));
- EXPECT_FALSE(ls5.equals(ls3, true));
- EXPECT_FALSE(ls5.equals(ls4, true));
- EXPECT_TRUE(ls5.equals(ls5, true));
- EXPECT_FALSE(ls5.equals(ls6, true));
- EXPECT_FALSE(ls5.equals(ls7, true));
- EXPECT_FALSE(ls5.equals(ls8, true));
- EXPECT_TRUE(ls9.equals(ls10, true));
- EXPECT_FALSE(ls9.equals(ls11, true));
- EXPECT_FALSE(ls9.equals(ls12, true));
- EXPECT_FALSE(ls11.equals(ls12, true));
- }
- TEST_F(LabelSequenceTest, equals_insensitive) {
- EXPECT_TRUE(ls1.equals(ls1));
- EXPECT_FALSE(ls1.equals(ls2));
- EXPECT_TRUE(ls1.equals(ls3));
- EXPECT_FALSE(ls1.equals(ls4));
- EXPECT_TRUE(ls1.equals(ls5));
- EXPECT_TRUE(ls1.equals(ls6));
- EXPECT_FALSE(ls1.equals(ls7));
- EXPECT_FALSE(ls2.equals(ls1));
- EXPECT_TRUE(ls2.equals(ls2));
- EXPECT_FALSE(ls2.equals(ls3));
- EXPECT_FALSE(ls2.equals(ls4));
- EXPECT_FALSE(ls2.equals(ls5));
- EXPECT_FALSE(ls2.equals(ls6));
- EXPECT_FALSE(ls2.equals(ls7));
- EXPECT_TRUE(ls3.equals(ls1));
- EXPECT_FALSE(ls3.equals(ls2));
- EXPECT_TRUE(ls3.equals(ls3));
- EXPECT_FALSE(ls3.equals(ls4));
- EXPECT_TRUE(ls3.equals(ls5));
- EXPECT_TRUE(ls3.equals(ls6));
- EXPECT_FALSE(ls3.equals(ls7));
- EXPECT_FALSE(ls4.equals(ls1));
- EXPECT_FALSE(ls4.equals(ls2));
- EXPECT_FALSE(ls4.equals(ls3));
- EXPECT_TRUE(ls4.equals(ls4));
- EXPECT_FALSE(ls4.equals(ls5));
- EXPECT_FALSE(ls4.equals(ls6));
- EXPECT_FALSE(ls4.equals(ls7));
- EXPECT_TRUE(ls5.equals(ls1));
- EXPECT_FALSE(ls5.equals(ls2));
- EXPECT_TRUE(ls5.equals(ls3));
- EXPECT_FALSE(ls5.equals(ls4));
- EXPECT_TRUE(ls5.equals(ls5));
- EXPECT_TRUE(ls5.equals(ls6));
- EXPECT_FALSE(ls5.equals(ls7));
- EXPECT_TRUE(ls9.equals(ls10));
- EXPECT_FALSE(ls9.equals(ls11));
- EXPECT_FALSE(ls9.equals(ls12));
- EXPECT_TRUE(ls11.equals(ls12));
- }
- void
- getDataCheck(const uint8_t* expected_data, size_t expected_len,
- const LabelSequence& ls)
- {
- size_t len;
- const uint8_t* data = ls.getData(&len);
- ASSERT_EQ(expected_len, len) << "Expected data: " << expected_data <<
- " name: " << ls.getName().toText();
- EXPECT_EQ(expected_len, ls.getDataLength()) <<
- "Expected data: " << expected_data <<
- " name: " << ls.getName().toText();
- for (size_t i = 0; i < len; ++i) {
- EXPECT_EQ(expected_data[i], data[i]) <<
- "Difference at pos " << i << ": Expected data: " << expected_data <<
- " name: " << ls.getName().toText();;
- }
- }
- // Convenient data converter for expected data. Label data must be of
- // uint8_t*, while it's convenient if we can specify some test data in
- // plain string (which is of char*). This wrapper converts the latter to
- // the former in a safer way.
- void
- getDataCheck(const char* expected_char_data, size_t expected_len,
- const LabelSequence& ls)
- {
- const vector<uint8_t> expected_data(expected_char_data,
- expected_char_data + expected_len);
- getDataCheck(&expected_data[0], expected_len, ls);
- }
- TEST_F(LabelSequenceTest, getData) {
- getDataCheck("\007example\003org\000", 13, ls1);
- getDataCheck("\007example\003com\000", 13, ls2);
- getDataCheck("\007example\003org\000", 13, ls3);
- getDataCheck("\003foo\003bar\004test\007example\000", 22, ls4);
- getDataCheck("\007example\003ORG\000", 13, ls5);
- getDataCheck("\007ExAmPlE\003org\000", 13, ls6);
- getDataCheck("\000", 1, ls7);
- };
- TEST_F(LabelSequenceTest, stripLeft) {
- EXPECT_TRUE(ls1.equals(ls3));
- ls1.stripLeft(0);
- getDataCheck("\007example\003org\000", 13, ls1);
- EXPECT_TRUE(ls1.equals(ls3));
- ls1.stripLeft(1);
- getDataCheck("\003org\000", 5, ls1);
- EXPECT_FALSE(ls1.equals(ls3));
- ls1.stripLeft(1);
- getDataCheck("\000", 1, ls1);
- EXPECT_TRUE(ls1.equals(ls7));
- ls2.stripLeft(2);
- getDataCheck("\000", 1, ls2);
- EXPECT_TRUE(ls2.equals(ls7));
- }
- TEST_F(LabelSequenceTest, stripRight) {
- EXPECT_TRUE(ls1.equals(ls3));
- ls1.stripRight(1);
- getDataCheck("\007example\003org", 12, ls1);
- EXPECT_FALSE(ls1.equals(ls3));
- ls1.stripRight(1);
- getDataCheck("\007example", 8, ls1);
- EXPECT_FALSE(ls1.equals(ls3));
- ASSERT_FALSE(ls1.equals(ls2));
- ls2.stripRight(2);
- getDataCheck("\007example", 8, ls2);
- EXPECT_TRUE(ls1.equals(ls2));
- }
- TEST_F(LabelSequenceTest, stripOutOfRange) {
- EXPECT_THROW(ls1.stripLeft(100), isc::OutOfRange);
- EXPECT_THROW(ls1.stripLeft(5), isc::OutOfRange);
- EXPECT_THROW(ls1.stripLeft(4), isc::OutOfRange);
- EXPECT_THROW(ls1.stripLeft(3), isc::OutOfRange);
- getDataCheck("\007example\003org\000", 13, ls1);
- EXPECT_THROW(ls1.stripRight(100), isc::OutOfRange);
- EXPECT_THROW(ls1.stripRight(5), isc::OutOfRange);
- EXPECT_THROW(ls1.stripRight(4), isc::OutOfRange);
- EXPECT_THROW(ls1.stripRight(3), isc::OutOfRange);
- getDataCheck("\007example\003org\000", 13, ls1);
- }
- TEST_F(LabelSequenceTest, getLabelCount) {
- EXPECT_EQ(3, ls1.getLabelCount());
- ls1.stripLeft(0);
- EXPECT_EQ(3, ls1.getLabelCount());
- ls1.stripLeft(1);
- EXPECT_EQ(2, ls1.getLabelCount());
- ls1.stripLeft(1);
- EXPECT_EQ(1, ls1.getLabelCount());
- EXPECT_EQ(3, ls2.getLabelCount());
- ls2.stripRight(1);
- EXPECT_EQ(2, ls2.getLabelCount());
- ls2.stripRight(1);
- EXPECT_EQ(1, ls2.getLabelCount());
- EXPECT_EQ(3, ls3.getLabelCount());
- ls3.stripRight(2);
- EXPECT_EQ(1, ls3.getLabelCount());
- EXPECT_EQ(5, ls4.getLabelCount());
- ls4.stripRight(3);
- EXPECT_EQ(2, ls4.getLabelCount());
- EXPECT_EQ(3, ls5.getLabelCount());
- ls5.stripLeft(2);
- EXPECT_EQ(1, ls5.getLabelCount());
- }
- TEST_F(LabelSequenceTest, comparePart) {
- EXPECT_FALSE(ls1.equals(ls8));
- // strip root label from example.org.
- ls1.stripRight(1);
- // strip foo from foo.example.org.bar.
- ls8.stripLeft(1);
- // strip bar. (i.e. bar and root) too
- ls8.stripRight(2);
- EXPECT_TRUE(ls1.equals(ls8));
- // Data comparison
- size_t len;
- const uint8_t* data = ls1.getData(&len);
- getDataCheck(data, len, ls8);
- }
- TEST_F(LabelSequenceTest, isAbsolute) {
- ASSERT_TRUE(ls1.isAbsolute());
- ls1.stripLeft(1);
- ASSERT_TRUE(ls1.isAbsolute());
- ls1.stripRight(1);
- ASSERT_FALSE(ls1.isAbsolute());
- ASSERT_TRUE(ls2.isAbsolute());
- ls2.stripRight(1);
- ASSERT_FALSE(ls2.isAbsolute());
- ASSERT_TRUE(ls3.isAbsolute());
- ls3.stripLeft(2);
- ASSERT_TRUE(ls3.isAbsolute());
- }
- TEST_F(LabelSequenceTest, toText) {
- EXPECT_EQ("example.org.", ls1.toText());
- ls1.stripLeft(1);
- EXPECT_EQ("org.", ls1.toText());
- ls1.stripLeft(1);
- EXPECT_EQ(".", ls1.toText());
- EXPECT_EQ("example.com.", ls2.toText());
- ls2.stripRight(1);
- EXPECT_EQ("example", ls2.toText());
- ls2.stripRight(1);
- EXPECT_EQ("", ls2.toText());
- EXPECT_EQ("foo.example.org.bar.", ls8.toText());
- ls8.stripRight(2);
- EXPECT_EQ("foo.example", ls8.toText());
- EXPECT_EQ(".", ls7.toText());
- EXPECT_THROW(ls7.stripLeft(1), isc::OutOfRange);
- }
- // The following are test data used in the getHash test below. Normally
- // we use example/documentation domain names for testing, but in this case
- // we'd specifically like to use more realistic data, and are intentionally
- // using real-world samples: They are the NS names of root and some top level
- // domains as of this test.
- const char* const root_servers[] = {
- "a.root-servers.net", "b.root-servers.net", "c.root-servers.net",
- "d.root-servers.net", "e.root-servers.net", "f.root-servers.net",
- "g.root-servers.net", "h.root-servers.net", "i.root-servers.net",
- "j.root-servers.net", "k.root-servers.net", "l.root-servers.net",
- "m.root-servers.net", NULL
- };
- const char* const gtld_servers[] = {
- "a.gtld-servers.net", "b.gtld-servers.net", "c.gtld-servers.net",
- "d.gtld-servers.net", "e.gtld-servers.net", "f.gtld-servers.net",
- "g.gtld-servers.net", "h.gtld-servers.net", "i.gtld-servers.net",
- "j.gtld-servers.net", "k.gtld-servers.net", "l.gtld-servers.net",
- "m.gtld-servers.net", NULL
- };
- const char* const jp_servers[] = {
- "a.dns.jp", "b.dns.jp", "c.dns.jp", "d.dns.jp", "e.dns.jp",
- "f.dns.jp", "g.dns.jp", NULL
- };
- const char* const cn_servers[] = {
- "a.dns.cn", "b.dns.cn", "c.dns.cn", "d.dns.cn", "e.dns.cn",
- "ns.cernet.net", NULL
- };
- const char* const ca_servers[] = {
- "k.ca-servers.ca", "e.ca-servers.ca", "a.ca-servers.ca", "z.ca-servers.ca",
- "tld.isc-sns.net", "c.ca-servers.ca", "j.ca-servers.ca", "l.ca-servers.ca",
- "sns-pb.isc.org", "f.ca-servers.ca", NULL
- };
- // A helper function used in the getHash test below.
- void
- hashDistributionCheck(const char* const* servers) {
- const size_t BUCKETS = 64; // constant used in the MessageRenderer
- set<Name> names;
- vector<size_t> hash_counts(BUCKETS);
- // Store all test names and their super domain names (excluding the
- // "root" label) in the set, calculates their hash values, and increments
- // the counter for the corresponding hash "bucket".
- for (size_t i = 0; servers[i] != NULL; ++i) {
- const Name name(servers[i]);
- for (size_t l = 0; l < name.getLabelCount() - 1; ++l) {
- pair<set<Name>::const_iterator, bool> ret =
- names.insert(name.split(l));
- if (ret.second) {
- hash_counts[LabelSequence((*ret.first)).getHash(false) %
- BUCKETS]++;
- }
- }
- }
- // See how many conflicts we have in the buckets. For the testing purpose
- // we expect there's at most 2 conflicts in each set, which is an
- // arbitrary choice (it should happen to succeed with the hash function
- // and data we are using; if it's not the case, maybe with an update to
- // the hash implementation, we should revise the test).
- for (size_t i = 0; i < BUCKETS; ++i) {
- EXPECT_GE(3, hash_counts[i]);
- }
- }
- TEST_F(LabelSequenceTest, getHash) {
- // Trivial case. The same sequence should have the same hash.
- EXPECT_EQ(ls1.getHash(true), ls1.getHash(true));
- // Check the case-insensitive mode behavior.
- EXPECT_EQ(ls1.getHash(false), ls5.getHash(false));
- // Check that the distribution of hash values is "not too bad" (such as
- // everything has the same hash value due to a stupid bug). It's
- // difficult to check such things reliably. We do some ad hoc tests here.
- hashDistributionCheck(root_servers);
- hashDistributionCheck(jp_servers);
- hashDistributionCheck(cn_servers);
- hashDistributionCheck(ca_servers);
- }
- // test operator<<. We simply confirm it appends the result of toText().
- TEST_F(LabelSequenceTest, LeftShiftOperator) {
- ostringstream oss;
- oss << ls1;
- EXPECT_EQ(ls1.toText(), oss.str());
- }
- }
|