aboutsummaryrefslogtreecommitdiffstats
path: root/metis/ccnx/forwarder/metis/core/test/testrig_MetisIoOperations.h
blob: 80735862b49212d1646714f9cbe668be8fa5b3dd (plain)
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
/*
 * Copyright (c) 2017 Cisco and/or its affiliates.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef Metis_testrig_MetisIoOperations_h
#define Metis_testrig_MetisIoOperations_h

/**
 * Setup a test rig around a MetisIoOperation so we have visibility in to
 * what the connection table is doing
 *
 * Usage: Use <code>mockIoOperationsData_Create()</code> or <code>mockIoOperationsData_CreateSimple()</code>
 *        to create the MetisIoOperations.  You can then inspect the TestData inside the context
 *        by mapping <code>TestData *data = (TestData *) metisIoOperations_GetClosure(ops)</code>.
 *
 * IMPORTANT: ops->destroy(&ops) will not destroy the test rig.  It will increment a counter.
 *            you must call <code>testdata_Destroy(&ops)</code> yourself.  You should call this
 *            as the very last thing, even after <code>metisForwarder_Destroy()</code>, if you put
 *            the MetisIoOpereations in the connection table.
 */
static bool                     mockIoOperations_Send(MetisIoOperations *ops, const CPIAddress *nexthop, MetisMessage *message);
static const CPIAddress        *mockIoOperations_GetRemoteAddress(const MetisIoOperations *ops);
static const MetisAddressPair  *mockIoOperations_GetAddressPair(const MetisIoOperations *ops);
static bool                     mockIoOperations_IsUp(const MetisIoOperations *ops);
static bool                     mockIoOperations_IsLocal(const MetisIoOperations *ops);
static unsigned                 mockIoOperations_GetConnectionId(const MetisIoOperations *ops);
static void                     mockIoOperations_Destroy(MetisIoOperations **opsPtr);
static CPIConnectionType        mockIoOperations_GetConnectionType(const MetisIoOperations *ops);
static const void *mockIoOperations_Class(const MetisIoOperations *ops);

static MetisIoOperations mockIoOperationsTemplate = {
    .closure           = NULL,
    .send              = &mockIoOperations_Send,
    .getRemoteAddress  = &mockIoOperations_GetRemoteAddress,
    .getAddressPair    = &mockIoOperations_GetAddressPair,
    .isUp              = &mockIoOperations_IsUp,
    .isLocal           = &mockIoOperations_IsLocal,
    .getConnectionId   = &mockIoOperations_GetConnectionId,
    .destroy           = &mockIoOperations_Destroy,
    .getConnectionType = &mockIoOperations_GetConnectionType,
    .class             = &mockIoOperations_Class
};

typedef struct mock_io_operations_data {
    // counters for each call
    unsigned sendCount;
    unsigned getRemoteAddressCount;
    unsigned getAddressPairCount;
    unsigned isUpCount;
    unsigned isLocalCount;
    unsigned getConnectionIdCount;
    unsigned destroyCount;
    unsigned getConnectionTypeCount;
    unsigned classCount;

    MetisMessage *lastMessage;
    MetisAddressPair *addressPair;
    unsigned id;
    bool isUp;
    bool isLocal;
    bool sendResult;                // what to return when send() called
    CPIConnectionType connType;
} MockIoOperationsData;

/**
 * @function testdata_Create
 * @abstract Creates a data set for testing MetisIoOperations
 * @discussion
 *   Caller must explicitly use <code>testdata_Destroy()</code> when done.  Calling the destroyer through
 *   the io operations only increments counters, it does not destroy the object.
 *
 * @param <#param1#>
 * @return <#return#>
 */
static MetisIoOperations *
mockIoOperationsData_Create(MetisAddressPair *pair, unsigned id, bool isUp, bool sendResult, bool isLocal, CPIConnectionType connType)
{
    MockIoOperationsData *data = parcMemory_AllocateAndClear(sizeof(MockIoOperationsData));
    data->addressPair = pair;
    data->id = id;
    data->isUp = isUp;
    data->sendResult = sendResult;
    data->lastMessage = NULL;
    data->isLocal = isLocal;
    data->connType = connType;

    MetisIoOperations *ops = parcMemory_AllocateAndClear(sizeof(MetisIoOperations));
    memcpy(ops, &mockIoOperationsTemplate, sizeof(MetisIoOperations));
    ops->closure = data;

    return ops;
}

