mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 02:25:17 +00:00
Generate hooks and stubs for tests
svn path=/branches/xmlbuildsystem/; revision=15304
This commit is contained in:
parent
c141408f1d
commit
9017f3f4f6
11 changed files with 426 additions and 150 deletions
|
@ -1,3 +1,19 @@
|
|||
<module name="kernel32" type="win32dll" baseaddress="${BASEADDRESS_KERNEL32}" installbase="system32" installname="kernel32.dll">
|
||||
<importlibrary definition="kernel32.def" />
|
||||
<include base="kernel32">.</include>
|
||||
<include base="kernel32">include</include>
|
||||
<define name="_DISABLE_TIDENTS" />
|
||||
<define name="_SEH_NO_NATIVE_NLG" />
|
||||
<define name="WINVER">0x0500</define>
|
||||
<library>kernel32_base</library>
|
||||
<library>pseh</library>
|
||||
<library>rosrtl</library>
|
||||
<library>ntdll</library>
|
||||
<linkerflag>-lgcc</linkerflag>
|
||||
<linkerflag>-nostartfiles</linkerflag>
|
||||
<linkerflag>-nostdlib</linkerflag>
|
||||
<file>kernel32.rc</file>
|
||||
</module>
|
||||
<module name="kernel32_base" type="objectlibrary">
|
||||
<include base="kernel32_base">.</include>
|
||||
<include base="kernel32_base">include</include>
|
||||
|
@ -104,24 +120,8 @@
|
|||
<file>tls.c</file>
|
||||
</directory>
|
||||
</module>
|
||||
<module name="kernel32" type="win32dll" baseaddress="${BASEADDRESS_KERNEL32}" installbase="system32" installname="kernel32.dll">
|
||||
<importlibrary definition="kernel32.def" />
|
||||
<include base="kernel32">.</include>
|
||||
<include base="kernel32">include</include>
|
||||
<define name="_DISABLE_TIDENTS" />
|
||||
<define name="_SEH_NO_NATIVE_NLG" />
|
||||
<define name="WINVER">0x0500</define>
|
||||
<library>kernel32_base</library>
|
||||
<library>pseh</library>
|
||||
<library>rosrtl</library>
|
||||
<library>ntdll</library>
|
||||
<linkerflag>-lgcc</linkerflag>
|
||||
<linkerflag>-nostartfiles</linkerflag>
|
||||
<linkerflag>-nostdlib</linkerflag>
|
||||
<file>kernel32.rc</file>
|
||||
</module>
|
||||
<!--
|
||||
<directory name="tests">
|
||||
<xi:include href="tests/kernel32.xml" />
|
||||
</directory>
|
||||
-->
|
||||
-->
|
|
@ -12,11 +12,11 @@ typedef struct
|
|||
{
|
||||
LPCWSTR lpFileName;
|
||||
DWORD dwDesiredAccess;
|
||||
DWORD dwShareMode;
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes;
|
||||
DWORD dwCreationDisposition;
|
||||
DWORD dwFlagsAndAttributes;
|
||||
HANDLE hTemplateFile;
|
||||
DWORD dwShareMode;
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes;
|
||||
DWORD dwCreationDisposition;
|
||||
DWORD dwFlagsAndAttributes;
|
||||
HANDLE hTemplateFile;
|
||||
} CreateFile_PARAMETERS;
|
||||
|
||||
typedef struct
|
||||
|
@ -93,7 +93,7 @@ MockNtCreateFile(PHANDLE FileHandle,
|
|||
static HOOK NtCreateFileHooks[] =
|
||||
{
|
||||
{"NtCreateFile", MockNtCreateFile},
|
||||
NULL, NULL
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
static void TestFile()
|
||||
|
|
|
@ -41,18 +41,6 @@ v2s ( const string_list& v, int wrap_at )
|
|||
}
|
||||
|
||||
|
||||
/* static */ string
|
||||
Environment::GetVariable ( const string& name )
|
||||
{
|
||||
char* value = getenv ( name.c_str () );
|
||||
if ( value != NULL && strlen ( value ) > 0 )
|
||||
return ssprintf ( "%s",
|
||||
value );
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
Directory::Directory ( const string& name_ )
|
||||
: name(name_)
|
||||
{
|
||||
|
@ -131,45 +119,13 @@ Directory::ReplaceVariable ( string name,
|
|||
return path;
|
||||
}
|
||||
|
||||
/* static */ string
|
||||
Directory::GetEnvironmentVariablePathOrDefault ( const string& name,
|
||||
const string& defaultValue )
|
||||
{
|
||||
const string& environmentVariableValue = Environment::GetVariable ( name );
|
||||
if ( environmentVariableValue.length () > 0 )
|
||||
return NormalizeFilename ( environmentVariableValue );
|
||||
else
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/* static */ string
|
||||
Directory::GetIntermediatePath ()
|
||||
{
|
||||
return GetEnvironmentVariablePathOrDefault ( "ROS_INTERMEDIATE",
|
||||
"obj-i386" );
|
||||
}
|
||||
|
||||
/* static */ string
|
||||
Directory::GetOutputPath ()
|
||||
{
|
||||
return GetEnvironmentVariablePathOrDefault ( "ROS_OUTPUT",
|
||||
"output-i386" );
|
||||
}
|
||||
|
||||
/* static */ string
|
||||
Directory::GetInstallPath ()
|
||||
{
|
||||
return GetEnvironmentVariablePathOrDefault ( "ROS_INSTALL",
|
||||
"reactos" );
|
||||
}
|
||||
|
||||
void
|
||||
Directory::ResolveVariablesInPath ( char* buf,
|
||||
string path )
|
||||
{
|
||||
string s = ReplaceVariable ( "$(INTERMEDIATE)", GetIntermediatePath (), path );
|
||||
s = ReplaceVariable ( "$(OUTPUT)", GetOutputPath (), s );
|
||||
s = ReplaceVariable ( "$(INSTALL)", GetInstallPath (), s );
|
||||
string s = ReplaceVariable ( "$(INTERMEDIATE)", Environment::GetIntermediatePath (), path );
|
||||
s = ReplaceVariable ( "$(OUTPUT)", Environment::GetOutputPath (), s );
|
||||
s = ReplaceVariable ( "$(INSTALL)", Environment::GetInstallPath (), s );
|
||||
strcpy ( buf, s.c_str () );
|
||||
}
|
||||
|
||||
|
@ -217,7 +173,7 @@ Directory::EscapeSpaces ( string path )
|
|||
|
||||
void
|
||||
Directory::CreateRule ( FILE* f,
|
||||
const string& parent )
|
||||
const string& parent )
|
||||
{
|
||||
string path;
|
||||
|
||||
|
@ -356,6 +312,7 @@ MingwBackend::Process ()
|
|||
GenerateDirectoryTargets ();
|
||||
GenerateDirectories ();
|
||||
UnpackWineResources ();
|
||||
GenerateTestSupportCode ();
|
||||
CheckAutomaticDependencies ();
|
||||
CloseMakefile ();
|
||||
}
|
||||
|
@ -641,7 +598,7 @@ MingwBackend::GenerateXmlBuildFilesMacro() const
|
|||
string
|
||||
MingwBackend::GetBin2ResExecutable ()
|
||||
{
|
||||
return NormalizeFilename ( Directory::GetOutputPath () + SSEP + "tools/bin2res/bin2res" + EXEPOSTFIX );
|
||||
return NormalizeFilename ( Environment::GetOutputPath () + SSEP + "tools/bin2res/bin2res" + EXEPOSTFIX );
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -654,6 +611,15 @@ MingwBackend::UnpackWineResources ()
|
|||
printf ( "done\n" );
|
||||
}
|
||||
|
||||
void
|
||||
MingwBackend::GenerateTestSupportCode ()
|
||||
{
|
||||
printf ( "Generating test support code..." );
|
||||
TestSupportCode testSupportCode ( ProjectNode );
|
||||
testSupportCode.GenerateTestSupportCode ( verbose );
|
||||
printf ( "done\n" );
|
||||
}
|
||||
|
||||
void
|
||||
MingwBackend::CheckAutomaticDependencies ()
|
||||
{
|
||||
|
|
|
@ -18,13 +18,6 @@ v2s ( const string_list& v, int wrap_at );
|
|||
typedef std::map<std::string,Directory*> directory_map;
|
||||
|
||||
|
||||
class Environment
|
||||
{
|
||||
public:
|
||||
static std::string GetVariable ( const std::string& name );
|
||||
};
|
||||
|
||||
|
||||
class Directory
|
||||
{
|
||||
public:
|
||||
|
@ -37,17 +30,12 @@ public:
|
|||
std::string EscapeSpaces ( std::string path );
|
||||
void CreateRule ( FILE* f,
|
||||
const std::string& parent );
|
||||
static std::string GetIntermediatePath ();
|
||||
static std::string GetOutputPath ();
|
||||
static std::string GetInstallPath ();
|
||||
private:
|
||||
bool mkdir_p ( const char* path );
|
||||
std::string ReplaceVariable ( std::string name,
|
||||
std::string value,
|
||||
std::string path );
|
||||
std::string GetEnvironmentVariable ( const std::string& name );
|
||||
static std::string GetEnvironmentVariablePathOrDefault ( const std::string& name,
|
||||
const std::string& defaultValue );
|
||||
void ResolveVariablesInPath ( char* buf,
|
||||
std::string path );
|
||||
bool CreateDirectory ( std::string path );
|
||||
|
@ -92,6 +80,7 @@ private:
|
|||
void GenerateXmlBuildFilesMacro() const;
|
||||
std::string GetBin2ResExecutable ();
|
||||
void UnpackWineResources ();
|
||||
void GenerateTestSupportCode ();
|
||||
void CheckAutomaticDependencies ();
|
||||
bool IncludeDirectoryTarget ( const std::string& directory ) const;
|
||||
bool TryToDetectThisCompiler ( const std::string& compiler );
|
||||
|
|
68
reactos/tools/rbuild/filesupportcode.cpp
Normal file
68
reactos/tools/rbuild/filesupportcode.cpp
Normal file
|
@ -0,0 +1,68 @@
|
|||
#include "pch.h"
|
||||
#include <assert.h>
|
||||
|
||||
#include "rbuild.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
/* static */ void
|
||||
FileSupportCode::WriteIfChanged ( char* outbuf,
|
||||
string filename )
|
||||
{
|
||||
FILE* out;
|
||||
unsigned int end;
|
||||
char* cmpbuf;
|
||||
unsigned int stat;
|
||||
|
||||
out = fopen ( filename.c_str (), "rb" );
|
||||
if ( out == NULL )
|
||||
{
|
||||
out = fopen ( filename.c_str (), "wb" );
|
||||
if ( out == NULL )
|
||||
throw AccessDeniedException ( filename );
|
||||
fputs ( outbuf, out );
|
||||
fclose ( out );
|
||||
return;
|
||||
}
|
||||
|
||||
fseek ( out, 0, SEEK_END );
|
||||
end = ftell ( out );
|
||||
cmpbuf = (char*) malloc ( end );
|
||||
if ( cmpbuf == NULL )
|
||||
{
|
||||
fclose ( out );
|
||||
throw OutOfMemoryException ();
|
||||
}
|
||||
|
||||
fseek ( out, 0, SEEK_SET );
|
||||
stat = fread ( cmpbuf, 1, end, out );
|
||||
if ( stat != end )
|
||||
{
|
||||
free ( cmpbuf );
|
||||
fclose ( out );
|
||||
throw AccessDeniedException ( filename );
|
||||
}
|
||||
if ( end == strlen ( outbuf ) && memcmp ( cmpbuf, outbuf, end ) == 0 )
|
||||
{
|
||||
free ( cmpbuf );
|
||||
fclose ( out );
|
||||
return;
|
||||
}
|
||||
|
||||
free ( cmpbuf );
|
||||
fclose ( out );
|
||||
out = fopen ( filename.c_str (), "wb" );
|
||||
if ( out == NULL )
|
||||
{
|
||||
throw AccessDeniedException ( filename );
|
||||
}
|
||||
|
||||
stat = fwrite ( outbuf, 1, strlen ( outbuf ), out);
|
||||
if ( strlen ( outbuf ) != stat )
|
||||
{
|
||||
fclose ( out );
|
||||
throw AccessDeniedException ( filename );
|
||||
}
|
||||
|
||||
fclose ( out );
|
||||
}
|
|
@ -7,6 +7,50 @@
|
|||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
/* static */ string
|
||||
Environment::GetVariable ( const string& name )
|
||||
{
|
||||
char* value = getenv ( name.c_str () );
|
||||
if ( value != NULL && strlen ( value ) > 0 )
|
||||
return ssprintf ( "%s",
|
||||
value );
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
/* static */ string
|
||||
Environment::GetEnvironmentVariablePathOrDefault ( const string& name,
|
||||
const string& defaultValue )
|
||||
{
|
||||
const string& environmentVariableValue = Environment::GetVariable ( name );
|
||||
if ( environmentVariableValue.length () > 0 )
|
||||
return NormalizeFilename ( environmentVariableValue );
|
||||
else
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/* static */ string
|
||||
Environment::GetIntermediatePath ()
|
||||
{
|
||||
return GetEnvironmentVariablePathOrDefault ( "ROS_INTERMEDIATE",
|
||||
"obj-i386" );
|
||||
}
|
||||
|
||||
/* static */ string
|
||||
Environment::GetOutputPath ()
|
||||
{
|
||||
return GetEnvironmentVariablePathOrDefault ( "ROS_OUTPUT",
|
||||
"output-i386" );
|
||||
}
|
||||
|
||||
/* static */ string
|
||||
Environment::GetInstallPath ()
|
||||
{
|
||||
return GetEnvironmentVariablePathOrDefault ( "ROS_INSTALL",
|
||||
"reactos" );
|
||||
}
|
||||
|
||||
|
||||
Project::Project ( const string& filename )
|
||||
: xmlfile (filename),
|
||||
node (NULL),
|
||||
|
@ -41,68 +85,6 @@ Project::LookupProperty ( const string& name ) const
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
Project::WriteIfChanged ( char* outbuf,
|
||||
string filename )
|
||||
{
|
||||
FILE* out;
|
||||
unsigned int end;
|
||||
char* cmpbuf;
|
||||
unsigned int stat;
|
||||
|
||||
out = fopen ( filename.c_str (), "rb" );
|
||||
if ( out == NULL )
|
||||
{
|
||||
out = fopen ( filename.c_str (), "wb" );
|
||||
if ( out == NULL )
|
||||
throw AccessDeniedException ( filename );
|
||||
fputs ( outbuf, out );
|
||||
fclose ( out );
|
||||
return;
|
||||
}
|
||||
|
||||
fseek ( out, 0, SEEK_END );
|
||||
end = ftell ( out );
|
||||
cmpbuf = (char*) malloc ( end );
|
||||
if ( cmpbuf == NULL )
|
||||
{
|
||||
fclose ( out );
|
||||
throw OutOfMemoryException ();
|
||||
}
|
||||
|
||||
fseek ( out, 0, SEEK_SET );
|
||||
stat = fread ( cmpbuf, 1, end, out );
|
||||
if ( stat != end )
|
||||
{
|
||||
free ( cmpbuf );
|
||||
fclose ( out );
|
||||
throw AccessDeniedException ( filename );
|
||||
}
|
||||
if ( end == strlen ( outbuf ) && memcmp ( cmpbuf, outbuf, end ) == 0 )
|
||||
{
|
||||
free ( cmpbuf );
|
||||
fclose ( out );
|
||||
return;
|
||||
}
|
||||
|
||||
free ( cmpbuf );
|
||||
fclose ( out );
|
||||
out = fopen ( filename.c_str (), "wb" );
|
||||
if ( out == NULL )
|
||||
{
|
||||
throw AccessDeniedException ( filename );
|
||||
}
|
||||
|
||||
stat = fwrite ( outbuf, 1, strlen ( outbuf ), out);
|
||||
if ( strlen ( outbuf ) != stat )
|
||||
{
|
||||
fclose ( out );
|
||||
throw AccessDeniedException ( filename );
|
||||
}
|
||||
|
||||
fclose ( out );
|
||||
}
|
||||
|
||||
void
|
||||
Project::SetConfigurationOption ( char* s,
|
||||
string name,
|
||||
|
@ -161,7 +143,7 @@ Project::WriteConfigurationFile ()
|
|||
|
||||
s = s + sprintf ( s, "#endif /* __INCLUDE_CONFIG_H */\n" );
|
||||
|
||||
WriteIfChanged ( buf, "include" SSEP "roscfg.h" );
|
||||
FileSupportCode::WriteIfChanged ( buf, "include" SSEP "roscfg.h" );
|
||||
|
||||
free ( buf );
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@ class If;
|
|||
class CompilerFlag;
|
||||
class LinkerFlag;
|
||||
class Property;
|
||||
class TestSupportCode;
|
||||
class WineResource;
|
||||
class AutomaticDependency;
|
||||
class Bootstrap;
|
||||
|
@ -66,6 +67,25 @@ class StubbedSymbol;
|
|||
|
||||
class SourceFileTest;
|
||||
|
||||
|
||||
class Environment
|
||||
{
|
||||
public:
|
||||
static std::string GetVariable ( const std::string& name );
|
||||
static std::string GetIntermediatePath ();
|
||||
static std::string GetOutputPath ();
|
||||
static std::string GetInstallPath ();
|
||||
static std::string GetEnvironmentVariablePathOrDefault ( const std::string& name,
|
||||
const std::string& defaultValue );
|
||||
};
|
||||
|
||||
class FileSupportCode
|
||||
{
|
||||
public:
|
||||
static void WriteIfChanged ( char* outbuf,
|
||||
std::string filename );
|
||||
};
|
||||
|
||||
class IfableData
|
||||
{
|
||||
public:
|
||||
|
@ -110,8 +130,6 @@ private:
|
|||
std::string* alternativeName );
|
||||
void SetConfigurationOption ( char* s,
|
||||
std::string name );
|
||||
void WriteIfChanged ( char* outbuf,
|
||||
std::string filename );
|
||||
void ReadXml ();
|
||||
void ProcessXMLSubElement ( const XMLElement& e,
|
||||
const std::string& path,
|
||||
|
@ -422,6 +440,37 @@ public:
|
|||
};
|
||||
|
||||
|
||||
class TestSupportCode
|
||||
{
|
||||
public:
|
||||
const Project& project;
|
||||
|
||||
TestSupportCode ( const Project& project );
|
||||
~TestSupportCode ();
|
||||
void GenerateTestSupportCode ( bool verbose );
|
||||
private:
|
||||
bool IsTestModule ( const Module& module );
|
||||
void GenerateTestSupportCodeForModule ( Module& module,
|
||||
bool verbose );
|
||||
std::string GetHooksFilename ( Module& module );
|
||||
char* WriteStubbedSymbolToHooksFile ( char* buffer,
|
||||
const StubbedComponent& component,
|
||||
const StubbedSymbol& symbol );
|
||||
char* WriteStubbedComponentToHooksFile ( char* buffer,
|
||||
const StubbedComponent& component );
|
||||
void WriteHooksFile ( Module& module );
|
||||
std::string GetStubsFilename ( Module& module );
|
||||
char* WriteStubbedSymbolToStubsFile ( char* buffer,
|
||||
const StubbedComponent& component,
|
||||
const StubbedSymbol& symbol,
|
||||
int stubIndex );
|
||||
char* WriteStubbedComponentToStubsFile ( char* buffer,
|
||||
const StubbedComponent& component,
|
||||
int* stubIndex );
|
||||
void WriteStubsFile ( Module& module );
|
||||
};
|
||||
|
||||
|
||||
class WineResource
|
||||
{
|
||||
public:
|
||||
|
@ -610,10 +659,13 @@ public:
|
|||
const XMLElement& node;
|
||||
std::string symbol;
|
||||
std::string newname;
|
||||
std::string strippedName;
|
||||
|
||||
StubbedSymbol ( const XMLElement& stubbedSymbolNode );
|
||||
~StubbedSymbol ();
|
||||
void ProcessXML();
|
||||
private:
|
||||
std::string StripSymbol ( std::string symbol );
|
||||
};
|
||||
|
||||
extern std::string
|
||||
|
|
|
@ -116,6 +116,7 @@ RBUILD_COMMON_SOURCES = \
|
|||
compilerflag.cpp \
|
||||
define.cpp \
|
||||
exception.cpp \
|
||||
filesupportcode.cpp \
|
||||
include.cpp \
|
||||
installfile.cpp \
|
||||
linkerflag.cpp \
|
||||
|
@ -123,6 +124,7 @@ RBUILD_COMMON_SOURCES = \
|
|||
project.cpp \
|
||||
ssprintf.cpp \
|
||||
stubbedcomponent.cpp \
|
||||
testsupportcode.cpp \
|
||||
wineresource.cpp \
|
||||
XML.cpp \
|
||||
)
|
||||
|
@ -230,6 +232,10 @@ $(RBUILD_INT_)exception.o: $(RBUILD_BASE_)exception.cpp $(RBUILD_HEADERS) | $(RB
|
|||
$(ECHO_CC)
|
||||
${host_gpp} $(RBUILD_HOST_CXXFLAGS) -c $< -o $@
|
||||
|
||||
$(RBUILD_INT_)filesupportcode.o: $(RBUILD_BASE_)filesupportcode.cpp $(RBUILD_HEADERS) | $(RBUILD_INT)
|
||||
$(ECHO_CC)
|
||||
${host_gpp} $(RBUILD_HOST_CXXFLAGS) -c $< -o $@
|
||||
|
||||
$(RBUILD_INT_)include.o: $(RBUILD_BASE_)include.cpp $(RBUILD_HEADERS) | $(RBUILD_INT)
|
||||
$(ECHO_CC)
|
||||
${host_gpp} $(RBUILD_HOST_CXXFLAGS) -c $< -o $@
|
||||
|
@ -266,6 +272,10 @@ $(RBUILD_INT_)wineresource.o: $(RBUILD_BASE_)wineresource.cpp $(RBUILD_HEADERS)
|
|||
$(ECHO_CC)
|
||||
${host_gpp} $(RBUILD_HOST_CXXFLAGS) -c $< -o $@
|
||||
|
||||
$(RBUILD_INT_)testsupportcode.o: $(RBUILD_BASE_)testsupportcode.cpp $(RBUILD_HEADERS) | $(RBUILD_INT)
|
||||
$(ECHO_CC)
|
||||
${host_gpp} $(RBUILD_HOST_CXXFLAGS) -c $< -o $@
|
||||
|
||||
$(RBUILD_INT_)XML.o: $(RBUILD_BASE_)XML.cpp $(RBUILD_HEADERS) | $(RBUILD_INT)
|
||||
$(ECHO_CC)
|
||||
${host_gpp} $(RBUILD_HOST_CXXFLAGS) -c $< -o $@
|
||||
|
|
|
@ -77,4 +77,23 @@ StubbedSymbol::ProcessXML ()
|
|||
newname = att->value;
|
||||
else
|
||||
newname = symbol;
|
||||
|
||||
strippedName = StripSymbol ( symbol );
|
||||
}
|
||||
|
||||
string
|
||||
StubbedSymbol::StripSymbol ( string symbol )
|
||||
{
|
||||
size_t start = 0;
|
||||
while ( start < symbol.length () && symbol[start] == '@')
|
||||
start++;
|
||||
size_t end = symbol.length () - 1;
|
||||
while ( end > 0 && isdigit ( symbol[end] ) )
|
||||
end--;
|
||||
if ( end > 0 and symbol[end] == '@' )
|
||||
end--;
|
||||
if ( end > 0 )
|
||||
return symbol.substr ( start, end - start + 1 );
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
|
190
reactos/tools/rbuild/testsupportcode.cpp
Normal file
190
reactos/tools/rbuild/testsupportcode.cpp
Normal file
|
@ -0,0 +1,190 @@
|
|||
#include "pch.h"
|
||||
#include <assert.h>
|
||||
|
||||
#include "rbuild.h"
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
TestSupportCode::TestSupportCode ( const Project& project )
|
||||
: project ( project )
|
||||
{
|
||||
}
|
||||
|
||||
TestSupportCode::~TestSupportCode ()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
TestSupportCode::IsTestModule ( const Module& module )
|
||||
{
|
||||
return module.type == Test;
|
||||
}
|
||||
|
||||
void
|
||||
TestSupportCode::GenerateTestSupportCode ( bool verbose )
|
||||
{
|
||||
for ( size_t i = 0; i < project.modules.size (); i++ )
|
||||
{
|
||||
if ( IsTestModule ( *project.modules[i] ) )
|
||||
{
|
||||
GenerateTestSupportCodeForModule ( *project.modules[i],
|
||||
verbose );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TestSupportCode::GenerateTestSupportCodeForModule ( Module& module,
|
||||
bool verbose )
|
||||
{
|
||||
if ( verbose )
|
||||
{
|
||||
printf ( "\nGenerating test support code for %s",
|
||||
module.name.c_str () );
|
||||
}
|
||||
|
||||
WriteHooksFile ( module );
|
||||
WriteStubsFile ( module );
|
||||
}
|
||||
|
||||
string
|
||||
TestSupportCode::GetHooksFilename ( Module& module )
|
||||
{
|
||||
return NormalizeFilename ( Environment::GetIntermediatePath () + SSEP + module.GetBasePath () + SSEP + "_hooks.c" );
|
||||
}
|
||||
|
||||
char*
|
||||
TestSupportCode::WriteStubbedSymbolToHooksFile ( char* buffer,
|
||||
const StubbedComponent& component,
|
||||
const StubbedSymbol& symbol )
|
||||
{
|
||||
buffer = buffer + sprintf ( buffer,
|
||||
" {\"%s\", \"%s\", NULL, NULL, NULL},\n",
|
||||
component.name.c_str (),
|
||||
symbol.strippedName.c_str () );
|
||||
return buffer;
|
||||
}
|
||||
|
||||
char*
|
||||
TestSupportCode::WriteStubbedComponentToHooksFile ( char* buffer,
|
||||
const StubbedComponent& component )
|
||||
{
|
||||
for ( size_t i = 0; i < component.symbols.size () ; i++ )
|
||||
buffer = WriteStubbedSymbolToHooksFile ( buffer,
|
||||
component,
|
||||
*component.symbols[i] );
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void
|
||||
TestSupportCode::WriteHooksFile ( Module& module )
|
||||
{
|
||||
char* buf;
|
||||
char* s;
|
||||
|
||||
buf = (char*) malloc ( 50*1024 );
|
||||
if ( buf == NULL )
|
||||
throw OutOfMemoryException ();
|
||||
|
||||
s = buf;
|
||||
s = s + sprintf ( s, "/* This file is automatically generated. */\n" );
|
||||
s = s + sprintf ( s, "#include <windows.h>\n" );
|
||||
s = s + sprintf ( s, "#include \"regtests.h\"\n" );
|
||||
s = s + sprintf ( s, "\n" );
|
||||
s = s + sprintf ( s, "API_DESCRIPTION ExternalDependencies[] =\n" );
|
||||
s = s + sprintf ( s, "{\n" );
|
||||
|
||||
int symbolCount = 0;
|
||||
for ( size_t i = 0; i < module.stubbedComponents.size () ; i++ )
|
||||
{
|
||||
s = WriteStubbedComponentToHooksFile ( s,
|
||||
*module.stubbedComponents[i] );
|
||||
symbolCount += module.stubbedComponents[i]->symbols.size ();
|
||||
}
|
||||
|
||||
s = s + sprintf ( s, "};\n" );
|
||||
s = s + sprintf ( s, "\n" );
|
||||
s = s + sprintf ( s, "#define ExternalDependencyCount %d\n", symbolCount );
|
||||
s = s + sprintf ( s, "ULONG MaxExternalDependency = ExternalDependencyCount - 1;\n" );
|
||||
s = s + sprintf ( s, "\n" );
|
||||
|
||||
FileSupportCode::WriteIfChanged ( buf, GetHooksFilename ( module ) );
|
||||
|
||||
free ( buf );
|
||||
}
|
||||
|
||||
string
|
||||
TestSupportCode::GetStubsFilename ( Module& module )
|
||||
{
|
||||
return NormalizeFilename ( Environment::GetIntermediatePath () + SSEP + module.GetBasePath () + SSEP + "_stubs.S" );
|
||||
}
|
||||
|
||||
char*
|
||||
TestSupportCode::WriteStubbedSymbolToStubsFile ( char* buffer,
|
||||
const StubbedComponent& component,
|
||||
const StubbedSymbol& symbol,
|
||||
int stubIndex )
|
||||
{
|
||||
buffer = buffer + sprintf ( buffer,
|
||||
".globl _%s\n",
|
||||
symbol.symbol.c_str () );
|
||||
buffer = buffer + sprintf ( buffer,
|
||||
"_%s:\n",
|
||||
symbol.symbol.c_str () );
|
||||
buffer = buffer + sprintf ( buffer,
|
||||
" pushl $%d\n",
|
||||
stubIndex );
|
||||
buffer = buffer + sprintf ( buffer,
|
||||
" jmp passthrough\n" );
|
||||
buffer = buffer + sprintf ( buffer, "\n" );
|
||||
return buffer;
|
||||
}
|
||||
|
||||
char*
|
||||
TestSupportCode::WriteStubbedComponentToStubsFile ( char* buffer,
|
||||
const StubbedComponent& component,
|
||||
int* stubIndex )
|
||||
{
|
||||
for ( size_t i = 0; i < component.symbols.size () ; i++ )
|
||||
buffer = WriteStubbedSymbolToStubsFile ( buffer,
|
||||
component,
|
||||
*component.symbols[i],
|
||||
(*stubIndex)++ );
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void
|
||||
TestSupportCode::WriteStubsFile ( Module& module )
|
||||
{
|
||||
char* buf;
|
||||
char* s;
|
||||
|
||||
buf = (char*) malloc ( 50*1024 );
|
||||
if ( buf == NULL )
|
||||
throw OutOfMemoryException ();
|
||||
|
||||
s = buf;
|
||||
s = s + sprintf ( s, "/* This file is automatically generated. */\n" );
|
||||
s = s + sprintf ( s, "passthrough:\n" );
|
||||
s = s + sprintf ( s, " call _FrameworkGetHook@4\n" );
|
||||
s = s + sprintf ( s, " test %%eax, %%eax\n" );
|
||||
s = s + sprintf ( s, " je .return\n" );
|
||||
s = s + sprintf ( s, " jmp *%%eax\n" );
|
||||
s = s + sprintf ( s, ".return:\n" );
|
||||
s = s + sprintf ( s, " /* This will most likely corrupt the stack */\n" );
|
||||
s = s + sprintf ( s, " ret\n" );
|
||||
s = s + sprintf ( s, "\n" );
|
||||
|
||||
int stubIndex = 0;
|
||||
for ( size_t i = 0; i < module.stubbedComponents.size () ; i++ )
|
||||
{
|
||||
s = WriteStubbedComponentToStubsFile ( s,
|
||||
*module.stubbedComponents[i],
|
||||
&stubIndex );
|
||||
}
|
||||
|
||||
FileSupportCode::WriteIfChanged ( buf, GetStubsFilename ( module ) );
|
||||
|
||||
free ( buf );
|
||||
}
|
|
@ -82,7 +82,7 @@ WineResource::UnpackResourcesInModule ( Module& module,
|
|||
|
||||
if ( verbose )
|
||||
{
|
||||
printf ( "Unpacking resources for %s",
|
||||
printf ( "\nUnpacking resources for %s",
|
||||
module.name.c_str () );
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue