darling-objc4/test/methodCacheLeaks.m
2022-03-31 21:15:07 -07:00

71 lines
1.6 KiB
Objective-C

// TEST_CONFIG MEM=mrc LANGUAGE=objective-c
/*
TEST_RUN_OUTPUT
[\S\s]*0 leaks for 0 total leaked bytes[\S\s]*
END
*/
#include "test.h"
#include "testroot.i"
#include <spawn.h>
#include <stdio.h>
void noopIMP(id self __unused, SEL _cmd __unused) {}
id test(int n, int methodCount) {
char *name;
asprintf(&name, "TestClass%d", n);
Class c = objc_allocateClassPair([TestRoot class], name, 0);
free(name);
SEL *sels = malloc(methodCount * sizeof(*sels));
for(int i = 0; i < methodCount; i++) {
asprintf(&name, "selector%d", i);
sels[i] = sel_getUid(name);
free(name);
}
for(int i = 0; i < methodCount; i++) {
class_addMethod(c, sels[i], (IMP)noopIMP, "v@:");
}
objc_registerClassPair(c);
id obj = [[c alloc] init];
for (int i = 0; i < methodCount; i++) {
((void (*)(id, SEL))objc_msgSend)(obj, sels[i]);
}
free(sels);
return obj;
}
int main()
{
int classCount = 16;
id *objs = malloc(classCount * sizeof(*objs));
for (int i = 0; i < classCount; i++) {
objs[i] = test(i, 1 << i);
}
char *pidstr;
int result = asprintf(&pidstr, "%u", getpid());
testassert(result);
extern char **environ;
char *argv[] = { "/usr/bin/leaks", pidstr, NULL };
pid_t pid;
result = posix_spawn(&pid, "/usr/bin/leaks", NULL, NULL, argv, environ);
if (result) {
perror("posix_spawn");
exit(1);
}
wait4(pid, NULL, 0, NULL);
// Clean up. Otherwise leaks can end up seeing this as a leak, oddly enough.
for (int i = 0; i < classCount; i++) {
[objs[i] release];
}
free(objs);
}