licencecoreTests.m

This file can be downloaded as part of milnlicence.tbz.

//
//  licencecoreTests.m
//  LicenceCore - https://indie.miln.eu
//
//  Copyright © Graham Miln. All rights reserved. https://miln.eu
//
//  This package is subject to the terms of the Artistic License 2.0.
//  If a copy of the Artistic-2.0 was not distributed with this file, you can
//  obtain one at https://indie.miln.eu/licence

#import <XCTest/XCTest.h>
@import LicenceCore;

static NSString* rootPEM = @"-----BEGIN CERTIFICATE-----\nMIIFSDCCAzagAwIBAgIBATANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJGUjEX\nMBUGA1UEChMOTXkgQ29tcGFueSBJbmMxHzAdBgNVBAMTFk15IENvbXBhbnkgSW5j\nIFJvb3QgQ0ExEjAQBgNVBAUTCTEyMzEyMzEyMzAeFw0xODA3MjIwOTIyMjhaFw0z\nODA3MTcwOTIyMjhaMFsxCzAJBgNVBAYTAkZSMRcwFQYDVQQKEw5NeSBDb21wYW55\nIEluYzEfMB0GA1UEAxMWTXkgQ29tcGFueSBJbmMgUm9vdCBDQTESMBAGA1UEBRMJ\nMTIzMTIzMTIzMIICHDANBgkqhkiG9w0BAQEFAAOCAgkAMIICBAKCAfsA7Z4DbNkB\ni8XvK8jjFLujp8TYvmIBhxpqw4IyIRwkADEzcpivOxhRSTwiqRFOsgiCbPqaJ9WO\nUS+U3D19WCf5RT+edsvWqfOzK38wyyt7A80SVv/3Z7/c+YIEaPtUNbc11tXiOzMm\nUxb33oktHykRrgEsNm2GnkQvjV92KmdTpRLzUlbho9pHCpHqfDPGpcJjEQKHxMOM\nmNn+NUhJ9OzwfSmvFd/WuGYzFqmF+A4IZA5PEvIQNIxu8KsS+OL7Zs/aIy1bkWG5\neMUupWvJAbal6zrMsMP+lDGyoZ6fHzKgFHf56AyyjIa6wP9sVDrp1dusrDqR8/US\nBDoQktELNEmvLkfWSUBvfl18UnY7ZjbuSUCAGT3SrEQ+SP2IUxTlUOH83rYRyFQM\n/sgqkCjdJ8EBf32rWoKGNq1fFq5DJeUdX5sIsasC0t7AorxsJpqVa79b5DFXY1Om\nqWZo8QzoP2D3nwqM2ho67xM207giAYqnTpZ5kCDhAz+n4x4JOxOGPn+Yt/40IRsX\nkZxTRu0B5UmbEVrJVc4ymMUYobG9okb78gtddZY4fA374eURga0fGGVqAxiC/w7D\n8v2SGFq/XOPXswhyibXqtiA/q29Nuhis0KOIDzzBrI/qkLbpCcKmbsBQ5UAxX2gN\nBYkLK7IHVpoTlpFi9qb3x7jmxksCAwEAAaMjMCEwDgYDVR0PAQH/BAQDAgGGMA8G\nA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggH7AGHNdvKn3v1Jo+yTTFCf\nNRMlAhdijLW9Tl1hV8tm2yBCbkM+c8evrfSeo9wDaEmipSGNhuZbL2IcNFDpzcXG\nH9WnmQqDnKdtQoSg18PINb32rmvtFBN816APL14Rp+2yP1wr1i9UDANSzEzneBwn\nTrwxt0vWRpvXeSM+Xuwv7CjMVmp5cIv3Sum9o23i+zXePwaLgaY8zEv+o2qArCNm\nnVHsI3J6Si+Ead2LHH/hIU4TKcAH8yp/WKmXf2z3C1Ew2thh8u9NNNIU7iA2gKSi\nANz+OY9WfI+sXbiXUO8lMZc9LIEJbStCzg1mOd0x9AWZc0GL71viJWamijEUW3gD\n9m4Rwtm15h4pbMeSjAwoCPHy9ab+vKcihhuQQuZNl1l7J2aK9lY8hp5RkdfcqhBU\nQ6D6Jazni43nTLNTurO2Dw7b9kSwGTmQ1zI8RhgToiqJX2eTSU9j+5V0bqqyZKIR\nISPH/xafv8aPWvae7wW3SRGgeQNXZsFVxasis/lxh8/2cOHomARw2cASNev7H5ZX\nh76RMNa0Ixzu3r4N1qzQVG1zfNO7SJEoUIWJ7BmBdd+iIJ98I2wkC6A+RAijltSP\n66PgFJKmjFc1EokjqyHi7uZGPjslHQirsO4BjwHj8gHAQ9Nq/+wJgfhvo/WgS3Og\ng3Uys7Qse+dMoSdD\n-----END CERTIFICATE-----";
static NSString* certPEM = @"-----BEGIN CERTIFICATE-----\nMIIEcjCCAmCgAwIBAgIEDAdVpzANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJG\nUjEXMBUGA1UEChMOTXkgQ29tcGFueSBJbmMxHzAdBgNVBAMTFk15IENvbXBhbnkg\nSW5jIFJvb3QgQ0ExEjAQBgNVBAUTCTEyMzEyMzEyMzAeFw0xODA3MjcwNzI1NDBa\nFw0zODA3MTcwOTIyMjhaMEoxETAPBgNVBAoTCFBlcnNvbmFsMSAwHgYDVQQLExdN\nZW1iZXJzaGlwIC0gTWFueSBZZWFyczETMBEGA1UEAxMKdGVzdCBidXllcjCBnzAN\nBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvqe7lPuaLIw/DbvUzZXKP/mYAhryiBxI\npxXW7ayQPqU28Vz+j1EZAkrC3yBQ/lyGxWI6VzkAvOn+IELPUuQ0xr4qOML3vAZK\nEtOjCXgal+w0ask3yOZNbhoHE9q/QGm6QmLfgRsttK/BnJZrA5Wt82j7uuVjRzhA\nE6qcHpzjuN0CAwEAAaOB2DCB1TAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIw\nADB5BggrBgEFBQcBAQRtMGswNgYIKwYBBQUHMAGGKmh0dHBzOi8vc2FuZGJveC5k\nc3N3LnVrL2NhL21lbWJlcnNoaXAvb2NzcDAxBggrBgEFBQcwAoYlaHR0cHM6Ly9z\nYW5kYm94LmRzc3cudWsvY2EvbWVtYmVyc2hpcDA6BgNVHR8EMzAxMC+gLaArhilo\ndHRwczovL3NhbmRib3guZHNzdy51ay9jYS9tZW1iZXJzaGlwL2NybDANBgkqhkiG\n9w0BAQsFAAOCAfsAXhc9D5Tmw9OFUi2Ob/f2O3cH7j2YjwQs27KFBnAxol5OVqm7\nWZQysJGxLKZvWsZsnvAmjG5faBm4ol0GSzdn6vkDAJPaW6Bvj+vJ9Gu3/PGq4cpy\nj5F8AtrD6+MfYLgEo4APwicWWuTMEwKTrOKsP07fXhAlNjSyJzC8PGJva2NdkFJd\nNnvzhFElCMVBm7csXHxMq9mzlAdUOtoHUZv36+4dErB6RhkkvzA8LN3KvgXrd36Q\nqZCfA8ghLqrJJZa+7Rs8aC91At69h+PfkpkqhWI6DDoia5CWLid+la7Jnd8rK15v\nF4ygpYSiCb90CMHjZGamOi9gbIBU9PKXm4052359Q1z/pcMyNbkUdeInLAcSrjyh\nn7mB3nBompIpoBtVxTZu99Ain+bBt7ndWDJOi2ci9nOFoAdjsmu1rEmNWoC8vPdK\nb2idyGKu7LdDqXYtY1iPf/tt1emuudmO7qEEwQz2cEOvsvgzpA71eQB/8Xa4Ie//\nNIDgPVrxmmYuUA7zP/z0Bm7McENtzlRyHx3Ww4yzMWeLxzDfOj+DtdtIMAuq7qZA\ndpDXmIsT9qXQy5tahBDbz+Xfg9wbjVHzIpvYDrHxb/99zzrbUgGXrs1MslwCbxPl\n6B8BunoYlxIHcZ1FyJQFNEDncxqO3c4trf43LhsYDy0GmAB+e3E=\n-----END CERTIFICATE-----\n";
static NSString* combinedPEM = @"-----BEGIN CERTIFICATE-----\nMIIEcjCCAmCgAwIBAgIEDAdVpzANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJG\nUjEXMBUGA1UEChMOTXkgQ29tcGFueSBJbmMxHzAdBgNVBAMTFk15IENvbXBhbnkg\nSW5jIFJvb3QgQ0ExEjAQBgNVBAUTCTEyMzEyMzEyMzAeFw0xODA3MjcwNzI1NDBa\nFw0zODA3MTcwOTIyMjhaMEoxETAPBgNVBAoTCFBlcnNvbmFsMSAwHgYDVQQLExdN\nZW1iZXJzaGlwIC0gTWFueSBZZWFyczETMBEGA1UEAxMKdGVzdCBidXllcjCBnzAN\nBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvqe7lPuaLIw/DbvUzZXKP/mYAhryiBxI\npxXW7ayQPqU28Vz+j1EZAkrC3yBQ/lyGxWI6VzkAvOn+IELPUuQ0xr4qOML3vAZK\nEtOjCXgal+w0ask3yOZNbhoHE9q/QGm6QmLfgRsttK/BnJZrA5Wt82j7uuVjRzhA\nE6qcHpzjuN0CAwEAAaOB2DCB1TAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIw\nADB5BggrBgEFBQcBAQRtMGswNgYIKwYBBQUHMAGGKmh0dHBzOi8vc2FuZGJveC5k\nc3N3LnVrL2NhL21lbWJlcnNoaXAvb2NzcDAxBggrBgEFBQcwAoYlaHR0cHM6Ly9z\nYW5kYm94LmRzc3cudWsvY2EvbWVtYmVyc2hpcDA6BgNVHR8EMzAxMC+gLaArhilo\ndHRwczovL3NhbmRib3guZHNzdy51ay9jYS9tZW1iZXJzaGlwL2NybDANBgkqhkiG\n9w0BAQsFAAOCAfsAXhc9D5Tmw9OFUi2Ob/f2O3cH7j2YjwQs27KFBnAxol5OVqm7\nWZQysJGxLKZvWsZsnvAmjG5faBm4ol0GSzdn6vkDAJPaW6Bvj+vJ9Gu3/PGq4cpy\nj5F8AtrD6+MfYLgEo4APwicWWuTMEwKTrOKsP07fXhAlNjSyJzC8PGJva2NdkFJd\nNnvzhFElCMVBm7csXHxMq9mzlAdUOtoHUZv36+4dErB6RhkkvzA8LN3KvgXrd36Q\nqZCfA8ghLqrJJZa+7Rs8aC91At69h+PfkpkqhWI6DDoia5CWLid+la7Jnd8rK15v\nF4ygpYSiCb90CMHjZGamOi9gbIBU9PKXm4052359Q1z/pcMyNbkUdeInLAcSrjyh\nn7mB3nBompIpoBtVxTZu99Ain+bBt7ndWDJOi2ci9nOFoAdjsmu1rEmNWoC8vPdK\nb2idyGKu7LdDqXYtY1iPf/tt1emuudmO7qEEwQz2cEOvsvgzpA71eQB/8Xa4Ie//\nNIDgPVrxmmYuUA7zP/z0Bm7McENtzlRyHx3Ww4yzMWeLxzDfOj+DtdtIMAuq7qZA\ndpDXmIsT9qXQy5tahBDbz+Xfg9wbjVHzIpvYDrHxb/99zzrbUgGXrs1MslwCbxPl\n6B8BunoYlxIHcZ1FyJQFNEDncxqO3c4trf43LhsYDy0GmAB+e3E=\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIIFSDCCAzagAwIBAgIBATANBgkqhkiG9w0BAQsFADBbMQswCQYDVQQGEwJGUjEX\nMBUGA1UEChMOTXkgQ29tcGFueSBJbmMxHzAdBgNVBAMTFk15IENvbXBhbnkgSW5j\nIFJvb3QgQ0ExEjAQBgNVBAUTCTEyMzEyMzEyMzAeFw0xODA3MjIwOTIyMjhaFw0z\nODA3MTcwOTIyMjhaMFsxCzAJBgNVBAYTAkZSMRcwFQYDVQQKEw5NeSBDb21wYW55\nIEluYzEfMB0GA1UEAxMWTXkgQ29tcGFueSBJbmMgUm9vdCBDQTESMBAGA1UEBRMJ\nMTIzMTIzMTIzMIICHDANBgkqhkiG9w0BAQEFAAOCAgkAMIICBAKCAfsA7Z4DbNkB\ni8XvK8jjFLujp8TYvmIBhxpqw4IyIRwkADEzcpivOxhRSTwiqRFOsgiCbPqaJ9WO\nUS+U3D19WCf5RT+edsvWqfOzK38wyyt7A80SVv/3Z7/c+YIEaPtUNbc11tXiOzMm\nUxb33oktHykRrgEsNm2GnkQvjV92KmdTpRLzUlbho9pHCpHqfDPGpcJjEQKHxMOM\nmNn+NUhJ9OzwfSmvFd/WuGYzFqmF+A4IZA5PEvIQNIxu8KsS+OL7Zs/aIy1bkWG5\neMUupWvJAbal6zrMsMP+lDGyoZ6fHzKgFHf56AyyjIa6wP9sVDrp1dusrDqR8/US\nBDoQktELNEmvLkfWSUBvfl18UnY7ZjbuSUCAGT3SrEQ+SP2IUxTlUOH83rYRyFQM\n/sgqkCjdJ8EBf32rWoKGNq1fFq5DJeUdX5sIsasC0t7AorxsJpqVa79b5DFXY1Om\nqWZo8QzoP2D3nwqM2ho67xM207giAYqnTpZ5kCDhAz+n4x4JOxOGPn+Yt/40IRsX\nkZxTRu0B5UmbEVrJVc4ymMUYobG9okb78gtddZY4fA374eURga0fGGVqAxiC/w7D\n8v2SGFq/XOPXswhyibXqtiA/q29Nuhis0KOIDzzBrI/qkLbpCcKmbsBQ5UAxX2gN\nBYkLK7IHVpoTlpFi9qb3x7jmxksCAwEAAaMjMCEwDgYDVR0PAQH/BAQDAgGGMA8G\nA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggH7AGHNdvKn3v1Jo+yTTFCf\nNRMlAhdijLW9Tl1hV8tm2yBCbkM+c8evrfSeo9wDaEmipSGNhuZbL2IcNFDpzcXG\nH9WnmQqDnKdtQoSg18PINb32rmvtFBN816APL14Rp+2yP1wr1i9UDANSzEzneBwn\nTrwxt0vWRpvXeSM+Xuwv7CjMVmp5cIv3Sum9o23i+zXePwaLgaY8zEv+o2qArCNm\nnVHsI3J6Si+Ead2LHH/hIU4TKcAH8yp/WKmXf2z3C1Ew2thh8u9NNNIU7iA2gKSi\nANz+OY9WfI+sXbiXUO8lMZc9LIEJbStCzg1mOd0x9AWZc0GL71viJWamijEUW3gD\n9m4Rwtm15h4pbMeSjAwoCPHy9ab+vKcihhuQQuZNl1l7J2aK9lY8hp5RkdfcqhBU\nQ6D6Jazni43nTLNTurO2Dw7b9kSwGTmQ1zI8RhgToiqJX2eTSU9j+5V0bqqyZKIR\nISPH/xafv8aPWvae7wW3SRGgeQNXZsFVxasis/lxh8/2cOHomARw2cASNev7H5ZX\nh76RMNa0Ixzu3r4N1qzQVG1zfNO7SJEoUIWJ7BmBdd+iIJ98I2wkC6A+RAijltSP\n66PgFJKmjFc1EokjqyHi7uZGPjslHQirsO4BjwHj8gHAQ9Nq/+wJgfhvo/WgS3Og\ng3Uys7Qse+dMoSdD\n-----END CERTIFICATE-----";

