blob: 0609736e5d0e1217d443c35395089ae202c00dd7 [file] [log] [blame]
Laurence Lundbladef156fb82018-10-01 09:47:03 -07001/*==============================================================================
2 run_tests.c -- test aggregator and results reporting
Laurence Lundblade3aee3a32018-12-17 16:17:45 -08003
Laurence Lundbladeee851742020-01-08 08:37:05 -08004 Copyright (c) 2018-2020, Laurence Lundblade. All rights reserved.
Laurence Lundblade035bd782019-01-21 17:01:31 -08005
Laurence Lundbladea3fd49f2019-01-21 10:16:22 -08006 SPDX-License-Identifier: BSD-3-Clause
Laurence Lundblade035bd782019-01-21 17:01:31 -08007
Laurence Lundbladea3fd49f2019-01-21 10:16:22 -08008 See BSD-3-Clause license in README.md
Laurence Lundbladef156fb82018-10-01 09:47:03 -07009
Laurence Lundblade1f8b5b02019-01-01 22:27:38 -080010 Created on 9/30/18
Laurence Lundbladeee851742020-01-08 08:37:05 -080011 =============================================================================*/
Laurence Lundbladef156fb82018-10-01 09:47:03 -070012
Laurence Lundbladef156fb82018-10-01 09:47:03 -070013#include "run_tests.h"
14#include "UsefulBuf.h"
15#include <stdbool.h>
16
Laurence Lundblade2d85ce42018-10-12 14:12:47 +080017#include "float_tests.h"
Laurence Lundblade9e3651c2018-10-10 11:49:55 +080018#include "qcbor_decode_tests.h"
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +053019#include "qcbor_encode_tests.h"
20#include "UsefulBuf_Tests.h"
Laurence Lundbladef156fb82018-10-01 09:47:03 -070021
Laurence Lundblade1f8b5b02019-01-01 22:27:38 -080022
Laurence Lundbladef156fb82018-10-01 09:47:03 -070023/*
Laurence Lundbladea65b4822019-09-08 12:17:03 -070024 Test configuration
25 */
Laurence Lundblade1f8b5b02019-01-01 22:27:38 -080026
Laurence Lundbladec5fef682020-01-25 11:38:45 -080027typedef int32_t (test_fun_t)(void);
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +053028typedef const char * (test_fun2_t)(void);
29
Laurence Lundbladef156fb82018-10-01 09:47:03 -070030
Laurence Lundbladea2e29072018-12-30 09:20:06 -080031#define TEST_ENTRY(test_name) {#test_name, test_name, true}
32#define TEST_ENTRY_DISABLED(test_name) {#test_name, test_name, false}
33
Laurence Lundbladef156fb82018-10-01 09:47:03 -070034typedef struct {
Laurence Lundbladea2e29072018-12-30 09:20:06 -080035 const char *szTestName;
Laurence Lundbladef156fb82018-10-01 09:47:03 -070036 test_fun_t *test_fun;
Laurence Lundbladea2e29072018-12-30 09:20:06 -080037 bool bEnabled;
Laurence Lundbladef156fb82018-10-01 09:47:03 -070038} test_entry;
39
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +053040typedef struct {
41 const char *szTestName;
42 test_fun2_t *test_fun;
Laurence Lundbladea2e29072018-12-30 09:20:06 -080043 bool bEnabled;
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +053044} test_entry2;
45
Laurence Lundbladea65b4822019-09-08 12:17:03 -070046
47static test_entry2 s_tests2[] = {
Laurence Lundblade7566b9f2018-10-12 09:13:32 +080048 TEST_ENTRY(UBUTest_CopyUtil),
49 TEST_ENTRY(UOBTest_NonAdversarial),
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +053050 TEST_ENTRY(TestBasicSanity),
Laurence Lundblade7566b9f2018-10-12 09:13:32 +080051 TEST_ENTRY(UOBTest_BoundaryConditionsTest),
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +053052 TEST_ENTRY(UBMacroConversionsTest),
53 TEST_ENTRY(UBUtilTests),
Laurence Lundblade7566b9f2018-10-12 09:13:32 +080054 TEST_ENTRY(UIBTest_IntegerFormat)
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +053055};
56
57
Laurence Lundbladea65b4822019-09-08 12:17:03 -070058static test_entry s_tests[] = {
Laurence Lundblade0750fc42020-06-20 21:02:34 -070059 TEST_ENTRY(EnterBstrTest),
Laurence Lundblade9c905e82020-04-25 11:31:38 -070060 TEST_ENTRY(IntegerConvertTest),
Laurence Lundbladebb87be22020-04-09 19:15:32 -070061 TEST_ENTRY(EnterMapTest),
Laurence Lundbladec9f0fbc2020-02-07 10:48:33 +000062 TEST_ENTRY(QCBORHeadTest),
Laurence Lundblade9916b1b2019-09-07 22:33:25 -070063 TEST_ENTRY(EmptyMapsAndArraysTest),
Laurence Lundbladebb1062e2019-08-12 23:28:54 -070064 TEST_ENTRY(NotWellFormedTests),
Laurence Lundbladeccfb8cd2018-12-07 21:11:30 +090065 TEST_ENTRY(ParseMapAsArrayTest),
Laurence Lundbladea44d5062018-10-17 18:45:12 +053066 TEST_ENTRY(AllocAllStringsTest),
67 TEST_ENTRY(IndefiniteLengthNestTest),
68 TEST_ENTRY(NestedMapTestIndefLen),
69 TEST_ENTRY(ParseSimpleTest),
Laurence Lundblade3a6042e2019-06-28 19:58:04 -070070 TEST_ENTRY(DecodeFailureTests),
Laurence Lundblade0fb6c6d2018-10-12 22:02:05 +080071 TEST_ENTRY(EncodeRawTest),
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +053072 TEST_ENTRY(RTICResultsTest),
73 TEST_ENTRY(MapEncodeTest),
74 TEST_ENTRY(ArrayNestingTest1),
75 TEST_ENTRY(ArrayNestingTest2),
76 TEST_ENTRY(ArrayNestingTest3),
77 TEST_ENTRY(EncodeDateTest),
78 TEST_ENTRY(SimpleValuesTest1),
79 TEST_ENTRY(IntegerValuesTest1),
80 TEST_ENTRY(AllAddMethodsTest),
Laurence Lundblade9e3651c2018-10-10 11:49:55 +080081 TEST_ENTRY(ParseTooDeepArrayTest),
82 TEST_ENTRY(ComprehensiveInputTest),
83 TEST_ENTRY(ParseMapTest),
Laurence Lundbladea44d5062018-10-17 18:45:12 +053084 TEST_ENTRY(IndefiniteLengthArrayMapTest),
Laurence Lundblade369b90a2018-10-22 02:04:37 +053085 TEST_ENTRY(BasicEncodeTest),
Laurence Lundblade9e3651c2018-10-10 11:49:55 +080086 TEST_ENTRY(NestedMapTest),
87 TEST_ENTRY(BignumParseTest),
88 TEST_ENTRY(OptTagParseTest),
89 TEST_ENTRY(DateParseTest),
Laurence Lundbladec7114722020-08-13 05:11:40 -070090 TEST_ENTRY(SpiffyDateDecodeTest),
Laurence Lundblade9e3651c2018-10-10 11:49:55 +080091 TEST_ENTRY(ShortBufferParseTest2),
92 TEST_ENTRY(ShortBufferParseTest),
93 TEST_ENTRY(ParseDeepArrayTest),
94 TEST_ENTRY(SimpleArrayTest),
95 TEST_ENTRY(IntegerValuesParseTest),
Laurence Lundbladea44d5062018-10-17 18:45:12 +053096 TEST_ENTRY(MemPoolTest),
97 TEST_ENTRY(IndefiniteLengthStringTest),
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -070098#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
Laurence Lundbladebb474be2018-10-22 11:53:21 +053099 TEST_ENTRY(HalfPrecisionDecodeBasicTests),
Laurence Lundbladebb474be2018-10-22 11:53:21 +0530100 TEST_ENTRY(DoubleAsSmallestTest),
101 TEST_ENTRY(HalfPrecisionAgainstRFCCodeTest),
Laurence Lundbladeb275cdc2020-07-12 12:34:38 -0700102#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
Laurence Lundblade585127a2020-07-15 03:25:24 -0700103 TEST_ENTRY(GeneralFloatEncodeTests),
Laurence Lundblade02fcf312020-07-17 02:49:46 -0700104 TEST_ENTRY(GeneralFloatDecodeTests),
Laurence Lundblade369b90a2018-10-22 02:04:37 +0530105 TEST_ENTRY(BstrWrapTest),
106 TEST_ENTRY(BstrWrapErrorTest),
107 TEST_ENTRY(BstrWrapNestTest),
108 TEST_ENTRY(CoseSign1TBSTest),
Laurence Lundbladeea567ac2018-12-09 14:03:21 -0800109 TEST_ENTRY(StringDecoderModeFailTest),
Laurence Lundbladea2e29072018-12-30 09:20:06 -0800110 TEST_ENTRY_DISABLED(BigComprehensiveInputTest),
Laurence Lundbladea4308a82020-10-03 18:08:57 -0700111 TEST_ENTRY_DISABLED(TooLargeInputTest),
Laurence Lundblade1ef8b2d2018-12-14 23:13:34 -0800112 TEST_ENTRY(EncodeErrorTests),
Laurence Lundblade1d7eb632019-02-17 17:23:38 -0800113 TEST_ENTRY(SetUpAllocatorTest),
Jan Jongboom47d86c52019-07-25 08:54:16 +0200114 TEST_ENTRY(SimpleValuesIndefiniteLengthTest1),
Jan Jongboom5d827882019-08-07 12:51:15 +0200115 TEST_ENTRY(EncodeLengthThirtyoneTest),
Laurence Lundbladee3553422020-05-02 11:11:17 -0700116 TEST_ENTRY(CBORSequenceDecodeTests),
Laurence Lundbladee15326f2020-06-15 15:50:23 -0700117 TEST_ENTRY(IntToTests),
Laurence Lundblade37f46e52020-08-04 03:32:14 -0700118 TEST_ENTRY(DecodeTaggedTypeTests),
Laurence Lundblade59289e52019-12-30 13:44:37 -0800119#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
120 TEST_ENTRY(EncodeLengthThirtyoneTest),
121 TEST_ENTRY(ExponentAndMantissaDecodeTests),
122 TEST_ENTRY(ExponentAndMantissaDecodeFailTests),
123 TEST_ENTRY(ExponentAndMantissaEncodeTests),
Laurence Lundbladeb6d1c692020-10-07 18:37:48 -0700124 TEST_ENTRY(SpiffyIndefiniteLengthStringsTests),
Laurence Lundblade59289e52019-12-30 13:44:37 -0800125#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
Laurence Lundbladef156fb82018-10-01 09:47:03 -0700126};
127
128
Laurence Lundbladea65b4822019-09-08 12:17:03 -0700129
130
131/*
132 Convert a number up to 999999999 to a string. This is so sprintf doesn't
133 have to be linked in so as to minimized dependencies even in test code.
Laurence Lundblade6216b1b2019-09-27 11:24:39 +0900134
135 StringMem should be 12 bytes long, 9 for digits, 1 for minus and
136 1 for \0 termination.
Laurence Lundbladea65b4822019-09-08 12:17:03 -0700137 */
138static const char *NumToString(int32_t nNum, UsefulBuf StringMem)
139{
140 const int32_t nMax = 1000000000;
141
142 UsefulOutBuf OutBuf;
143 UsefulOutBuf_Init(&OutBuf, StringMem);
144
145 if(nNum < 0) {
146 UsefulOutBuf_AppendByte(&OutBuf, '-');
147 nNum = -nNum;
148 }
149 if(nNum > nMax-1) {
150 return "XXX";
151 }
152
153 bool bDidSomeOutput = false;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800154 for(int32_t n = nMax; n > 0; n/=10) {
155 int nDigitValue = nNum/n;
156 if(nDigitValue || bDidSomeOutput){
Laurence Lundbladea65b4822019-09-08 12:17:03 -0700157 bDidSomeOutput = true;
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800158 UsefulOutBuf_AppendByte(&OutBuf, (uint8_t)('0' + nDigitValue));
159 nNum -= nDigitValue * n;
Laurence Lundbladea65b4822019-09-08 12:17:03 -0700160 }
161 }
162 if(!bDidSomeOutput){
163 UsefulOutBuf_AppendByte(&OutBuf, '0');
164 }
165 UsefulOutBuf_AppendByte(&OutBuf, '\0');
166
167 return UsefulOutBuf_GetError(&OutBuf) ? "" : StringMem.ptr;
168}
169
170
171/*
172 Public function. See run_test.h.
173 */
Laurence Lundblade29501b72020-01-16 15:05:18 -0800174int RunTestsQCBOR(const char *szTestNames[],
Laurence Lundbladeee851742020-01-08 08:37:05 -0800175 OutputStringCB pfOutput,
176 void *poutCtx,
177 int *pNumTestsRun)
Laurence Lundbladef156fb82018-10-01 09:47:03 -0700178{
179 int nTestsFailed = 0;
180 int nTestsRun = 0;
Laurence Lundblade59289e52019-12-30 13:44:37 -0800181
Laurence Lundblade6216b1b2019-09-27 11:24:39 +0900182 UsefulBuf_MAKE_STACK_UB(StringStorage, 12);
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530183
184 test_entry2 *t2;
185 const test_entry2 *s_tests2_end = s_tests2 + sizeof(s_tests2)/sizeof(test_entry2);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800186
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530187 for(t2 = s_tests2; t2 < s_tests2_end; t2++) {
Laurence Lundblade1f8b5b02019-01-01 22:27:38 -0800188 if(szTestNames[0]) {
189 // Some tests have been named
190 const char **szRequestedNames;
191 for(szRequestedNames = szTestNames; *szRequestedNames; szRequestedNames++) {
192 if(!strcmp(t2->szTestName, *szRequestedNames)) {
193 break; // Name matched
194 }
195 }
196 if(*szRequestedNames == NULL) {
197 // Didn't match this test
198 continue;
199 }
200 } else {
201 // no tests named, but don't run "disabled" tests
202 if(!t2->bEnabled) {
203 // Don't run disabled tests when all tests are being run
204 // as indicated by no specific test names being given
205 continue;
206 }
Laurence Lundbladea2e29072018-12-30 09:20:06 -0800207 }
Laurence Lundblade1f8b5b02019-01-01 22:27:38 -0800208
Laurence Lundbladea2e29072018-12-30 09:20:06 -0800209 const char * szTestResult = (t2->test_fun)();
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530210 nTestsRun++;
Laurence Lundblade1f8b5b02019-01-01 22:27:38 -0800211 if(pfOutput) {
Laurence Lundbladed396f622019-01-12 17:12:29 -0800212 (*pfOutput)(t2->szTestName, poutCtx, 0);
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530213 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800214
Laurence Lundbladea2e29072018-12-30 09:20:06 -0800215 if(szTestResult) {
Laurence Lundblade1f8b5b02019-01-01 22:27:38 -0800216 if(pfOutput) {
Laurence Lundbladed396f622019-01-12 17:12:29 -0800217 (*pfOutput)(" FAILED (returned ", poutCtx, 0);
218 (*pfOutput)(szTestResult, poutCtx, 0);
Laurence Lundbladedf1c1cf2019-01-17 11:55:05 -0800219 (*pfOutput)(")", poutCtx, 1);
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530220 }
221 nTestsFailed++;
222 } else {
Laurence Lundblade1f8b5b02019-01-01 22:27:38 -0800223 if(pfOutput) {
Laurence Lundbladed396f622019-01-12 17:12:29 -0800224 (*pfOutput)( " PASSED", poutCtx, 1);
Laurence Lundbladedc6e28e2018-10-11 19:19:27 +0530225 }
226 }
227 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800228
229
Laurence Lundbladef156fb82018-10-01 09:47:03 -0700230 test_entry *t;
231 const test_entry *s_tests_end = s_tests + sizeof(s_tests)/sizeof(test_entry);
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800232
Laurence Lundbladef156fb82018-10-01 09:47:03 -0700233 for(t = s_tests; t < s_tests_end; t++) {
Laurence Lundblade1f8b5b02019-01-01 22:27:38 -0800234 if(szTestNames[0]) {
235 // Some tests have been named
236 const char **szRequestedNames;
237 for(szRequestedNames = szTestNames; *szRequestedNames; szRequestedNames++) {
238 if(!strcmp(t->szTestName, *szRequestedNames)) {
239 break; // Name matched
240 }
241 }
242 if(*szRequestedNames == NULL) {
243 // Didn't match this test
244 continue;
245 }
246 } else {
247 // no tests named, but don't run "disabled" tests
248 if(!t->bEnabled) {
249 // Don't run disabled tests when all tests are being run
250 // as indicated by no specific test names being given
251 continue;
252 }
Laurence Lundbladea2e29072018-12-30 09:20:06 -0800253 }
Laurence Lundblade1f8b5b02019-01-01 22:27:38 -0800254
Laurence Lundbladec5fef682020-01-25 11:38:45 -0800255 int32_t nTestResult = (t->test_fun)();
Laurence Lundbladef156fb82018-10-01 09:47:03 -0700256 nTestsRun++;
Laurence Lundblade1f8b5b02019-01-01 22:27:38 -0800257 if(pfOutput) {
Laurence Lundbladed396f622019-01-12 17:12:29 -0800258 (*pfOutput)(t->szTestName, poutCtx, 0);
Laurence Lundbladef156fb82018-10-01 09:47:03 -0700259 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800260
Laurence Lundbladea2e29072018-12-30 09:20:06 -0800261 if(nTestResult) {
Laurence Lundblade1f8b5b02019-01-01 22:27:38 -0800262 if(pfOutput) {
Laurence Lundbladed396f622019-01-12 17:12:29 -0800263 (*pfOutput)(" FAILED (returned ", poutCtx, 0);
264 (*pfOutput)(NumToString(nTestResult, StringStorage), poutCtx, 0);
265 (*pfOutput)(")", poutCtx, 1);
Laurence Lundbladef156fb82018-10-01 09:47:03 -0700266 }
267 nTestsFailed++;
268 } else {
Laurence Lundblade1f8b5b02019-01-01 22:27:38 -0800269 if(pfOutput) {
Laurence Lundbladed396f622019-01-12 17:12:29 -0800270 (*pfOutput)( " PASSED", poutCtx, 1);
Laurence Lundbladef156fb82018-10-01 09:47:03 -0700271 }
272 }
273 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800274
Laurence Lundbladef156fb82018-10-01 09:47:03 -0700275 if(pNumTestsRun) {
276 *pNumTestsRun = nTestsRun;
277 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800278
Laurence Lundblade1f8b5b02019-01-01 22:27:38 -0800279 if(pfOutput) {
Laurence Lundbladed396f622019-01-12 17:12:29 -0800280 (*pfOutput)( "SUMMARY: ", poutCtx, 0);
281 (*pfOutput)( NumToString(nTestsRun, StringStorage), poutCtx, 0);
282 (*pfOutput)( " tests run; ", poutCtx, 0);
283 (*pfOutput)( NumToString(nTestsFailed, StringStorage), poutCtx, 0);
284 (*pfOutput)( " tests failed", poutCtx, 1);
Laurence Lundbladef156fb82018-10-01 09:47:03 -0700285 }
Laurence Lundblade3aee3a32018-12-17 16:17:45 -0800286
Laurence Lundbladef156fb82018-10-01 09:47:03 -0700287 return nTestsFailed;
288}
Laurence Lundblade1f8b5b02019-01-01 22:27:38 -0800289
290
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800291// For size printing
292#include "qcbor/qcbor_encode.h"
293#include "qcbor/qcbor_decode.h"
Laurence Lundbladec384d4e2020-10-07 09:46:10 -0700294#include "qcbor/qcbor_spiffy_decode.h"
Laurence Lundblade844bb5c2020-03-01 17:27:25 -0800295
Laurence Lundblade1f8b5b02019-01-01 22:27:38 -0800296
Laurence Lundbladea65b4822019-09-08 12:17:03 -0700297/*
298 Public function. See run_test.h.
299 */
Laurence Lundbladeee851742020-01-08 08:37:05 -0800300static void PrintSize(const char *szWhat,
301 uint32_t uSize,
302 OutputStringCB pfOutput,
303 void *pOutCtx)
Laurence Lundblade1f8b5b02019-01-01 22:27:38 -0800304{
Laurence Lundbladed396f622019-01-12 17:12:29 -0800305 UsefulBuf_MAKE_STACK_UB(buffer, 20);
Laurence Lundblade1f8b5b02019-01-01 22:27:38 -0800306
Laurence Lundbladed396f622019-01-12 17:12:29 -0800307 (*pfOutput)(szWhat, pOutCtx, 0);
308 (*pfOutput)(" ", pOutCtx, 0);
Laurence Lundblade06350ea2020-01-27 19:32:40 -0800309 (*pfOutput)(NumToString((int32_t)uSize, buffer), pOutCtx, 0);
Laurence Lundbladed396f622019-01-12 17:12:29 -0800310 (*pfOutput)("", pOutCtx, 1);
Laurence Lundblade1f8b5b02019-01-01 22:27:38 -0800311}
312
Laurence Lundbladea65b4822019-09-08 12:17:03 -0700313
314/*
315 Public function. See run_test.h.
316 */
Laurence Lundblade29501b72020-01-16 15:05:18 -0800317void PrintSizesQCBOR(OutputStringCB pfOutput, void *pOutCtx)
Laurence Lundblade1f8b5b02019-01-01 22:27:38 -0800318{
Laurence Lundbladeee851742020-01-08 08:37:05 -0800319 // These will never be large so cast is safe
320 PrintSize("sizeof(QCBORTrackNesting)", (uint32_t)sizeof(QCBORTrackNesting), pfOutput, pOutCtx);
Laurence Lundbladed396f622019-01-12 17:12:29 -0800321 PrintSize("sizeof(QCBOREncodeContext)", (uint32_t)sizeof(QCBOREncodeContext), pfOutput, pOutCtx);
322 PrintSize("sizeof(QCBORDecodeNesting)", (uint32_t)sizeof(QCBORDecodeNesting), pfOutput, pOutCtx);
323 PrintSize("sizeof(QCBORDecodeContext)", (uint32_t)sizeof(QCBORDecodeContext), pfOutput, pOutCtx);
Laurence Lundbladeee851742020-01-08 08:37:05 -0800324 PrintSize("sizeof(QCBORItem)", (uint32_t)sizeof(QCBORItem), pfOutput, pOutCtx);
325 PrintSize("sizeof(QCBORTagListIn)", (uint32_t)sizeof(QCBORTagListIn), pfOutput, pOutCtx);
326 PrintSize("sizeof(QCBORTagListOut)", (uint32_t)sizeof(QCBORTagListOut), pfOutput, pOutCtx);
Laurence Lundbladec384d4e2020-10-07 09:46:10 -0700327 PrintSize("sizeof(TagSpecification)", (uint32_t)sizeof(TagSpecification), pfOutput, pOutCtx);
Laurence Lundbladed396f622019-01-12 17:12:29 -0800328 (*pfOutput)("", pOutCtx, 1);
Laurence Lundblade1f8b5b02019-01-01 22:27:38 -0800329}