/**
 * @function testdata_CreateSimple
 * @abstract Creates a data set for testing MetisIoOperations
 * @discussion
 *   Caller must explicitly use <code>testdata_Destroy()</code> when done.  Calling the destroyer through
 *   the io operations only increments counters, it does not destroy the object.
 *
 * @param <#param1#>
 * @return <#return#>
 */
static MetisIoOperations *
mockIoOperationsData_CreateSimple(unsigned addressLocal, unsigned addressRemote, unsigned id, bool isUp, bool sendResult, bool isLocal)
{
    CPIAddress *local = cpiAddress_CreateFromInterface(addressLocal);
    CPIAddress *remote = cpiAddress_CreateFromInterface(addressRemote);
    MetisAddressPair *pair = metisAddressPair_Create(local, remote);
    MetisIoOperations *ops = mockIoOperationsData_Create(pair, id, isUp, sendResult, isLocal, cpiConnection_UDP);
    cpiAddress_Destroy(&local);
    cpiAddress_Destroy(&remote);
    return ops;
}

static void
mockIoOperationsData_Destroy(MetisIoOperations **opsPtr)
{
    MetisIoOperations *ops = *opsPtr;
    MockIoOperationsData *data = (MockIoOperationsData *) metisIoOperations_GetClosure(ops);

    metisAddressPair_Release(&data->addressPair);
    if (data->lastMessage) {
        metisMessage_Release(&data->lastMessage);
    }
    parcMemory_Deallocate((void **) &data);
    ops->closure = NULL;
    parcMemory_Deallocate((void **) &ops);
    *opsPtr = NULL;
}

static bool
mockIoOperations_Send(MetisIoOperations *ops, const CPIAddress *nexthop, MetisMessage *message)
{
    MockIoOperationsData *data = (MockIoOperationsData *) metisIoOperations_GetClosure(ops);
    data->sendCount++;

    if (message) {
        if (data->lastMessage) {
            metisMessage_Release(&data->lastMessage);
        }

        data->lastMessage = metisMessage_Acquire(message);
    }

    return data->sendResult;
}

static const CPIAddress *
mockIoOperations_GetRemoteAddress(const MetisIoOperations *ops)
{
    MockIoOperationsData *data = (MockIoOperationsData *) metisIoOperations_GetClosure(ops);
    data->getRemoteAddressCount++;
    return metisAddressPair_GetRemote(data->addressPair);
}

static const MetisAddressPair *
mockIoOperations_GetAddressPair(const MetisIoOperations *ops)
{
    MockIoOperationsData *data = (MockIoOperationsData *) metisIoOperations_GetClosure(ops);
    data->getAddressPairCount++;
    return data->addressPair;
}

static bool
mockIoOperations_IsUp(const MetisIoOperations *ops)
{
    MockIoOperationsData *data = (MockIoOperationsData *) metisIoOperations_GetClosure(ops);
    data->isUpCount++;
    return data->isUp;
}

static bool
mockIoOperations_IsLocal(const MetisIoOperations *ops)
{
    MockIoOperationsData *data = (MockIoOperationsData *) metisIoOperations_GetClosure(ops);
    data->isLocalCount++;
    return data->isLocal;
}


static unsigned
mockIoOperations_GetConnectionId(const MetisIoOperations *ops)
{
    MockIoOperationsData *data = (MockIoOperationsData *) metisIoOperations_GetClosure(ops);
    data->getConnectionIdCount++;
    return data->id;
}

static void
mockIoOperations_Destroy(MetisIoOperations **opsPtr)
{
    MockIoOperationsData *data = (MockIoOperationsData *) (*opsPtr)->closure;
    data->destroyCount++;
    *opsPtr = NULL;
}

static CPIConnectionType
mockIoOperations_GetConnectionType(const MetisIoOperations *ops)
{
    MockIoOperationsData *data = (MockIoOperationsData *) metisIoOperations_GetClosure(ops);
    data->getConnectionTypeCount++;
    return data->connType;
}

static const void *
mockIoOperations_Class(const MetisIoOperations *ops)
{
    MockIoOperationsData *data = (MockIoOperationsData *) metisIoOperations_GetClosure(ops);
    data->classCount++;
    return __FILE__;
}
#endif // Metis_testrig_MetisIoOperations_h