/*
* 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"
#import "ObjFW.h"
#import "ObjFWTest.h"
@interface OFSystemInfoTests: OTTestCase
@end
#ifdef OF_HAVE_SOCKETS
static void
appendAddresses(OFMutableString *string, OFData *addresses, bool *firstAddress)
{
size_t count = addresses.count;
for (size_t i = 0; i < count; i++) {
const OFSocketAddress *address = [addresses itemAtIndex: i];
if (!*firstAddress)
[string appendString: @", "];
*firstAddress = false;
[string appendString: OFSocketAddressString(address)];
}
}
#endif
@implementation OFSystemInfoTests
+ (OFArray OF_GENERIC(OFPair OF_GENERIC(OFString *, id) *) *)summary
{
OFMutableArray *summary = [OFMutableArray array];
#ifdef OF_HAVE_SOCKETS
OFDictionary *networkInterfaces;
OFMutableString *networkInterfacesString;
bool firstInterface = true;
#endif
#define ADD(name, value) \
[summary addObject: [OFPair pairWithFirstObject: name \
secondObject: value]];
#define ADD_UINT(name, value) \
ADD(name, [OFNumber numberWithUnsignedInt: value]);
#define ADD_ULONGLONG(name, value) \
ADD(name, [OFNumber numberWithUnsignedLongLong: value]);
#define ADD_BOOL(name, value) \
ADD(name, [OFNumber numberWithBool: value]);
ADD(@"ObjFW version", [OFSystemInfo ObjFWVersion])
ADD_UINT(@"ObjFW version major", [OFSystemInfo ObjFWVersionMajor])
ADD_UINT(@"ObjFW version minor", [OFSystemInfo ObjFWVersionMinor])
ADD(@"Operating system name", [OFSystemInfo operatingSystemName]);
ADD(@"Operating system version", [OFSystemInfo operatingSystemVersion]);
#ifdef OF_WINDOWS
ADD(@"Wine version", [OFSystemInfo wineVersion]);
#endif
ADD_ULONGLONG(@"Page size", [OFSystemInfo pageSize]);
ADD_ULONGLONG(@"Number of CPUs", [OFSystemInfo numberOfCPUs]);
ADD(@"User config IRI", [OFSystemInfo userConfigIRI].string);
ADD(@"User data IRI", [OFSystemInfo userDataIRI].string);
ADD(@"Temporary directory IRI",
[OFSystemInfo temporaryDirectoryIRI].string);
ADD(@"CPU vendor", [OFSystemInfo CPUVendor]);
ADD(@"CPU model", [OFSystemInfo CPUModel]);
#if defined(OF_AMD64) || defined(OF_X86)
ADD_BOOL(@"Supports MMX", [OFSystemInfo supportsMMX]);
ADD_BOOL(@"Supports 3DNow!", [OFSystemInfo supports3DNow]);
ADD_BOOL(@"Supports enhanced 3DNow!",
[OFSystemInfo supportsEnhanced3DNow]);
ADD_BOOL(@"Supports SSE", [OFSystemInfo supportsSSE]);
ADD_BOOL(@"Supports SSE2", [OFSystemInfo supportsSSE2]);
ADD_BOOL(@"Supports SSE3", [OFSystemInfo supportsSSE3]);
ADD_BOOL(@"Supports SSSE3", [OFSystemInfo supportsSSSE3]);
ADD_BOOL(@"Supports SSE4.1", [OFSystemInfo supportsSSE41]);
ADD_BOOL(@"Supports SSE4.2", [OFSystemInfo supportsSSE42]);
ADD_BOOL(@"Supports AVX", [OFSystemInfo supportsAVX]);
ADD_BOOL(@"Supports AVX2", [OFSystemInfo supportsAVX2]);
ADD_BOOL(@"Supports AES-NI", [OFSystemInfo supportsAESNI]);
ADD_BOOL(@"Supports SHA extensions",
[OFSystemInfo supportsSHAExtensions]);
ADD_BOOL(@"Supports fused multiply-add",
[OFSystemInfo supportsFusedMultiplyAdd]);
ADD_BOOL(@"Supports F16C", [OFSystemInfo supportsF16C]);
ADD_BOOL(@"Supports AVX-512 Foundation",
[OFSystemInfo supportsAVX512Foundation]);
ADD_BOOL(@"Supports AVX-512 Conflict Detection Instructions",
[OFSystemInfo supportsAVX512ConflictDetectionInstructions]);
ADD_BOOL(@"Supports AVX-512 Exponential and Reciprocal Instructions",
[OFSystemInfo supportsAVX512ExponentialAndReciprocalInstructions]);
ADD_BOOL(@"Supports AVX-512 Prefetch Instructions",
[OFSystemInfo supportsAVX512PrefetchInstructions]);
ADD_BOOL(@"Supports AVX-512 Vector Length Extensions",
[OFSystemInfo supportsAVX512VectorLengthExtensions]);
ADD_BOOL(@"Supports AVX-512 Doubleword and Quadword Instructions",
[OFSystemInfo supportsAVX512DoublewordAndQuadwordInstructions]);
ADD_BOOL(@"Supports AVX-512 Byte and Word Instructions",
[OFSystemInfo supportsAVX512ByteAndWordInstructions]);
ADD_BOOL(@"Supports AVX-512 Integer Fused Multiply Add",
[OFSystemInfo supportsAVX512IntegerFusedMultiplyAdd]);
ADD_BOOL(@"Supports AVX-512 Vector Byte Manipulation Instructions",
[OFSystemInfo supportsAVX512VectorByteManipulationInstructions]);
ADD_BOOL(@"Supports AVX-512 Vector Population Count Instruction",
[OFSystemInfo supportsAVX512VectorPopulationCountInstruction]);
ADD_BOOL(@"Supports AVX-512 Vector Neutral Network Instructions",
[OFSystemInfo supportsAVX512VectorNeuralNetworkInstructions]);
ADD_BOOL(@"Supports AVX-512 Vector Byte Manipulation Instructions 2",
[OFSystemInfo supportsAVX512VectorByteManipulationInstructions2]);
ADD_BOOL(@"Supports AVX-512 Bit Algorithms",
[OFSystemInfo supportsAVX512BitAlgorithms]);
ADD_BOOL(@"Supports AVX-512 Float16 Instructions",
[OFSystemInfo supportsAVX512Float16Instructions]);
ADD_BOOL(@"Supports AVX-512 BFloat16 Instructions",
[OFSystemInfo supportsAVX512BFloat16Instructions]);
#endif
#ifdef OF_POWERPC
ADD_BOOL(@"Supports AltiVec", [OFSystemInfo supportsAltiVec]);
#endif
#undef ADD
#undef ADD_UINT
#undef ADD_ULONGLONG
#undef ADD_BOOL
#ifdef OF_HAVE_SOCKETS
networkInterfaces = [OFSystemInfo networkInterfaces];
networkInterfacesString = [OFMutableString string];
for (OFString *name in networkInterfaces) {
bool firstAddress = true;
OFNetworkInterface interface;
OFData *hardwareAddress;
if (!firstInterface)
[networkInterfacesString appendString: @"; "];
firstInterface = false;
[networkInterfacesString appendFormat: @"%@(", name];
interface = [networkInterfaces objectForKey: name];
appendAddresses(networkInterfacesString,
[interface objectForKey: OFNetworkInterfaceIPv4Addresses],
&firstAddress);
# ifdef OF_HAVE_IPV6
appendAddresses(networkInterfacesString,
[interface objectForKey: OFNetworkInterfaceIPv6Addresses],
&firstAddress);
# endif
# ifdef OF_HAVE_IPX
appendAddresses(networkInterfacesString,
[interface objectForKey: OFNetworkInterfaceIPXAddresses],
&firstAddress);
# endif
# ifdef OF_HAVE_APPLETALK
appendAddresses(networkInterfacesString,
[interface objectForKey:
OFNetworkInterfaceAppleTalkAddresses], &firstAddress);
# endif
hardwareAddress = [interface
objectForKey: OFNetworkInterfaceHardwareAddress];
if (hardwareAddress != nil) {
const unsigned char *bytes = hardwareAddress.items;
size_t length = hardwareAddress.count;
if (!firstAddress)
[networkInterfacesString appendString: @", "];
for (size_t i = 0; i < length; i++) {
if (i > 0)
[networkInterfacesString
appendString: @":"];
[networkInterfacesString
appendFormat: @"%02X", bytes[i]];
}
}
[networkInterfacesString appendString: @")"];
}
[summary addObject:
[OFPair pairWithFirstObject: @"Network interfaces"
secondObject: networkInterfacesString]];
#endif
return summary;
}
@end