177 lines
5.0 KiB
Plaintext
177 lines
5.0 KiB
Plaintext
// This file is part of VSTGUI. It is subject to the license terms
|
|
// in the LICENSE file found in the top-level directory of this
|
|
// distribution and at http://github.com/steinbergmedia/vstgui/LICENSE
|
|
|
|
#import <XCTest/XCTest.h>
|
|
#import <objc/message.h>
|
|
#import <objc/runtime.h>
|
|
|
|
#import "../../lib/cstring.h"
|
|
#import "../../lib/vstguiinit.h"
|
|
#import "unittests.h"
|
|
|
|
#import <functional>
|
|
#import <string>
|
|
#import <unordered_map>
|
|
#import <vector>
|
|
|
|
using namespace VSTGUI::UnitTest;
|
|
|
|
//------------------------------------------------------------------------
|
|
void setupFunc (id self, SEL _cmd)
|
|
{
|
|
auto cls = [self class];
|
|
std::string clsName (class_getName (cls) + 7);
|
|
auto testSuite = UnitTestRegistry::instance ().find (clsName);
|
|
assert (testSuite);
|
|
auto ivar = class_getInstanceVariable ([self class], "_testSuite");
|
|
object_setIvar (self, ivar, reinterpret_cast<id> (testSuite));
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
void testFunc (id self, SEL _cmd)
|
|
{
|
|
auto ivar = class_getInstanceVariable ([self class], "_testSuite");
|
|
auto testSuite = reinterpret_cast<TestSuite*> (object_getIvar (self, ivar));
|
|
auto name = std::string (sel_getName (_cmd) + 4);
|
|
auto it = std::find_if (testSuite->begin (), testSuite->end (),
|
|
[&] (auto& pair) { return pair.first == name; });
|
|
assert (it != testSuite->end ());
|
|
|
|
struct TestContext : Context
|
|
{
|
|
TestContext (TestSuite& suite) : suite (suite) {}
|
|
void printRaw (const char* str) override { text += str; }
|
|
std::any& storage () override { return suite.getStorage (); }
|
|
TestSuite& suite;
|
|
std::string text;
|
|
} context (*testSuite);
|
|
|
|
size_t assertLineNo = 0;
|
|
std::string assertFilePath;
|
|
|
|
bool result = true;
|
|
|
|
try
|
|
{
|
|
if (auto setup = testSuite->setup ())
|
|
setup (&context);
|
|
|
|
try
|
|
{
|
|
it->second (&context);
|
|
}
|
|
catch (...)
|
|
{
|
|
if (auto teardown = testSuite->teardown ())
|
|
teardown (&context);
|
|
throw;
|
|
}
|
|
|
|
if (auto teardown = testSuite->teardown ())
|
|
teardown (&context);
|
|
}
|
|
catch (const error& exc)
|
|
{
|
|
result = false;
|
|
context.print ("%s", exc.what () ? exc.what () : "unknown");
|
|
assertLineNo = exc.lineNo;
|
|
assertFilePath = exc.filePath;
|
|
}
|
|
catch (const std::logic_error& exc)
|
|
{
|
|
result = false;
|
|
context.print ("%s", exc.what () ? exc.what () : "unknown");
|
|
}
|
|
catch (const std::exception& exc)
|
|
{
|
|
result = false;
|
|
context.print ("Exception: %s", exc.what () ? exc.what () : "unknown");
|
|
}
|
|
if (!result)
|
|
{
|
|
#ifdef MAC_OS_VERSION_11_0
|
|
auto sourceCodeLocation = [[[XCTSourceCodeLocation alloc]
|
|
initWithFilePath:[NSString stringWithUTF8String:assertFilePath.data ()]
|
|
lineNumber:assertLineNo] autorelease];
|
|
auto sourceCodeContext =
|
|
[[[XCTSourceCodeContext alloc] initWithLocation:sourceCodeLocation] autorelease];
|
|
auto issue =
|
|
[[[XCTIssue alloc] initWithType:XCTIssueTypeAssertionFailure
|
|
compactDescription:[NSString stringWithUTF8String:context.text.data ()]
|
|
detailedDescription:nullptr
|
|
sourceCodeContext:sourceCodeContext
|
|
associatedError:nullptr
|
|
attachments:@[]] autorelease];
|
|
|
|
[self recordIssue:issue];
|
|
#else
|
|
|
|
[self recordFailureWithDescription:[NSString stringWithUTF8String:context.text.data ()]
|
|
inFile:[NSString stringWithUTF8String:assertFilePath.data ()]
|
|
atLine:assertLineNo
|
|
expected:NO];
|
|
#endif
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
@interface VSTGUITestCaseFactory : XCTestCase
|
|
@end
|
|
|
|
@implementation VSTGUITestCaseFactory
|
|
|
|
//------------------------------------------------------------------------
|
|
+ (void)initialize
|
|
{
|
|
VSTGUI::setAssertionHandler (
|
|
[] (const char* file, const char* line, const char* condition, const char* desc) {
|
|
size_t lineNo = 0;
|
|
if (line)
|
|
{
|
|
if (auto l = VSTGUI::UTF8StringView (line).toNumber<size_t> ())
|
|
lineNo = *l;
|
|
}
|
|
std::string text;
|
|
if (desc)
|
|
{
|
|
text = desc;
|
|
}
|
|
else
|
|
{
|
|
text = "Assertion: '";
|
|
text += condition;
|
|
text += "' failed.";
|
|
}
|
|
throw VSTGUI::UnitTest::error (file, lineNo, text.data ());
|
|
});
|
|
VSTGUI::init (CFBundleGetMainBundle ());
|
|
|
|
auto baseClass = objc_getClass ("XCTestCase");
|
|
for (auto& testCase : UnitTestRegistry::instance ())
|
|
{
|
|
std::string className = "VSTGUI_" + testCase.getName ();
|
|
auto cls = objc_allocateClassPair (baseClass, className.data (), 0);
|
|
if (!cls)
|
|
{
|
|
NSLog (@"Duplicate TestCase name: %s", testCase.getName ().data ());
|
|
continue;
|
|
}
|
|
class_addIvar (cls, "_testSuite", sizeof (void*), (uint8_t)log2 (sizeof (void*)),
|
|
@encode (void*));
|
|
class_addMethod (cls, @selector (setUp), reinterpret_cast<IMP> (setupFunc), "v@:");
|
|
for (auto& test : testCase)
|
|
{
|
|
std::string name = "test" + test.first;
|
|
auto sel = sel_registerName (name.data ());
|
|
if (!class_addMethod (cls, sel, reinterpret_cast<IMP> (testFunc), "v@:"))
|
|
{
|
|
NSLog (@"Duplicate Method name: %s [%s]", name.data (), className.data ());
|
|
}
|
|
}
|
|
objc_registerClassPair (cls);
|
|
}
|
|
}
|
|
|
|
@end
|