1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
|
// Copyright (C) 2012-2017 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <config.h>
#include <asiolink/io_address.h>
#include <dhcpsrv/lease_mgr.h>
#include <dhcpsrv/memfile_lease_mgr.h>
#include <dhcpsrv/tests/test_utils.h>
#include <dhcpsrv/tests/generic_lease_mgr_unittest.h>
#include <gtest/gtest.h>
#include <iostream>
#include <sstream>
#include <time.h>
using namespace std;
using namespace isc;
using namespace isc::asiolink;
using namespace isc::dhcp;
using namespace isc::dhcp::test;
// This is a concrete implementation of a Lease database. It does not do
// anything useful and is used for abstract LeaseMgr class testing.
class ConcreteLeaseMgr : public LeaseMgr {
public:
/// @brief The sole lease manager constructor
///
/// dbconfig is a generic way of passing parameters. Parameters
/// are passed in the "name=value" format, separated by spaces.
/// Values may be enclosed in double quotes, if needed.
ConcreteLeaseMgr(const DatabaseConnection::ParameterMap&)
: LeaseMgr()
{}
/// @brief Destructor
virtual ~ConcreteLeaseMgr()
{}
/// @brief Adds an IPv4 lease.
///
/// @param lease lease to be added
virtual bool addLease(const Lease4Ptr&) {
return (false);
}
/// @brief Adds an IPv6 lease.
///
/// @param lease lease to be added
virtual bool addLease(const Lease6Ptr&) {
return (false);
}
/// @brief Returns existing IPv4 lease for specified IPv4 address.
///
/// @param addr address of the searched lease
///
/// @return smart pointer to the lease (or NULL if a lease is not found)
virtual Lease4Ptr getLease4(const isc::asiolink::IOAddress&) const {
return (Lease4Ptr());
}
/// @brief Returns existing IPv4 leases for specified hardware address.
///
/// Although in the usual case there will be only one lease, for mobile
/// clients or clients with multiple static/fixed/reserved leases there
/// can be more than one. Thus return type is a container, not a single
/// pointer.
///
/// @param hwaddr hardware address of the client
///
/// @return lease collection
virtual Lease4Collection getLease4(const HWAddr&) const {
return (Lease4Collection());
}
/// @brief Returns existing IPv4 leases for specified hardware address
/// and a subnet
///
/// There can be at most one lease for a given HW address in a single
/// pool, so this method with either return a single lease or NULL.
///
/// @param hwaddr hardware address of the client
/// @param subnet_id identifier of the subnet that lease must belong to
///
/// @return a pointer to the lease (or NULL if a lease is not found)
virtual Lease4Ptr getLease4(const HWAddr&, SubnetID) const {
return (Lease4Ptr());
}
/// @brief Returns existing IPv4 lease for specified client-id
///
/// @param clientid client identifier
///
/// @return lease collection
virtual Lease4Collection getLease4(const ClientId&) const {
return (Lease4Collection());
}
/// @brief Returns existing IPv4 lease for specified client identifier,
/// HW address and subnet identifier.
///
/// @param client_id Aclient identifier
/// @param hwaddr A HW address.
/// @param subnet_id A subnet identifier.
///
/// @return A pointer to an existing lease or NULL if lease not found.
virtual Lease4Ptr
getLease4(const ClientId&, const HWAddr&, SubnetID) const {
return (Lease4Ptr());
}
/// @brief Returns existing IPv4 lease for specified client-id
///
/// There can be at most one lease for a given HW address in a single
/// pool, so this method with either return a single lease or NULL.
///
/// @param clientid client identifier
/// @param subnet_id identifier of the subnet that lease must belong to
///
/// @return a pointer to the lease (or NULL if a lease is not found)
virtual Lease4Ptr getLease4(const ClientId&, SubnetID) const {
return (Lease4Ptr());
}
/// @brief Returns existing IPv6 lease for a given IPv6 address.
///
/// @param addr address of the searched lease
///
/// @return smart pointer to the lease (or NULL if a lease is not found)
virtual Lease6Ptr getLease6(Lease::Type /* not used yet */,
const isc::asiolink::IOAddress&) const {
return (Lease6Ptr());
}
/// @brief Returns existing IPv6 lease for a given DUID+IA combination
///
/// @param duid ignored
/// @param iaid ignored
///
/// @return whatever is set in leases6_ field
virtual Lease6Collection getLeases6(Lease::Type /* not used yet */,
const DUID&, uint32_t) const {
return (leases6_);
}
/// @brief Returns existing IPv6 lease for a given DUID+IA+subnet-id combination
///
/// @param duid ignored
/// @param iaid ignored
/// @param subnet_id ignored
///
/// @return whatever is set in leases6_ field
virtual Lease6Collection getLeases6(Lease::Type /* not used yet */,
const DUID&, uint32_t, SubnetID) const {
return (leases6_);
}
/// @brief Returns expired DHCPv6 leases.
///
/// This method is not implemented.
virtual void getExpiredLeases6(Lease6Collection&, const size_t) const {
isc_throw(NotImplemented, "ConcreteLeaseMgr::getExpiredLeases6 is not"
" implemented");
}
/// @brief Returns expired DHCPv4 leases.
///
/// This method is not implemented.
virtual void getExpiredLeases4(Lease4Collection&, const size_t) const {
isc_throw(NotImplemented, "ConcreteLeaseMgr::getExpiredLeases4 is not"
" implemented");
}
/// @brief Updates IPv4 lease.
///
/// @param lease4 The lease to be updated.
///
/// If no such lease is present, an exception will be thrown.
virtual void updateLease4(const Lease4Ptr&) {}
/// @brief Updates IPv4 lease.
///
/// @param lease4 The lease to be updated.
///
/// If no such lease is present, an exception will be thrown.
virtual void updateLease6(const Lease6Ptr&) {}
/// @brief Deletes a lease.
///
/// @param addr Address of the lease to be deleted. (This can be either
/// a V4 address or a V6 address.)
///
/// @return true if deletion was successful, false if no such lease exists
virtual bool deleteLease(const isc::asiolink::IOAddress&) {
return (false);
}
/// @brief Deletes all expired and reclaimed DHCPv4 leases.
///
/// @param secs Number of seconds since expiration of leases before
/// they can be removed. Leases which have expired later than this
/// time will not be deleted.
virtual uint64_t deleteExpiredReclaimedLeases4(const uint32_t) {
isc_throw(NotImplemented, "ConcreteLeaseMgr::deleteExpiredReclaimedLeases4"
" is not implemented");
}
/// @brief Deletes all expired and reclaimed DHCPv6 leases.
///
/// @param secs Number of seconds since expiration of leases before
/// they can be removed. Leases which have expired later than this
/// time will not be deleted.
virtual uint64_t deleteExpiredReclaimedLeases6(const uint32_t) {
isc_throw(NotImplemented, "ConcreteLeaseMgr::deleteExpiredReclaimedLeases6"
" is not implemented");
}
/// @brief Pretends to wipe all IPv4 leases from a subnet
/// @param subnet_id (ignored, but one day may specify the subnet)
virtual size_t wipeLeases4(const SubnetID&) {
isc_throw(NotImplemented, "ConreteLeaseMgr::wipeLeases4 not implemented");
}
/// @brief Pretends to wipe all IPv4 leases from a subnet
/// @param subnet_id (ignored, but one day may specify the subnet)
virtual size_t wipeLeases6(const SubnetID&) {
isc_throw(NotImplemented, "ConreteLeaseMgr::wipeLeases4 not implemented");
}
/// @brief Returns backend type.
///
/// Returns the type of the backend (e.g. "mysql", "memfile" etc.)
///
/// @return Type of the backend.
virtual std::string getType() const {
return (std::string("concrete"));
}
/// @brief Returns backend name.
///
/// If the backend is a database, this is the name of the database or the
/// file. Otherwise it is just the same as the type.
///
/// @return Name of the backend.
virtual std::string getName() const {
return (std::string("concrete"));
}
/// @brief Returns description of the backend.
///
/// This description may be multiline text that describes the backend.
///
/// @return Description of the backend.
virtual std::string getDescription() const {
return (std::string("This is a dummy concrete backend implementation."));
}
/// @brief Returns backend version.
virtual std::pair<uint32_t, uint32_t> getVersion() const {
return (make_pair(uint32_t(0), uint32_t(0)));
}
/// @brief Commit transactions
virtual void commit() {
}
/// @brief Rollback transactions
virtual void rollback() {
}
// We need to use it in ConcreteLeaseMgr
using LeaseMgr::getLease6;
Lease6Collection leases6_; ///< getLease6 methods return this as is
};
class LeaseMgrTest : public GenericLeaseMgrTest {
public:
LeaseMgrTest() {
}
/// @brief Reopen the database
///
/// No-op implementation. We need to provide concrete implementation,
/// as this is a pure virtual method in GenericLeaseMgrTest.
virtual void reopen(Universe) {
}
};
namespace {
// This test checks if getLease6() method is working properly for 0 (NULL),
// 1 (return the lease) and more than 1 leases (throw).
TEST_F(LeaseMgrTest, getLease6) {
DatabaseConnection::ParameterMap pmap;
boost::scoped_ptr<ConcreteLeaseMgr> mgr(new ConcreteLeaseMgr(pmap));
vector<Lease6Ptr> leases = createLeases6();
mgr->leases6_.clear();
// For no leases, the function should return NULL pointer
Lease6Ptr lease;
// the getLease6() is calling getLeases6(), which is a dummy. It returns
// whatever is there in leases6_ field.
EXPECT_NO_THROW(lease = mgr->getLease6(leasetype6_[1], *leases[1]->duid_,
leases[1]->iaid_,
leases[1]->subnet_id_));
EXPECT_TRUE(Lease6Ptr() == lease);
// For a single lease, the function should return that lease
mgr->leases6_.push_back(leases[1]);
EXPECT_NO_THROW(lease = mgr->getLease6(leasetype6_[1], *leases[1]->duid_,
leases[1]->iaid_,
leases[1]->subnet_id_));
EXPECT_TRUE(lease);
EXPECT_NO_THROW(detailCompareLease(lease, leases[1]));
// Add one more lease. There are 2 now. It should throw
mgr->leases6_.push_back(leases[2]);
EXPECT_THROW(lease = mgr->getLease6(leasetype6_[1], *leases[1]->duid_,
leases[1]->iaid_,
leases[1]->subnet_id_),
MultipleRecords);
}
// There's no point in calling any other methods in LeaseMgr, as they
// are purely virtual, so we would only call ConcreteLeaseMgr methods.
// Those methods are just stubs that do not return anything.
}; // end of anonymous namespace
|