1 // Copyright (C) 2012-2020 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 #include <config.h>
8 #include "test_utils.h"
9 #include <asiolink/io_address.h>
10 #include <gtest/gtest.h>
11 #include <sstream>
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <unistd.h>
15 
16 using namespace std;
17 using namespace isc::asiolink;
18 
19 namespace isc {
20 namespace dhcp {
21 namespace test {
22 
23 void
detailCompareLease(const Lease4Ptr & first,const Lease4Ptr & second)24 detailCompareLease(const Lease4Ptr& first, const Lease4Ptr& second) {
25     // Compare address strings.  Comparison of address objects is not used, as
26     // odd things happen when they are different: the EXPECT_EQ macro appears to
27     // call the operator uint32_t() function, which causes an exception to be
28     // thrown for IPv6 addresses.
29     ASSERT_TRUE(first);
30     ASSERT_TRUE(second);
31     EXPECT_EQ(first->addr_, second->addr_);
32 
33     // We need to compare the actual HWAddr objects, not pointers
34     EXPECT_TRUE(*first->hwaddr_ == *second->hwaddr_);
35 
36     if (first->client_id_ && second->client_id_) {
37         EXPECT_TRUE(*first->client_id_ == *second->client_id_);
38     } else {
39         if (first->client_id_ && !second->client_id_) {
40 
41             ADD_FAILURE() << "Client-id present in first lease ("
42                           << first->client_id_->getClientId().size()
43                           << " bytes), but missing in second.";
44         }
45         if (!first->client_id_ && second->client_id_) {
46             ADD_FAILURE() << "Client-id missing in first lease, but present in second ("
47                           << second->client_id_->getClientId().size()
48                           << " bytes).";
49         }
50         // else here would mean that both leases do not have client_id_
51         // which makes them equal in that regard. It is ok.
52     }
53     EXPECT_EQ(first->valid_lft_, second->valid_lft_);
54     EXPECT_EQ(first->cltt_, second->cltt_);
55     EXPECT_EQ(first->subnet_id_, second->subnet_id_);
56     EXPECT_EQ(first->fqdn_fwd_, second->fqdn_fwd_);
57     EXPECT_EQ(first->fqdn_rev_, second->fqdn_rev_);
58     EXPECT_EQ(first->hostname_, second->hostname_);
59     if (first->getContext()) {
60         EXPECT_TRUE(second->getContext());
61         if (second->getContext()) {
62             EXPECT_EQ(first->getContext()->str(), second->getContext()->str());
63         }
64     } else {
65         EXPECT_FALSE(second->getContext());
66     }
67 }
68 
69 void
detailCompareLease(const Lease6Ptr & first,const Lease6Ptr & second)70 detailCompareLease(const Lease6Ptr& first, const Lease6Ptr& second) {
71     ASSERT_TRUE(first);
72     ASSERT_TRUE(second);
73     EXPECT_EQ(first->type_, second->type_);
74 
75     // Compare address strings.  Comparison of address objects is not used, as
76     // odd things happen when they are different: the EXPECT_EQ macro appears to
77     // call the operator uint32_t() function, which causes an exception to be
78     // thrown for IPv6 addresses.
79     EXPECT_EQ(first->addr_, second->addr_);
80     EXPECT_EQ(first->prefixlen_, second->prefixlen_);
81     EXPECT_EQ(first->iaid_, second->iaid_);
82     ASSERT_TRUE(first->duid_);
83     ASSERT_TRUE(second->duid_);
84     EXPECT_TRUE(*first->duid_ == *second->duid_);
85     EXPECT_EQ(first->preferred_lft_, second->preferred_lft_);
86     EXPECT_EQ(first->valid_lft_, second->valid_lft_);
87     EXPECT_EQ(first->cltt_, second->cltt_);
88     EXPECT_EQ(first->subnet_id_, second->subnet_id_);
89     EXPECT_EQ(first->fqdn_fwd_, second->fqdn_fwd_);
90     EXPECT_EQ(first->fqdn_rev_, second->fqdn_rev_);
91     EXPECT_EQ(first->hostname_, second->hostname_);
92     if (first->getContext()) {
93         EXPECT_TRUE(second->getContext());
94         if (second->getContext()) {
95             EXPECT_EQ(first->getContext()->str(), second->getContext()->str());
96         }
97     } else {
98         EXPECT_FALSE(second->getContext());
99     }
100 }
101 
findLastSocketFd()102 int findLastSocketFd() {
103     int max_fd_number = getdtablesize();
104     int last_socket = -1;
105     struct stat stats;
106 
107     // Iterate over the open fds
108     for (int fd = 0; fd <= max_fd_number; fd++ ) {
109         errno = 0;
110         fstat(fd, &stats);
111 
112         if (errno == EBADF ) {
113             // Skip any that aren't open
114             continue;
115         }
116 
117         // it's a socket, remember it
118         if (S_ISSOCK(stats.st_mode)) {
119             last_socket = fd;
120         }
121     }
122 
123     return (last_socket);
124 }
125 
FillFdHoles(int limit)126 FillFdHoles::FillFdHoles(int limit) : fds_() {
127     if (limit <= 0) {
128         return;
129     }
130     for (;;) {
131         int fd = open("/dev/null", O_RDWR, 0);
132         if (fd == -1) {
133             return;
134         }
135         if (fd < limit) {
136             fds_.push_front(fd);
137         } else {
138             static_cast<void>(close(fd));
139             return;
140         }
141     }
142 }
143 
~FillFdHoles()144 FillFdHoles::~FillFdHoles() {
145     while (!fds_.empty()) {
146         static_cast<void>(close(fds_.back()));
147         fds_.pop_back();
148     }
149 }
150 
151 } // namespace test
152 } // namespace dhcp
153 } // namespace isc
154