/*
* Copyright (c) 2008-2024 Jonathan Schleifer <js@nil.im>
*
* All rights reserved.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License version 3.0 only,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* version 3.0 for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* version 3.0 along with this program. If not, see
* <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <string.h>
#if !defined(__STDC_NO_COMPLEX__) && defined(HAVE_COMPLEX_H)
# include <complex.h>
#endif
#import "ObjFW.h"
#import "ObjFWTest.h"
@interface OFMethodSignatureTests: OTTestCase
@end
struct Test1Struct {
char c;
int i;
char d;
};
struct Test2Struct {
char c;
struct {
short s;
int i;
} st;
union {
char c;
int i;
} u;
double d;
};
#if !defined(__STDC_NO_COMPLEX__) && defined(HAVE_COMPLEX_H)
struct Test3Struct {
char c;
complex double cd;
};
#endif
union Test3Union {
char c;
int i;
double d;
};
union Test4Union {
char c;
struct {
short x, y;
} st;
int i;
union {
float f;
double d;
} u;
};
@implementation OFMethodSignatureTests
- (void)testSignatureWithObjCTypes
{
OFMethodSignature *methodSignature;
methodSignature =
[OFMethodSignature signatureWithObjCTypes: "i28@0:8S16*20"];
OTAssertEqual(methodSignature.numberOfArguments, 4);
OTAssertEqual(strcmp(methodSignature.methodReturnType, "i"), 0);
OTAssertEqual(strcmp([methodSignature argumentTypeAtIndex: 0], "@"), 0);
OTAssertEqual(strcmp([methodSignature argumentTypeAtIndex: 1], ":"), 0);
OTAssertEqual(strcmp([methodSignature argumentTypeAtIndex: 2], "S"), 0);
OTAssertEqual(strcmp([methodSignature argumentTypeAtIndex: 3], "*"), 0);
OTAssertEqual(methodSignature.frameLength, 28);
OTAssertEqual([methodSignature argumentOffsetAtIndex: 0], 0);
OTAssertEqual([methodSignature argumentOffsetAtIndex: 1], 8);
OTAssertEqual([methodSignature argumentOffsetAtIndex: 2], 16);
OTAssertEqual([methodSignature argumentOffsetAtIndex: 3], 20);
methodSignature = [OFMethodSignature signatureWithObjCTypes:
"{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}24@0:8"
"^{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}16"];
OTAssertEqual(methodSignature.numberOfArguments, 3);
OTAssertEqual(strcmp(methodSignature.methodReturnType,
"{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}"), 0);
OTAssertEqual(strcmp([methodSignature argumentTypeAtIndex: 0], "@"), 0);
OTAssertEqual(strcmp([methodSignature argumentTypeAtIndex: 1], ":"), 0);
OTAssertEqual(strcmp([methodSignature argumentTypeAtIndex: 2],
"^{s0=csi(u1={s2=iii{s3=(u4=ic^v*)}})}"), 0);
OTAssertEqual(methodSignature.frameLength, 24);
OTAssertEqual([methodSignature argumentOffsetAtIndex: 0], 0);
OTAssertEqual([methodSignature argumentOffsetAtIndex: 1], 8);
OTAssertEqual([methodSignature argumentOffsetAtIndex: 2], 16);
}
- (void)testSignatureWithObjCTypesFailsWithInvalidFormat
{
OTAssertThrowsSpecific(
[OFMethodSignature signatureWithObjCTypes: "{ii"],
OFInvalidFormatException);
OTAssertThrowsSpecific([OFMethodSignature signatureWithObjCTypes: ""],
OFInvalidFormatException);
OTAssertThrowsSpecific([OFMethodSignature signatureWithObjCTypes: "0"],
OFInvalidFormatException);
OTAssertThrowsSpecific(
[OFMethodSignature signatureWithObjCTypes: "{{}0"],
OFInvalidFormatException);
}
- (void)testSizeOfTypeEncoding
{
OTAssertEqual(OFSizeOfTypeEncoding(@encode(struct Test1Struct)),
sizeof(struct Test1Struct));
OTAssertEqual(OFSizeOfTypeEncoding(@encode(struct Test2Struct)),
sizeof(struct Test2Struct));
#if !defined(__STDC_NO_COMPLEX__) && defined(HAVE_COMPLEX_H) && \
OF_GCC_VERSION >= 402
OTAssertEqual(OFSizeOfTypeEncoding(@encode(struct Test3Struct)),
sizeof(struct Test3Struct));
#endif
OTAssertEqual(OFSizeOfTypeEncoding(@encode(union Test3Union)),
sizeof(union Test3Union));
OTAssertEqual(OFSizeOfTypeEncoding(@encode(union Test4Union)),
sizeof(union Test4Union));
OTAssertEqual(OFSizeOfTypeEncoding(@encode(struct Test1Struct [5])),
sizeof(struct Test1Struct [5]));
}
- (void)testAlignmentOfTypeEncoding
{
OTAssertEqual(OFAlignmentOfTypeEncoding(@encode(struct Test1Struct)),
OF_ALIGNOF(struct Test1Struct));
OTAssertEqual(OFAlignmentOfTypeEncoding(@encode(struct Test2Struct)),
OF_ALIGNOF(struct Test2Struct));
#if !defined(__STDC_NO_COMPLEX__) && defined(HAVE_COMPLEX_H) && \
OF_GCC_VERSION >= 402
OTAssertEqual(OFAlignmentOfTypeEncoding(@encode(struct Test3Struct)),
OF_ALIGNOF(struct Test3Struct));
#endif
OTAssertEqual(OFAlignmentOfTypeEncoding(@encode(union Test3Union)),
OF_ALIGNOF(union Test3Union));
OTAssertEqual(OFAlignmentOfTypeEncoding(@encode(union Test4Union)),
OF_ALIGNOF(union Test4Union));
OTAssertEqual(
OFAlignmentOfTypeEncoding(@encode(struct Test1Struct [5])),
OF_ALIGNOF(struct Test1Struct [5]));
}
@end