e238e0eaab03b8ee4754e431900a6f6173f35ff0
9 TestSupportCode::TestSupportCode ( const Project
& project
)
14 TestSupportCode::~TestSupportCode ()
19 TestSupportCode::IsTestModule ( const Module
& module
)
21 return module
.type
== Test
;
25 TestSupportCode::GenerateTestSupportCode ( bool verbose
)
27 for ( size_t i
= 0; i
< project
.modules
.size (); i
++ )
29 if ( IsTestModule ( *project
.modules
[i
] ) )
31 GenerateTestSupportCodeForModule ( *project
.modules
[i
],
38 TestSupportCode::GenerateTestSupportCodeForModule ( Module
& module
,
43 printf ( "\nGenerating test support code for %s",
44 module
.name
.c_str () );
47 WriteHooksFile ( module
);
48 WriteStubsFile ( module
);
49 WriteStartupFile ( module
);
53 TestSupportCode::GetHooksFilename ( Module
& module
)
55 return NormalizeFilename ( Environment::GetIntermediatePath () + SSEP
+ module
.GetBasePath () + SSEP
+ "_hooks.c" );
59 TestSupportCode::WriteStubbedSymbolToHooksFile ( char* buffer
,
60 const StubbedComponent
& component
,
61 const StubbedSymbol
& symbol
)
63 buffer
= buffer
+ sprintf ( buffer
,
64 " {\"%s\", \"%s\", NULL, NULL, NULL},\n",
65 component
.name
.c_str (),
66 symbol
.newname
.c_str () );
71 TestSupportCode::WriteStubbedComponentToHooksFile ( char* buffer
,
72 const StubbedComponent
& component
)
74 for ( size_t i
= 0; i
< component
.symbols
.size () ; i
++ )
75 buffer
= WriteStubbedSymbolToHooksFile ( buffer
,
77 *component
.symbols
[i
] );
82 TestSupportCode::WriteHooksFile ( Module
& module
)
87 buf
= (char*) malloc ( 50*1024 );
89 throw OutOfMemoryException ();
92 s
= s
+ sprintf ( s
, "/* This file is automatically generated. */\n" );
93 s
= s
+ sprintf ( s
, "#include <windows.h>\n" );
94 s
= s
+ sprintf ( s
, "#include \"regtests.h\"\n" );
95 s
= s
+ sprintf ( s
, "\n" );
96 s
= s
+ sprintf ( s
, "_API_DESCRIPTION ExternalDependencies[] =\n" );
97 s
= s
+ sprintf ( s
, "{\n" );
100 for ( size_t i
= 0; i
< module
.stubbedComponents
.size () ; i
++ )
102 s
= WriteStubbedComponentToHooksFile ( s
,
103 *module
.stubbedComponents
[i
] );
104 symbolCount
+= module
.stubbedComponents
[i
]->symbols
.size ();
107 s
= s
+ sprintf ( s
, "};\n" );
108 s
= s
+ sprintf ( s
, "\n" );
109 s
= s
+ sprintf ( s
, "#define ExternalDependencyCount %d\n", symbolCount
);
110 s
= s
+ sprintf ( s
, "ULONG MaxExternalDependency = ExternalDependencyCount - 1;\n" );
111 s
= s
+ sprintf ( s
, "\n" );
113 FileSupportCode::WriteIfChanged ( buf
, GetHooksFilename ( module
) );
119 TestSupportCode::GetStubsFilename ( Module
& module
)
121 return NormalizeFilename ( Environment::GetIntermediatePath () + SSEP
+ module
.GetBasePath () + SSEP
+ "_stubs.S" );
125 GetImportSymbol ( const StubbedSymbol
& symbol
)
127 if (symbol
.symbol
[0] == '@')
128 return "__imp_" + symbol
.symbol
;
130 return "__imp__" + symbol
.symbol
;
134 TestSupportCode::WriteStubbedSymbolToStubsFile ( char* buffer
,
135 const StubbedComponent
& component
,
136 const StubbedSymbol
& symbol
,
139 string importSymbol
= GetImportSymbol( symbol
);
140 buffer
= buffer
+ sprintf ( buffer
,
142 symbol
.symbol
.c_str () );
143 buffer
= buffer
+ sprintf ( buffer
,
145 importSymbol
.c_str () );
146 buffer
= buffer
+ sprintf ( buffer
,
148 symbol
.symbol
.c_str () );
149 buffer
= buffer
+ sprintf ( buffer
,
151 importSymbol
.c_str () );
152 buffer
= buffer
+ sprintf ( buffer
,
155 buffer
= buffer
+ sprintf ( buffer
,
156 " jmp passthrough\n" );
157 buffer
= buffer
+ sprintf ( buffer
, "\n" );
162 TestSupportCode::WriteStubbedComponentToStubsFile ( char* buffer
,
163 const StubbedComponent
& component
,
166 for ( size_t i
= 0; i
< component
.symbols
.size () ; i
++ )
167 buffer
= WriteStubbedSymbolToStubsFile ( buffer
,
169 *component
.symbols
[i
],
175 TestSupportCode::WriteStubsFile ( Module
& module
)
180 buf
= (char*) malloc ( 50*1024 );
182 throw OutOfMemoryException ();
185 s
= s
+ sprintf ( s
, "/* This file is automatically generated. */\n" );
186 s
= s
+ sprintf ( s
, "passthrough:\n" );
187 s
= s
+ sprintf ( s
, " call _FrameworkGetHook@4\n" );
188 s
= s
+ sprintf ( s
, " test %%eax, %%eax\n" );
189 s
= s
+ sprintf ( s
, " je .return\n" );
190 s
= s
+ sprintf ( s
, " jmp *%%eax\n" );
191 s
= s
+ sprintf ( s
, ".return:\n" );
192 s
= s
+ sprintf ( s
, " /* This will most likely corrupt the stack */\n" );
193 s
= s
+ sprintf ( s
, " ret\n" );
194 s
= s
+ sprintf ( s
, "\n" );
197 for ( size_t i
= 0; i
< module
.stubbedComponents
.size () ; i
++ )
199 s
= WriteStubbedComponentToStubsFile ( s
,
200 *module
.stubbedComponents
[i
],
204 FileSupportCode::WriteIfChanged ( buf
, GetStubsFilename ( module
) );
210 TestSupportCode::GetStartupFilename ( Module
& module
)
212 return NormalizeFilename ( Environment::GetIntermediatePath () + SSEP
+ module
.GetBasePath () + SSEP
+ "_startup.c" );
216 TestSupportCode::IsUnknownCharacter ( char ch
)
218 if ( ch
>= 'a' && ch
<= 'z' )
220 if ( ch
>= 'A' && ch
<= 'Z' )
222 if ( ch
>= '0' && ch
<= '9' )
228 TestSupportCode::GetTestDispatcherName ( string filename
)
230 string filenamePart
= ReplaceExtension ( GetFilename ( filename
), "" );
231 if ( filenamePart
.length () > 0 )
232 filenamePart
[0] = toupper ( filenamePart
[0] );
233 for ( size_t i
= 1; i
< filenamePart
.length (); i
++ )
235 if ( IsUnknownCharacter ( filenamePart
[i
] ) )
236 filenamePart
[i
] = '_';
238 filenamePart
[i
] = tolower ( filenamePart
[i
] );
240 return filenamePart
+ "Test";
244 TestSupportCode::IsTestFile ( string
& filename
) const
246 if ( stricmp ( GetFilename ( filename
).c_str (), "setup.c" ) == 0 )
252 TestSupportCode::GetSourceFilenames ( string_list
& list
,
253 Module
& module
) const
257 const vector
<File
*>& files
= module
.non_if_data
.files
;
258 for ( i
= 0; i
< files
.size (); i
++ )
260 if ( !files
[i
]->IsGeneratedFile () && IsTestFile ( files
[i
]->name
) )
261 list
.push_back ( files
[i
]->name
);
263 // intentionally make a copy so that we can append more work in
264 // the middle of processing without having to go recursive
265 vector
<If
*> v
= module
.non_if_data
.ifs
;
266 for ( i
= 0; i
< v
.size (); i
++ )
270 // check for sub-ifs to add to list
271 const vector
<If
*>& ifs
= rIf
.data
.ifs
;
272 for ( j
= 0; j
< ifs
.size (); j
++ )
273 v
.push_back ( ifs
[j
] );
274 const vector
<File
*>& files
= rIf
.data
.files
;
275 for ( j
= 0; j
< files
.size (); j
++ )
277 File
& file
= *files
[j
];
278 if ( !file
.IsGeneratedFile () && IsTestFile ( file
.name
) )
280 list
.push_back ( file
.name
);
287 TestSupportCode::WriteTestDispatcherPrototypesToStartupFile ( char* buffer
,
291 GetSourceFilenames ( files
,
293 for ( size_t i
= 0; i
< files
.size (); i
++ )
295 buffer
= buffer
+ sprintf ( buffer
,
296 "extern void %s(int Command, char *Buffer);\n",
297 GetTestDispatcherName ( files
[i
] ).c_str () );
299 buffer
= buffer
+ sprintf ( buffer
, "\n" );
304 TestSupportCode::WriteRegisterTestsFunctionToStartupFile ( char* buffer
,
307 buffer
= buffer
+ sprintf ( buffer
,
308 "extern void AddTest(TestRoutine Routine);\n" );
309 buffer
= buffer
+ sprintf ( buffer
,
312 buffer
= buffer
+ sprintf ( buffer
,
314 buffer
= buffer
+ sprintf ( buffer
,
315 "RegisterTests()\n" );
316 buffer
= buffer
+ sprintf ( buffer
,
320 GetSourceFilenames ( files
,
322 for ( size_t i
= 0; i
< files
.size (); i
++ )
324 buffer
= buffer
+ sprintf ( buffer
,
325 "AddTest((TestRoutine)%s);\n",
326 GetTestDispatcherName ( files
[i
]).c_str () );
328 buffer
= buffer
+ sprintf ( buffer
,
330 buffer
= buffer
+ sprintf ( buffer
, "\n" );
335 TestSupportCode::WriteStartupFile ( Module
& module
)
340 buf
= (char*) malloc ( 50*1024 );
342 throw OutOfMemoryException ();
345 s
= s
+ sprintf ( s
, "/* This file is automatically generated. */\n" );
346 s
= s
+ sprintf ( s
, "\n" );
347 s
= s
+ sprintf ( s
, "#include <windows.h>\n" );
348 s
= s
+ sprintf ( s
, "#include \"regtests.h\"\n" );
349 s
= s
+ sprintf ( s
, "\n" );
350 s
= WriteTestDispatcherPrototypesToStartupFile ( s
,
352 s
= WriteRegisterTestsFunctionToStartupFile ( s
,
354 s
= s
+ sprintf ( s
, "\n" );
355 s
= s
+ sprintf ( s
, "void\n" );
356 s
= s
+ sprintf ( s
, "ConsoleWrite(char *Buffer)\n" );
357 s
= s
+ sprintf ( s
, "{\n" );
358 s
= s
+ sprintf ( s
, " printf(Buffer);\n" );
359 s
= s
+ sprintf ( s
, "}\n" );
360 s
= s
+ sprintf ( s
, "\n" );
361 s
= s
+ sprintf ( s
, "int\n" );
362 s
= s
+ sprintf ( s
, "mainCRTStartup(HANDLE hInstance,\n" );
363 s
= s
+ sprintf ( s
, " HANDLE hPrevInstance,\n" );
364 s
= s
+ sprintf ( s
, " LPSTR lpszCmdParam,\n" );
365 s
= s
+ sprintf ( s
, " int nCmdShow)\n" );
366 s
= s
+ sprintf ( s
, "{\n" );
367 s
= s
+ sprintf ( s
, " _SetPriorityClass(_GetCurrentProcess(), HIGH_PRIORITY_CLASS);\n" );
368 s
= s
+ sprintf ( s
, " _SetThreadPriority(_GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);\n" );
369 s
= s
+ sprintf ( s
, " InitializeTests();\n" );
370 s
= s
+ sprintf ( s
, " RegisterTests();\n" );
371 s
= s
+ sprintf ( s
, " SetupOnce();\n" );
372 s
= s
+ sprintf ( s
, " PerformTests(ConsoleWrite, NULL);\n" );
373 s
= s
+ sprintf ( s
, " _ExitProcess(0);\n" );
374 s
= s
+ sprintf ( s
, " return 0;\n" );
375 s
= s
+ sprintf ( s
, "}\n" );
376 s
= s
+ sprintf ( s
, "\n" );
378 FileSupportCode::WriteIfChanged ( buf
, GetStartupFilename ( module
) );