aboutsummaryrefslogtreecommitdiffstats
path: root/libparc/parc/testing/parc_ObjectTesting.c
blob: 03fe22221e323e0d16b85904037a7b0157248d37 (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
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
/*
 * 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.
 */

/**
 */
#include <config.h>
#include <LongBow/runtime.h>
#include <inttypes.h>

#include <parc/testing/parc_ObjectTesting.h>
#include <parc/algol/parc_HashCode.h>
#include <parc/algol/parc_Memory.h>

void
parcObjectTesting_AssertAcquireReleaseContractImpl(void *(acquireFunction)(const PARCObject *), const PARCObject *instance)
{
    void *reference = acquireFunction(instance);
    assertTrue(reference == instance, "Expected the acquire function to return the same instance pointer.");
    parcObject_Release(&reference);
    parcObjectTesting_AssertAcquireReleaseImpl(instance);
}

void
parcObjectTesting_AssertAcquireReleaseImpl(const PARCObject *instance)
{
    PARCReferenceCount originalReferences = parcObject_GetReferenceCount(instance);

    PARCObject *newReference = parcObject_Acquire(instance);

    assertTrue(newReference == instance, "Expected the acquire function to return the same instance pointer.");

    PARCReferenceCount currentReferences = parcObject_GetReferenceCount(instance);
    assertTrue(currentReferences == (originalReferences + 1),
               "Expected references to be %" PRIu64 ", actual %" PRIu64, (originalReferences + 1), currentReferences);

    parcObject_Release(&newReference);
    currentReferences = parcObject_GetReferenceCount(instance);
    assertTrue(currentReferences == originalReferences,
               "Expected references to be %" PRIu64 ", actual %" PRIu64, originalReferences, currentReferences);
}

static void
_parcObjectTesting_AssertEquals(bool (*equalsFunction)(const void *a, const void *b), const void *x, const void *y, const void *z, va_list ap)
{
    assertNotNull(x, "The value of x cannot be NULL.");
    assertNotNull(y, "The value of y cannot be NULL.");
    assertNotNull(z, "The value of z cannot be NULL.");

    assertFalse(x == y, "The value x cannot be the same as y");
    assertFalse(x == z, "The value x cannot be the same as z");
    assertFalse(y == z, "The value y cannot be the same as z");

    assertTrue(equalsFunction(NULL, NULL), "Equality failed: Equals(NULL, NULL) must be true");

    assertFalse(equalsFunction(x, NULL), "Equality failed: The value of x must not be Equal to NULL.");
    assertFalse(equalsFunction(NULL, x), "Equality failed: NULL must not be equal to the value of x.");

    assertTrue(equalsFunction(x, x), "Reflexive failed: for any non-null reference value x, equals(x, x) must return true.");

    assertTrue(equalsFunction(x, y), "Equality failed: The values of x and y must be Equal.");
    assertTrue(equalsFunction(x, z), "Equality failed: The values of x and z must be Equal.");

    assertTrue(equalsFunction(x, y) == equalsFunction(y, x), "Symmetric equality failed: equals(x, y) == equals(y, x) must true.");

    assertTrue((equalsFunction(x, y) == equalsFunction(y, z)) == equalsFunction(z, x),
               "Transitive equality failed: equals(x, y) == equals(y, z) == equals(z, x) must true.");

    int index = 0;
    for (void *value = va_arg(ap, void *); value != 0; value = va_arg(ap, void *)) {
        assertFalse(equalsFunction(x, value), "Value %d (@%p) must not be equal to x", index, value);
        assertTrue(equalsFunction(x, value) == equalsFunction(value, x),
                   "Symmetric equality failed: equals(x, value) == equals(value, x) must true.");
        index++;
    }
}

void
parcObjectTesting_AssertEquals(const PARCObject *x, const void *y, const void *z, ...)
{
    va_list ap;
    va_start(ap, z);

    _parcObjectTesting_AssertEquals((bool (*)(const void *, const void *))parcObject_Equals, x, y, z, ap);

    assertTrue(parcObject_HashCode(x) == parcObject_HashCode(y),
               "HashCode of x and y must be equal");
    assertTrue(parcObject_HashCode(x) == parcObject_HashCode(z),
               "HashCode of x and z must be equal");

    va_end(ap);
}

void
parcObjectTesting_AssertEqualsFunctionImpl(bool (*equalsFunction)(const void *a, const void *b), const void *x, const void *y, const void *z, ...)
{
    va_list ap;
    va_start(ap, z);
    _parcObjectTesting_AssertEquals(equalsFunction, x, y, z, ap);

    va_end(ap);
}

bool
parcObjectTesting_AssertCompareToImpl(int (*compareTo)(const void *a, const void *b),
                                      const void *exemplar,
                                      const void **equivalent,
                                      const void **lesser,
                                      const void **greater)
{
    assertNotNull(exemplar, "Parameter exemplar must not be NULL");
    assertNotNull(equivalent, "Parameter equivalent must not be NULL");
    assertNotNull(lesser, "Parameter less must not be NULL");
    assertNotNull(greater, "Parameter greater must not be NULL");

    assertTrue(compareTo(NULL, NULL) == 0, "Comparison of null values must be 0.");

    assertTrue(compareTo(exemplar, NULL) > 0, "Comparison of a non-null value to a null value must be > 0.");

    assertTrue(compareTo(NULL, exemplar) < 0, "Comparison of null value to a non-null value must be < 0.");

    assertTrue(compareTo(exemplar, exemplar) == 0, "Comparison of a value to itself must == 0");

    for (int i = 0; equivalent[i] != NULL; i++) {
        assertTrue(compareTo(exemplar, equivalent[i]) == 0,
                   "Comparison of the value to equivalent[%d] must == 0", i);
        assertTrue(compareTo(exemplar, equivalent[i]) == -compareTo(equivalent[i], exemplar),
                   "Requires sgn(compareTo(value, equivalent[%d])) == -sgn(equivalent[%d], value)", i, i);
    }
    for (int i = 0; lesser[i] != NULL; i++) {
        assertTrue(compareTo(exemplar, lesser[i]) > 0,
                   "Compare of value to lesser[%d] must be > 0", i);
        assertTrue(compareTo(exemplar, lesser[i]) == -compareTo(lesser[i], exemplar),
                   "Requires signum(compareTo(value, lesser[%d])) == -signum(lesser[%d], value)", i, i);
    }
    for (int i = 0; greater[i] != NULL; i++) {
        assertTrue(compareTo(exemplar, greater[i]) < 0, "Compare to greater[%d] must be > 0", i);
        assertTrue(compareTo(exemplar, greater[i]) == -compareTo(greater[i], exemplar),
                   "Requires compareTo(value, greater[%d]) == -compareTo(greater[%d], value)", i, i);
    }

    return true;
}

void
parcObjectTesting_AssertHashCode(const PARCObject *x, const void *y)
{
    assertFalse(x == y, "The parameters x and y cannot be the same value.");
    assertTrue(parcObject_Equals(x, y), "The parameters x and y must be equal");

    PARCHashCode xCode = parcObject_HashCode(x);
    PARCHashCode yCode = parcObject_HashCode(y);

    assertTrue(xCode == yCode, "Expected the HashCode of two equal objects to be equal.");
}

void
parcObjectTesting_AssertHashCodeImpl(PARCHashCode (*hashCode)(const void *a), void *a)
{
    PARCHashCode code1 = hashCode(a);
    PARCHashCode code2 = hashCode(a);
    assertTrue(code1 == code2, "HashCode function does not consistently return the same value.");
}

static void
_parcObjectTesting_AssertCopy(const PARCObject *instance)
{
    PARCObject *copy = parcObject_Copy(instance);
    if (copy == instance) {
        parcObject_Release(&copy);
        assertFalse(true, "Copy should not be the same object");
    }
    if (!parcObject_Equals(instance, copy)) {
        parcObject_Release(&copy);
        assertTrue(false, "Object fails Copy Test");
    }

    parcObject_Release(&copy);
}

static void
_parcObjectTesting_AssertEqualsWrapper(const PARCObject *a,
                                       const PARCObject *b,
                                       const PARCObject *c,
                                       ...)
{
    va_list ap;
    va_start(ap, c);

    _parcObjectTesting_AssertEquals((bool (*)(const void *, const void *))parcObject_Equals, a, b, c, ap);

    va_end(ap);
}

static void
_parcObjectTesting_AssertToJSON(const PARCObject *instance)
{
    PARCJSON *json = parcObject_ToJSON(instance);
    char *result = parcJSON_ToString(json);
    assertNotNull(result, "Something should be returned");
    parcMemory_Deallocate(&result);
    parcJSON_Release(&json);
}

static void
_parcObjectTesting_AssertToString(const PARCObject *instance)
{
    char *result = parcObject_ToString(instance);
    assertNotNull(result, "Something should be returned");
    parcMemory_Deallocate(&result);
}

void
parcObjectTesting_AssertObjectConformance(const PARCObject *inst1,
                                          const PARCObject *inst2,
                                          const PARCObject *inst3,
                                          const PARCObject *lesser,
                                          const PARCObject *greater)
{
    assertNotNull(inst1, "The value of x cannot be NULL.");
    assertNotNull(inst2, "The value of y cannot be NULL.");
    assertNotNull(inst3, "The value of z cannot be NULL.");
    assertNotNull(lesser, "The value of z cannot be NULL.");
    assertNotNull(greater, "The value of z cannot be NULL.");

    parcObject_AssertValid(inst1);
    parcObject_AssertValid(inst2);
    parcObject_AssertValid(inst3);
    parcObject_AssertValid(lesser);
    parcObject_AssertValid(greater);

    // Acquire/Release
    parcObjectTesting_AssertAcquireReleaseImpl(inst1);

    // Equals
    _parcObjectTesting_AssertEqualsWrapper(inst1, inst2, inst3, lesser, greater, NULL);

    // Copy
    _parcObjectTesting_AssertCopy(inst1);

    // Compare
    const void *equals[] = { inst1, inst2, NULL };
    const void *lessThan[] = { lesser, NULL };
    const void *greaterThan[] = { greater, NULL };
    parcObjectTesting_AssertCompareToImpl(parcObject_Compare, inst1, equals, lessThan, greaterThan);

    // HashCode
    parcObjectTesting_AssertHashCode(inst1, inst2);

    // ToJSON
    _parcObjectTesting_AssertToJSON(inst1);

    // ToString
    _parcObjectTesting_AssertToString(inst1);
}