getImageNameHook.m   [plain text]


// TEST_CONFIG

#include "test.h"
#include "testroot.i"

@interface One : TestRoot @end
@implementation One @end

@interface Two : TestRoot @end
@implementation Two @end

@interface Both : TestRoot @end
@implementation Both @end

@interface None : TestRoot @end
@implementation None @end


objc_hook_getImageName OnePreviousHook;
BOOL GetImageNameHookOne(Class cls, const char **outName)
{
    if (0 == strcmp(class_getName(cls), "One")) {
        *outName = "Image One";
        return YES;
    } else if (0 == strcmp(class_getName(cls), "Both")) {
        *outName = "Image Both via One";
        return YES;
    } else {
        return OnePreviousHook(cls, outName);
    }
}

objc_hook_getImageName TwoPreviousHook;
BOOL GetImageNameHookTwo(Class cls, const char **outName)
{
    if (0 == strcmp(class_getName(cls), "Two")) {
        *outName = "Image Two";
        return YES;
    } else if (0 == strcmp(class_getName(cls), "Both")) {
        *outName = "Image Both via Two";
        return YES;
    } else {
        return TwoPreviousHook(cls, outName);
    }
}

int main()
{

    // before hooks: main executable is the image name for four classes
    testassert(strstr(class_getImageName([One class]), "getImageNameHook"));
    testassert(strstr(class_getImageName([Two class]), "getImageNameHook"));
    testassert(strstr(class_getImageName([Both class]), "getImageNameHook"));
    testassert(strstr(class_getImageName([None class]), "getImageNameHook"));
    testassert(strstr(class_getImageName([NSObject class]), "libobjc"));

    // install hook One
    objc_setHook_getImageName(GetImageNameHookOne, &OnePreviousHook);

    // two classes are in Image One with hook One in place
    testassert(strstr(class_getImageName([One class]), "Image One"));
    testassert(strstr(class_getImageName([Two class]), "getImageNameHook"));
    testassert(strstr(class_getImageName([Both class]), "Image Both via One"));
    testassert(strstr(class_getImageName([None class]), "getImageNameHook"));
    testassert(strstr(class_getImageName([NSObject class]), "libobjc"));

    // install hook Two which chains to One
    objc_setHook_getImageName(GetImageNameHookTwo, &TwoPreviousHook);

    // two classes are in Image Two and one in One with both hooks in place
    testassert(strstr(class_getImageName([One class]), "Image One"));
    testassert(strstr(class_getImageName([Two class]), "Image Two"));
    testassert(strstr(class_getImageName([Both class]), "Image Both via Two"));
    testassert(strstr(class_getImageName([None class]), "getImageNameHook"));
    testassert(strstr(class_getImageName([NSObject class]), "libobjc"));

    succeed(__FILE__);
}