Generate hooks and stubs for tests
[reactos.git] / reactos / tools / rbuild / testsupportcode.cpp
1 #include "pch.h"
2 #include <assert.h>
3
4 #include "rbuild.h"
5
6 using std::string;
7 using std::vector;
8
9 TestSupportCode::TestSupportCode ( const Project& project )
10 : project ( project )
11 {
12 }
13
14 TestSupportCode::~TestSupportCode ()
15 {
16 }
17
18 bool
19 TestSupportCode::IsTestModule ( const Module& module )
20 {
21 return module.type == Test;
22 }
23
24 void
25 TestSupportCode::GenerateTestSupportCode ( bool verbose )
26 {
27 for ( size_t i = 0; i < project.modules.size (); i++ )
28 {
29 if ( IsTestModule ( *project.modules[i] ) )
30 {
31 GenerateTestSupportCodeForModule ( *project.modules[i],
32 verbose );
33 }
34 }
35 }
36
37 void
38 TestSupportCode::GenerateTestSupportCodeForModule ( Module& module,
39 bool verbose )
40 {
41 if ( verbose )
42 {
43 printf ( "\nGenerating test support code for %s",
44 module.name.c_str () );
45 }
46
47 WriteHooksFile ( module );
48 WriteStubsFile ( module );
49 }
50
51 string
52 TestSupportCode::GetHooksFilename ( Module& module )
53 {
54 return NormalizeFilename ( Environment::GetIntermediatePath () + SSEP + module.GetBasePath () + SSEP + "_hooks.c" );
55 }
56
57 char*
58 TestSupportCode::WriteStubbedSymbolToHooksFile ( char* buffer,
59 const StubbedComponent& component,
60 const StubbedSymbol& symbol )
61 {
62 buffer = buffer + sprintf ( buffer,
63 " {\"%s\", \"%s\", NULL, NULL, NULL},\n",
64 component.name.c_str (),
65 symbol.strippedName.c_str () );
66 return buffer;
67 }
68
69 char*
70 TestSupportCode::WriteStubbedComponentToHooksFile ( char* buffer,
71 const StubbedComponent& component )
72 {
73 for ( size_t i = 0; i < component.symbols.size () ; i++ )
74 buffer = WriteStubbedSymbolToHooksFile ( buffer,
75 component,
76 *component.symbols[i] );
77 return buffer;
78 }
79
80 void
81 TestSupportCode::WriteHooksFile ( Module& module )
82 {
83 char* buf;
84 char* s;
85
86 buf = (char*) malloc ( 50*1024 );
87 if ( buf == NULL )
88 throw OutOfMemoryException ();
89
90 s = buf;
91 s = s + sprintf ( s, "/* This file is automatically generated. */\n" );
92 s = s + sprintf ( s, "#include <windows.h>\n" );
93 s = s + sprintf ( s, "#include \"regtests.h\"\n" );
94 s = s + sprintf ( s, "\n" );
95 s = s + sprintf ( s, "API_DESCRIPTION ExternalDependencies[] =\n" );
96 s = s + sprintf ( s, "{\n" );
97
98 int symbolCount = 0;
99 for ( size_t i = 0; i < module.stubbedComponents.size () ; i++ )
100 {
101 s = WriteStubbedComponentToHooksFile ( s,
102 *module.stubbedComponents[i] );
103 symbolCount += module.stubbedComponents[i]->symbols.size ();
104 }
105
106 s = s + sprintf ( s, "};\n" );
107 s = s + sprintf ( s, "\n" );
108 s = s + sprintf ( s, "#define ExternalDependencyCount %d\n", symbolCount );
109 s = s + sprintf ( s, "ULONG MaxExternalDependency = ExternalDependencyCount - 1;\n" );
110 s = s + sprintf ( s, "\n" );
111
112 FileSupportCode::WriteIfChanged ( buf, GetHooksFilename ( module ) );
113
114 free ( buf );
115 }
116
117 string
118 TestSupportCode::GetStubsFilename ( Module& module )
119 {
120 return NormalizeFilename ( Environment::GetIntermediatePath () + SSEP + module.GetBasePath () + SSEP + "_stubs.S" );
121 }
122
123 char*
124 TestSupportCode::WriteStubbedSymbolToStubsFile ( char* buffer,
125 const StubbedComponent& component,
126 const StubbedSymbol& symbol,
127 int stubIndex )
128 {
129 buffer = buffer + sprintf ( buffer,
130 ".globl _%s\n",
131 symbol.symbol.c_str () );
132 buffer = buffer + sprintf ( buffer,
133 "_%s:\n",
134 symbol.symbol.c_str () );
135 buffer = buffer + sprintf ( buffer,
136 " pushl $%d\n",
137 stubIndex );
138 buffer = buffer + sprintf ( buffer,
139 " jmp passthrough\n" );
140 buffer = buffer + sprintf ( buffer, "\n" );
141 return buffer;
142 }
143
144 char*
145 TestSupportCode::WriteStubbedComponentToStubsFile ( char* buffer,
146 const StubbedComponent& component,
147 int* stubIndex )
148 {
149 for ( size_t i = 0; i < component.symbols.size () ; i++ )
150 buffer = WriteStubbedSymbolToStubsFile ( buffer,
151 component,
152 *component.symbols[i],
153 (*stubIndex)++ );
154 return buffer;
155 }
156
157 void
158 TestSupportCode::WriteStubsFile ( Module& module )
159 {
160 char* buf;
161 char* s;
162
163 buf = (char*) malloc ( 50*1024 );
164 if ( buf == NULL )
165 throw OutOfMemoryException ();
166
167 s = buf;
168 s = s + sprintf ( s, "/* This file is automatically generated. */\n" );
169 s = s + sprintf ( s, "passthrough:\n" );
170 s = s + sprintf ( s, " call _FrameworkGetHook@4\n" );
171 s = s + sprintf ( s, " test %%eax, %%eax\n" );
172 s = s + sprintf ( s, " je .return\n" );
173 s = s + sprintf ( s, " jmp *%%eax\n" );
174 s = s + sprintf ( s, ".return:\n" );
175 s = s + sprintf ( s, " /* This will most likely corrupt the stack */\n" );
176 s = s + sprintf ( s, " ret\n" );
177 s = s + sprintf ( s, "\n" );
178
179 int stubIndex = 0;
180 for ( size_t i = 0; i < module.stubbedComponents.size () ; i++ )
181 {
182 s = WriteStubbedComponentToStubsFile ( s,
183 *module.stubbedComponents[i],
184 &stubIndex );
185 }
186
187 FileSupportCode::WriteIfChanged ( buf, GetStubsFilename ( module ) );
188
189 free ( buf );
190 }