@interface licencecoreTests : XCTestCase
@end

@implementation licencecoreTests

- (void)setupTrustedCertificates:(LCLicenceCore*)inLC {
	// Provide anchors programmatically to avoid needing a main bundle during testing
	inLC.trustedPEMs = @[[rootPEM dataUsingEncoding:NSUTF8StringEncoding]];
	
	// Provide subject prefixes programmatically
	inLC.subjectPrefixes = @[@"test " ];
	
	// Disable network fetching of certificate chain
	inLC.allowNetwork = NO;
}

- (void)testAssistant {
	LCLicenceCore* a1 = [LCLicenceCore sharedCore];
	XCTAssertNotNil(a1, @"Shared assistant returned");

	LCLicenceCore* a2 = [LCLicenceCore sharedCore];
	XCTAssertEqualObjects(a1, a2, @"Shared assistants match");
}

- (void)testAddLicenceEmpty {
	LCLicenceCore* la = [LCLicenceCore sharedCore];
	[self setupTrustedCertificates:la];
	
	NSData* licence = [NSData new];
	
	NSError* error = nil;
	BOOL validAdd = [la addLicence:licence error:&error];
	XCTAssertFalse(validAdd, @"invalid add licence");
	XCTAssertNotNil(error, @"add licence must return an error");
}

