1 /* Copyright (c) 2010 James Grenning and Contributed to Unity Project
2  * ==========================================
3  *  Unity Project - A Test Framework for C
4  *  Copyright (c) 2007 Mike Karlesky, Mark VanderVoord, Greg Williams
5  *  [Released under MIT License. Please refer to license.txt for details]
6  * ========================================== */
7 
8 #include "unity_fixture.h"
9 #include "unity_output_Spy.h"
10 #include <stdlib.h>
11 #include <string.h>
12 
13 TEST_GROUP(UnityFixture);
14 
TEST_SETUP(UnityFixture)15 TEST_SETUP(UnityFixture)
16 {
17 }
18 
TEST_TEAR_DOWN(UnityFixture)19 TEST_TEAR_DOWN(UnityFixture)
20 {
21 }
22 
23 static int* pointer1 = 0;
24 static int* pointer2 = (int*)2;
25 static int* pointer3 = (int*)3;
26 static int int1;
27 static int int2;
28 static int int3;
29 static int int4;
30 
TEST(UnityFixture,PointerSetting)31 TEST(UnityFixture, PointerSetting)
32 {
33     TEST_ASSERT_POINTERS_EQUAL(pointer1, 0);
34     UT_PTR_SET(pointer1, &int1);
35     UT_PTR_SET(pointer2, &int2);
36     UT_PTR_SET(pointer3, &int3);
37     TEST_ASSERT_POINTERS_EQUAL(pointer1, &int1);
38     TEST_ASSERT_POINTERS_EQUAL(pointer2, &int2);
39     TEST_ASSERT_POINTERS_EQUAL(pointer3, &int3);
40     UT_PTR_SET(pointer1, &int4);
41     UnityPointer_UndoAllSets();
42     TEST_ASSERT_POINTERS_EQUAL(pointer1, 0);
43     TEST_ASSERT_POINTERS_EQUAL(pointer2, (int*)2);
44     TEST_ASSERT_POINTERS_EQUAL(pointer3, (int*)3);
45 }
46 
TEST(UnityFixture,ForceMallocFail)47 TEST(UnityFixture, ForceMallocFail)
48 {
49     void* m;
50     void* mfails;
51     UnityMalloc_MakeMallocFailAfterCount(1);
52     m = malloc(10);
53     CHECK(m);
54     mfails = malloc(10);
55     TEST_ASSERT_POINTERS_EQUAL(0, mfails);
56     free(m);
57 }
58 
TEST(UnityFixture,ReallocSmallerIsUnchanged)59 TEST(UnityFixture, ReallocSmallerIsUnchanged)
60 {
61     void* m1 = malloc(10);
62     void* m2 = realloc(m1, 5);
63     TEST_ASSERT_POINTERS_EQUAL(m1, m2);
64     free(m2);
65 }
66 
TEST(UnityFixture,ReallocSameIsUnchanged)67 TEST(UnityFixture, ReallocSameIsUnchanged)
68 {
69     void* m1 = malloc(10);
70     void* m2 = realloc(m1, 10);
71     TEST_ASSERT_POINTERS_EQUAL(m1, m2);
72     free(m2);
73 }
74 
TEST(UnityFixture,ReallocLargerNeeded)75 TEST(UnityFixture, ReallocLargerNeeded)
76 {
77     void* m1 = malloc(10);
78     void* m2;
79     CHECK(m1);
80     strcpy((char*)m1, "123456789");
81     m2 = realloc(m1, 15);
82     /* CHECK(m1 != m2); //Depends on implementation */
83     STRCMP_EQUAL("123456789", m2);
84     free(m2);
85 }
86 
TEST(UnityFixture,ReallocNullPointerIsLikeMalloc)87 TEST(UnityFixture, ReallocNullPointerIsLikeMalloc)
88 {
89     void* m = realloc(0, 15);
90     CHECK(m != 0);
91     free(m);
92 }
93 
TEST(UnityFixture,ReallocSizeZeroFreesMemAndReturnsNullPointer)94 TEST(UnityFixture, ReallocSizeZeroFreesMemAndReturnsNullPointer)
95 {
96     void* m1 = malloc(10);
97     void* m2 = realloc(m1, 0);
98     TEST_ASSERT_POINTERS_EQUAL(0, m2);
99 }
100 
TEST(UnityFixture,CallocFillsWithZero)101 TEST(UnityFixture, CallocFillsWithZero)
102 {
103     void* m = calloc(3, sizeof(char));
104     char* s = (char*)m;
105     CHECK(m);
106     TEST_ASSERT_BYTES_EQUAL(0, s[0]);
107     TEST_ASSERT_BYTES_EQUAL(0, s[1]);
108     TEST_ASSERT_BYTES_EQUAL(0, s[2]);
109     free(m);
110 }
111 
112 static char *p1;
113 static char *p2;
114 
TEST(UnityFixture,PointerSet)115 TEST(UnityFixture, PointerSet)
116 {
117     char c1;
118     char c2;
119     char newC1;
120     char newC2;
121     p1 = &c1;
122     p2 = &c2;
123 
124     UnityPointer_Init();
125     UT_PTR_SET(p1, &newC1);
126     UT_PTR_SET(p2, &newC2);
127     TEST_ASSERT_POINTERS_EQUAL(&newC1, p1);
128     TEST_ASSERT_POINTERS_EQUAL(&newC2, p2);
129     UnityPointer_UndoAllSets();
130     TEST_ASSERT_POINTERS_EQUAL(&c1, p1);
131     TEST_ASSERT_POINTERS_EQUAL(&c2, p2);
132 }
133 
TEST(UnityFixture,FreeNULLSafety)134 TEST(UnityFixture, FreeNULLSafety)
135 {
136     free(NULL);
137 }
138 
TEST(UnityFixture,ConcludeTestIncrementsFailCount)139 TEST(UnityFixture, ConcludeTestIncrementsFailCount)
140 {
141     UNITY_UINT savedFails = Unity.TestFailures;
142     UNITY_UINT savedIgnores = Unity.TestIgnores;
143     UnityOutputCharSpy_Enable(1);
144     Unity.CurrentTestFailed = 1;
145     UnityConcludeFixtureTest(); /* Resets TestFailed for this test to pass */
146     Unity.CurrentTestIgnored = 1;
147     UnityConcludeFixtureTest(); /* Resets TestIgnored */
148     UnityOutputCharSpy_Enable(0);
149     TEST_ASSERT_EQUAL(savedFails + 1, Unity.TestFailures);
150     TEST_ASSERT_EQUAL(savedIgnores + 1, Unity.TestIgnores);
151     Unity.TestFailures = savedFails;
152     Unity.TestIgnores = savedIgnores;
153 }
154 
155 /*------------------------------------------------------------ */
156 
157 TEST_GROUP(UnityCommandOptions);
158 
159 static int savedVerbose;
160 static unsigned int savedRepeat;
161 static const char* savedName;
162 static const char* savedGroup;
163 
TEST_SETUP(UnityCommandOptions)164 TEST_SETUP(UnityCommandOptions)
165 {
166     savedVerbose = UnityFixture.Verbose;
167     savedRepeat = UnityFixture.RepeatCount;
168     savedName = UnityFixture.NameFilter;
169     savedGroup = UnityFixture.GroupFilter;
170 }
171 
TEST_TEAR_DOWN(UnityCommandOptions)172 TEST_TEAR_DOWN(UnityCommandOptions)
173 {
174     UnityFixture.Verbose = savedVerbose;
175     UnityFixture.RepeatCount= savedRepeat;
176     UnityFixture.NameFilter = savedName;
177     UnityFixture.GroupFilter = savedGroup;
178 }
179 
180 
181 static const char* noOptions[] = {
182         "testrunner.exe"
183 };
184 
TEST(UnityCommandOptions,DefaultOptions)185 TEST(UnityCommandOptions, DefaultOptions)
186 {
187     UnityGetCommandLineOptions(1, noOptions);
188     TEST_ASSERT_EQUAL(0, UnityFixture.Verbose);
189     TEST_ASSERT_POINTERS_EQUAL(0, UnityFixture.GroupFilter);
190     TEST_ASSERT_POINTERS_EQUAL(0, UnityFixture.NameFilter);
191     TEST_ASSERT_EQUAL(1, UnityFixture.RepeatCount);
192 }
193 
194 static const char* verbose[] = {
195         "testrunner.exe",
196         "-v"
197 };
198 
TEST(UnityCommandOptions,OptionVerbose)199 TEST(UnityCommandOptions, OptionVerbose)
200 {
201     TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(2, verbose));
202     TEST_ASSERT_EQUAL(1, UnityFixture.Verbose);
203 }
204 
205 static const char* group[] = {
206         "testrunner.exe",
207         "-g", "groupname"
208 };
209 
TEST(UnityCommandOptions,OptionSelectTestByGroup)210 TEST(UnityCommandOptions, OptionSelectTestByGroup)
211 {
212     TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(3, group));
213     STRCMP_EQUAL("groupname", UnityFixture.GroupFilter);
214 }
215 
216 static const char* name[] = {
217         "testrunner.exe",
218         "-n", "testname"
219 };
220 
TEST(UnityCommandOptions,OptionSelectTestByName)221 TEST(UnityCommandOptions, OptionSelectTestByName)
222 {
223     TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(3, name));
224     STRCMP_EQUAL("testname", UnityFixture.NameFilter);
225 }
226 
227 static const char* repeat[] = {
228         "testrunner.exe",
229         "-r", "99"
230 };
231 
TEST(UnityCommandOptions,OptionSelectRepeatTestsDefaultCount)232 TEST(UnityCommandOptions, OptionSelectRepeatTestsDefaultCount)
233 {
234     TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(2, repeat));
235     TEST_ASSERT_EQUAL(2, UnityFixture.RepeatCount);
236 }
237 
TEST(UnityCommandOptions,OptionSelectRepeatTestsSpecificCount)238 TEST(UnityCommandOptions, OptionSelectRepeatTestsSpecificCount)
239 {
240     TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(3, repeat));
241     TEST_ASSERT_EQUAL(99, UnityFixture.RepeatCount);
242 }
243 
244 static const char* multiple[] = {
245         "testrunner.exe",
246         "-v",
247         "-g", "groupname",
248         "-n", "testname",
249         "-r", "98"
250 };
251 
TEST(UnityCommandOptions,MultipleOptions)252 TEST(UnityCommandOptions, MultipleOptions)
253 {
254     TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(8, multiple));
255     TEST_ASSERT_EQUAL(1, UnityFixture.Verbose);
256     STRCMP_EQUAL("groupname", UnityFixture.GroupFilter);
257     STRCMP_EQUAL("testname", UnityFixture.NameFilter);
258     TEST_ASSERT_EQUAL(98, UnityFixture.RepeatCount);
259 }
260 
261 static const char* dashRNotLast[] = {
262         "testrunner.exe",
263         "-v",
264         "-g", "gggg",
265         "-r",
266         "-n", "tttt",
267 };
268 
TEST(UnityCommandOptions,MultipleOptionsDashRNotLastAndNoValueSpecified)269 TEST(UnityCommandOptions, MultipleOptionsDashRNotLastAndNoValueSpecified)
270 {
271     TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(7, dashRNotLast));
272     TEST_ASSERT_EQUAL(1, UnityFixture.Verbose);
273     STRCMP_EQUAL("gggg", UnityFixture.GroupFilter);
274     STRCMP_EQUAL("tttt", UnityFixture.NameFilter);
275     TEST_ASSERT_EQUAL(2, UnityFixture.RepeatCount);
276 }
277 
278 static const char* unknownCommand[] = {
279         "testrunner.exe",
280         "-v",
281         "-g", "groupname",
282         "-n", "testname",
283         "-r", "98",
284         "-z"
285 };
TEST(UnityCommandOptions,UnknownCommandIsIgnored)286 TEST(UnityCommandOptions, UnknownCommandIsIgnored)
287 {
288     TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(9, unknownCommand));
289     TEST_ASSERT_EQUAL(1, UnityFixture.Verbose);
290     STRCMP_EQUAL("groupname", UnityFixture.GroupFilter);
291     STRCMP_EQUAL("testname", UnityFixture.NameFilter);
292     TEST_ASSERT_EQUAL(98, UnityFixture.RepeatCount);
293 }
294 
TEST(UnityCommandOptions,GroupOrNameFilterWithoutStringFails)295 TEST(UnityCommandOptions, GroupOrNameFilterWithoutStringFails)
296 {
297     TEST_ASSERT_EQUAL(1, UnityGetCommandLineOptions(3, unknownCommand));
298     TEST_ASSERT_EQUAL(1, UnityGetCommandLineOptions(5, unknownCommand));
299     TEST_ASSERT_EQUAL(1, UnityMain(3, unknownCommand, NULL));
300 }
301 
TEST(UnityCommandOptions,GroupFilterReallyFilters)302 TEST(UnityCommandOptions, GroupFilterReallyFilters)
303 {
304     UNITY_UINT saved = Unity.NumberOfTests;
305     TEST_ASSERT_EQUAL(0, UnityGetCommandLineOptions(4, unknownCommand));
306     UnityIgnoreTest(NULL, "non-matching", NULL);
307     TEST_ASSERT_EQUAL(saved, Unity.NumberOfTests);
308 }
309 
IGNORE_TEST(UnityCommandOptions,TestShouldBeIgnored)310 IGNORE_TEST(UnityCommandOptions, TestShouldBeIgnored)
311 {
312     TEST_FAIL_MESSAGE("This test should not run!");
313 }
314 
315 /*------------------------------------------------------------ */
316 
317 TEST_GROUP(LeakDetection);
318 
TEST_SETUP(LeakDetection)319 TEST_SETUP(LeakDetection)
320 {
321 #ifdef UNITY_EXCLUDE_STDLIB_MALLOC
322     UnityOutputCharSpy_Create(200);
323 #else
324     UnityOutputCharSpy_Create(1000);
325 #endif
326 }
327 
TEST_TEAR_DOWN(LeakDetection)328 TEST_TEAR_DOWN(LeakDetection)
329 {
330     UnityOutputCharSpy_Destroy();
331 }
332 
333 #define EXPECT_ABORT_BEGIN \
334   { \
335     jmp_buf TestAbortFrame;   \
336     memcpy(TestAbortFrame, Unity.AbortFrame, sizeof(jmp_buf)); \
337     if (TEST_PROTECT()) \
338     {
339 
340 #define EXPECT_ABORT_END \
341     } \
342     memcpy(Unity.AbortFrame, TestAbortFrame, sizeof(jmp_buf)); \
343   }
344 
345 /* This tricky set of defines lets us see if we are using the Spy, returns 1 if true */
346 #ifdef __STDC_VERSION__
347 
348 #if __STDC_VERSION__ >= 199901L
349 #define USING_SPY_AS(a)                    EXPAND_AND_USE_2ND(ASSIGN_VALUE(a), 0)
350 #define ASSIGN_VALUE(a)                    VAL_##a
351 #define VAL_UnityOutputCharSpy_OutputChar  0, 1
352 #define EXPAND_AND_USE_2ND(a, b)           SECOND_PARAM(a, b, throwaway)
353 #define SECOND_PARAM(a, b, ...)            b
354 #if USING_SPY_AS(UNITY_OUTPUT_CHAR)
355   #define USING_OUTPUT_SPY /* UNITY_OUTPUT_CHAR = UnityOutputCharSpy_OutputChar */
356 #endif
357 #endif /* >= 199901 */
358 
359 #else  /* __STDC_VERSION__ else */
360 #define UnityOutputCharSpy_OutputChar 42
361 #if UNITY_OUTPUT_CHAR == UnityOutputCharSpy_OutputChar /* Works if no -Wundef -Werror */
362   #define USING_OUTPUT_SPY
363 #endif
364 #undef UnityOutputCharSpy_OutputChar
365 #endif /* __STDC_VERSION__ */
366 
TEST(LeakDetection,DetectsLeak)367 TEST(LeakDetection, DetectsLeak)
368 {
369 #ifndef USING_OUTPUT_SPY
370     TEST_IGNORE_MESSAGE("Build with '-D UNITY_OUTPUT_CHAR=UnityOutputCharSpy_OutputChar' to enable tests");
371 #else
372     void* m = malloc(10);
373     TEST_ASSERT_NOT_NULL(m);
374     UnityOutputCharSpy_Enable(1);
375     EXPECT_ABORT_BEGIN
376     UnityMalloc_EndTest();
377     EXPECT_ABORT_END
378     UnityOutputCharSpy_Enable(0);
379     Unity.CurrentTestFailed = 0;
380     CHECK(strstr(UnityOutputCharSpy_Get(), "This test leaks!"));
381     free(m);
382 #endif
383 }
384 
TEST(LeakDetection,BufferOverrunFoundDuringFree)385 TEST(LeakDetection, BufferOverrunFoundDuringFree)
386 {
387 #ifndef USING_OUTPUT_SPY
388     TEST_IGNORE();
389 #else
390     void* m = malloc(10);
391     char* s = (char*)m;
392     TEST_ASSERT_NOT_NULL(m);
393     s[10] = (char)0xFF;
394     UnityOutputCharSpy_Enable(1);
395     EXPECT_ABORT_BEGIN
396     free(m);
397     EXPECT_ABORT_END
398     UnityOutputCharSpy_Enable(0);
399     Unity.CurrentTestFailed = 0;
400     CHECK(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during free()"));
401 #endif
402 }
403 
TEST(LeakDetection,BufferOverrunFoundDuringRealloc)404 TEST(LeakDetection, BufferOverrunFoundDuringRealloc)
405 {
406 #ifndef USING_OUTPUT_SPY
407     TEST_IGNORE();
408 #else
409     void* m = malloc(10);
410     char* s = (char*)m;
411     TEST_ASSERT_NOT_NULL(m);
412     s[10] = (char)0xFF;
413     UnityOutputCharSpy_Enable(1);
414     EXPECT_ABORT_BEGIN
415     m = realloc(m, 100);
416     EXPECT_ABORT_END
417     UnityOutputCharSpy_Enable(0);
418     Unity.CurrentTestFailed = 0;
419     CHECK(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during realloc()"));
420 #endif
421 }
422 
TEST(LeakDetection,BufferGuardWriteFoundDuringFree)423 TEST(LeakDetection, BufferGuardWriteFoundDuringFree)
424 {
425 #ifndef USING_OUTPUT_SPY
426     TEST_IGNORE();
427 #else
428     void* m = malloc(10);
429     char* s = (char*)m;
430     TEST_ASSERT_NOT_NULL(m);
431     s[-1] = (char)0x00; /* Will not detect 0 */
432     s[-2] = (char)0x01;
433     UnityOutputCharSpy_Enable(1);
434     EXPECT_ABORT_BEGIN
435     free(m);
436     EXPECT_ABORT_END
437     UnityOutputCharSpy_Enable(0);
438     Unity.CurrentTestFailed = 0;
439     CHECK(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during free()"));
440 #endif
441 }
442 
TEST(LeakDetection,BufferGuardWriteFoundDuringRealloc)443 TEST(LeakDetection, BufferGuardWriteFoundDuringRealloc)
444 {
445 #ifndef USING_OUTPUT_SPY
446     TEST_IGNORE();
447 #else
448     void* m = malloc(10);
449     char* s = (char*)m;
450     TEST_ASSERT_NOT_NULL(m);
451     s[-1] = (char)0x0A;
452     UnityOutputCharSpy_Enable(1);
453     EXPECT_ABORT_BEGIN
454     m = realloc(m, 100);
455     EXPECT_ABORT_END
456     UnityOutputCharSpy_Enable(0);
457     Unity.CurrentTestFailed = 0;
458     CHECK(strstr(UnityOutputCharSpy_Get(), "Buffer overrun detected during realloc()"));
459 #endif
460 }
461 
TEST(LeakDetection,PointerSettingMax)462 TEST(LeakDetection, PointerSettingMax)
463 {
464 #ifndef USING_OUTPUT_SPY
465     TEST_IGNORE();
466 #else
467     int i;
468     for (i = 0; i < UNITY_MAX_POINTERS; i++) UT_PTR_SET(pointer1, &int1);
469     UnityOutputCharSpy_Enable(1);
470     EXPECT_ABORT_BEGIN
471     UT_PTR_SET(pointer1, &int1);
472     EXPECT_ABORT_END
473     UnityOutputCharSpy_Enable(0);
474     Unity.CurrentTestFailed = 0;
475     CHECK(strstr(UnityOutputCharSpy_Get(), "Too many pointers set"));
476 #endif
477 }
478 
479 /*------------------------------------------------------------ */
480 
481 TEST_GROUP(InternalMalloc);
482 #define TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(first_mem_ptr, ptr) \
483     ptr = malloc(10); free(ptr);                                   \
484     TEST_ASSERT_EQUAL_PTR_MESSAGE(first_mem_ptr, ptr, "Memory was stranded, free in LIFO order");
485 
486 
TEST_SETUP(InternalMalloc)487 TEST_SETUP(InternalMalloc) { }
TEST_TEAR_DOWN(InternalMalloc)488 TEST_TEAR_DOWN(InternalMalloc) { }
489 
TEST(InternalMalloc,MallocPastBufferFails)490 TEST(InternalMalloc, MallocPastBufferFails)
491 {
492 #ifdef UNITY_EXCLUDE_STDLIB_MALLOC
493     void* m = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1);
494     void* n = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2);
495     free(m);
496     TEST_ASSERT_NOT_NULL(m);
497     TEST_ASSERT_NULL(n);
498     TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(m, n);
499 #endif
500 }
501 
TEST(InternalMalloc,CallocPastBufferFails)502 TEST(InternalMalloc, CallocPastBufferFails)
503 {
504 #ifdef UNITY_EXCLUDE_STDLIB_MALLOC
505     void* m = calloc(1, UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1);
506     void* n = calloc(1, UNITY_INTERNAL_HEAP_SIZE_BYTES/2);
507     free(m);
508     TEST_ASSERT_NOT_NULL(m);
509     TEST_ASSERT_NULL(n);
510     TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(m, n);
511 #endif
512 }
513 
TEST(InternalMalloc,MallocThenReallocGrowsMemoryInPlace)514 TEST(InternalMalloc, MallocThenReallocGrowsMemoryInPlace)
515 {
516 #ifdef UNITY_EXCLUDE_STDLIB_MALLOC
517     void* m = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1);
518     void* n = realloc(m, UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 9);
519     free(n);
520     TEST_ASSERT_NOT_NULL(m);
521     TEST_ASSERT_EQUAL(m, n);
522     TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(m, n);
523 #endif
524 }
525 
TEST(InternalMalloc,ReallocFailDoesNotFreeMem)526 TEST(InternalMalloc, ReallocFailDoesNotFreeMem)
527 {
528 #ifdef UNITY_EXCLUDE_STDLIB_MALLOC
529     void* m = malloc(UNITY_INTERNAL_HEAP_SIZE_BYTES/2);
530     void* n1 = malloc(10);
531     void* out_of_mem = realloc(n1, UNITY_INTERNAL_HEAP_SIZE_BYTES/2 + 1);
532     void* n2 = malloc(10);
533 
534     free(n2);
535     if (out_of_mem == NULL) free(n1);
536     free(m);
537 
538     TEST_ASSERT_NOT_NULL(m);       /* Got a real memory location */
539     TEST_ASSERT_NULL(out_of_mem);  /* The realloc should have failed */
540     TEST_ASSERT_NOT_EQUAL(n2, n1); /* If n1 != n2 then realloc did not free n1 */
541     TEST_ASSERT_MEMORY_ALL_FREE_LIFO_ORDER(m, n2);
542 #endif
543 }
544