- (void)testAddLicenceMulitplePEM {
	LCLicenceCore* la = [LCLicenceCore sharedCore];
	[self setupTrustedCertificates:la];
	
	NSData* licence = [combinedPEM dataUsingEncoding:NSUTF8StringEncoding];
	XCTAssertNotNil(licence, @"test licence certificate read");
	
	NSError* error = nil;
	BOOL validAdd = [la addLicence:licence error:&error];
	XCTAssertFalse(validAdd, @"invalid add licence");
	XCTAssertNotNil(error, @"add licence must return an error");
}

- (void)testAddLicence {
	LCLicenceCore* la = [LCLicenceCore sharedCore];
	[self setupTrustedCertificates:la];
	
	NSData* licence = [certPEM dataUsingEncoding:NSUTF8StringEncoding];
	XCTAssertNotNil(licence, @"test licence certificate read");
	
	NSError* error = nil;
	BOOL validAdd = [la addLicence:licence error:&error];
	XCTAssertTrue(validAdd, @"valid add licence");
	XCTAssertNil(error, @"add licence returned no error");
}

- (void)testAddDuplicateLicence {
	LCLicenceCore* la = [LCLicenceCore sharedCore];
	[self setupTrustedCertificates:la];
	
	NSData* licence = [certPEM dataUsingEncoding:NSUTF8StringEncoding];
	XCTAssertNotNil(licence, @"test licence certificate read");
	
	NSError* error = nil;
	BOOL validAdd = [la addLicence:licence error:&error];
	XCTAssertTrue(validAdd, @"valid add licence");
	XCTAssertNil(error, @"add licence returned no error");
	
	BOOL validAdd2 = [la addLicence:licence error:&error];
	XCTAssertTrue(validAdd2, @"valid add licence");
	XCTAssertNil(error, @"add licence returned no error");
}

- (void)testRevoke {
	LCLicenceCore* la = [LCLicenceCore sharedCore];
	NSError* error = [la revoke];
	XCTAssertNil(error, @"revoke returned no error");
}

- (void)testIsLicensed {
	LCLicenceCore* la = [LCLicenceCore sharedCore];
	[self setupTrustedCertificates:la];
	
	// Ensure not licensed
	NSError* revokeError = [la revoke];
	XCTAssertNil(revokeError, @"revoke returned no error");
	
	XCTAssertFalse(la.isLicensed, @"not yet licensed");
	
	NSData* licence = [certPEM dataUsingEncoding:NSUTF8StringEncoding];
	XCTAssertNotNil(licence, @"test licence certificate read");
	
	NSError* error = nil;
	BOOL validAdd = [la addLicence:licence error:&error];
	XCTAssertTrue(validAdd, @"valid add licence");
	XCTAssertNil(error, @"add licence returned no error");

	XCTAssertTrue(la.isLicensed, @"licensed ok");
}

@end