From 056d8e0e95b30d0231d27353aa4b54af3f4bd0c6 Mon Sep 17 00:00:00 2001
From: Maksym Kucherov <maximus.the0@gmail.com>
Date: Thu, 16 Jan 2025 17:31:11 -0500
Subject: [PATCH] TEST: Restore tests in `IpParserTests`. Fix implementation.

---
 ip.c                    | 143 ++++++++++++++++++----
 tests/IpParserTests.cpp | 259 +++++++++++++++++++++-------------------
 2 files changed, 254 insertions(+), 148 deletions(-)

diff --git a/ip.c b/ip.c
index 76303289..2dc4c6ee 100644
--- a/ip.c
+++ b/ip.c
@@ -143,36 +143,108 @@ static IpEvidenceType getSegmentTypeWithSeparator(
 	}
 }
 
+typedef enum {
+	FIFTYONE_DEGREES_IP_NON_BREAK_CHAR = 0,
+	FIFTYONE_DEGREES_IP_SEGMENT_BREAK_CHAR = 1,
+	FIFTYONE_DEGREES_IP_ADDRESS_BREAK_CHAR = 2,
+	FIFTYONE_DEGREES_IP_INVALID_CHAR = 4,
+} fiftyoneDegreesIpStringSeparatorType;
+
+#define IP_NON_BREAK_CHAR FIFTYONE_DEGREES_IP_NON_BREAK_CHAR
+#define IP_SEGMENT_BREAK_CHAR FIFTYONE_DEGREES_IP_SEGMENT_BREAK_CHAR
+#define IP_ADDRESS_BREAK_CHAR FIFTYONE_DEGREES_IP_ADDRESS_BREAK_CHAR
+#define IP_INVALID_CHAR FIFTYONE_DEGREES_IP_INVALID_CHAR
+#define IpStringSeparatorType fiftyoneDegreesIpStringSeparatorType
+
+static IpStringSeparatorType GetSeparatorCharType(
+	const char ipChar,
+	const IpEvidenceType ipType) {
+
+	switch (ipChar) {
+		case ':':
+			return ((ipType == IP_EVIDENCE_TYPE_IPV4)
+				? IP_ADDRESS_BREAK_CHAR : IP_SEGMENT_BREAK_CHAR);
+		case '.':
+			return IP_SEGMENT_BREAK_CHAR;
+		case ',':
+		case ' ':
+		case ']':
+		case '/':
+		case '\0':
+			return IP_ADDRESS_BREAK_CHAR;
+		default:
+			break;
+	}
+	if ('0' <= ipChar && ipChar <= '9') {
+		return IP_NON_BREAK_CHAR;
+	}
+	if (('a' <= ipChar && ipChar <= 'f') || ('A' <= ipChar && ipChar <= 'F')) {
+		return (ipType == IP_EVIDENCE_TYPE_IPV4
+			? IP_INVALID_CHAR : IP_NON_BREAK_CHAR);
+	}
+	return IP_INVALID_CHAR;
+}
+
 /**
  * Calls the callback method every time a byte is identified in the value
  * when parsed left to right.
  */
 static IpEvidenceType iterateIpAddress(
 	const char *start,
-	const char *end,
-	void *state,
+	const char * const end,
+	void * const state,
+	int * const springCount,
 	IpEvidenceType type,
-	parseIterator foundSegment) {
+	const parseIterator foundSegment) {
+
+	*springCount = 0;
+	if (*start == '[') {
+		start++;
+	}
+
+	IpEvidenceType currentSegmentType =
+		FIFTYONE_DEGREES_IP_EVIDENCE_TYPE_INVALID;
+
 	const char *current = start;
 	const char *nextSegment = current;
-	IpEvidenceType currentSegmentType = FIFTYONE_DEGREES_IP_EVIDENCE_TYPE_INVALID;
-	while (current <= end && nextSegment < end) {
-		if (*current == ',' ||
-			*current == ':' ||
-			*current == '.' ||
-			*current == ' ' ||
-			*current == '\0') {
-			currentSegmentType = getSegmentTypeWithSeparator(*current, type, currentSegmentType);
-			if (type == FIFTYONE_DEGREES_IP_EVIDENCE_TYPE_INVALID) {
-				type = currentSegmentType;
-			}
-			// Check if it is leading abbreviation
-			if (current - 1 >= start) {
-				foundSegment(state, currentSegmentType, nextSegment, current - 1);
-			}
-			nextSegment = current + 1;
+	for (; current <= end && nextSegment < end; ++current) {
+		IpStringSeparatorType separatorType =
+			GetSeparatorCharType(*current, type);
+		if (!separatorType) {
+			continue;
 		}
-		current++;
+		if (separatorType & IP_INVALID_CHAR) {
+			return IP_EVIDENCE_TYPE_INVALID;
+		}
+
+		currentSegmentType = getSegmentTypeWithSeparator(
+			*current, type, currentSegmentType);
+		if (type == FIFTYONE_DEGREES_IP_EVIDENCE_TYPE_INVALID) {
+			type = currentSegmentType;
+		}
+
+		if (current - nextSegment > (type == IP_EVIDENCE_TYPE_IPV4 ? 3 : 4)) {
+			return IP_EVIDENCE_TYPE_INVALID;
+		}
+
+		// Check if it is leading abbreviation
+		if (current - 1 >= start) {
+			foundSegment(state, currentSegmentType,
+				nextSegment, current - 1);
+		}
+		if (separatorType & IP_ADDRESS_BREAK_CHAR) {
+			return type;
+		}
+		if (current == nextSegment && current != start) {
+			++*springCount;
+		}
+		nextSegment = current + 1;
+	}
+	if (nextSegment < current
+		&& type != FIFTYONE_DEGREES_IP_EVIDENCE_TYPE_INVALID) {
+
+		foundSegment(state, currentSegmentType,
+			nextSegment, current - 1);
 	}
 	return type;
 }
@@ -209,15 +281,39 @@ fiftyoneDegreesIpAddressEvidence* fiftyoneDegreesIpAddressParse(
 	void*(*malloc)(size_t),
 	const char *start,
 	const char *end) {
-	int count = 0;
+
+	if (!start) {
+		return NULL;
+	}
+
+	int byteCount = 0;
+	int springCount = 0;
 	IpAddressEvidence *address;
 	IpEvidenceType type = iterateIpAddress(
 		start,
 		end,
-		&count,
+		&byteCount,
+		&springCount,
 		FIFTYONE_DEGREES_IP_EVIDENCE_TYPE_INVALID,
 		callbackIpAddressCount);
 
+	switch (type) {
+		case FIFTYONE_DEGREES_IP_EVIDENCE_TYPE_IPV4:
+			if (byteCount != IPV4_LENGTH || springCount) {
+				return NULL;
+			}
+			break;
+		case FIFTYONE_DEGREES_IP_EVIDENCE_TYPE_IPV6:
+			if (byteCount > IPV6_LENGTH ||
+				springCount > 1 ||
+				(byteCount < IPV6_LENGTH && !springCount)) {
+				return NULL;
+			}
+			break;
+		default:
+			return NULL;
+	}
+
 	address = mallocIpAddress(malloc, type);
 	if (address != NULL) {
 		// Set the address of the byte array to the byte following the
@@ -226,13 +322,14 @@ fiftyoneDegreesIpAddressEvidence* fiftyoneDegreesIpAddressParse(
 		address->address = (byte*)(address + 1);
 		// Set the next byte to be added during the parse operation.
 		address->current = (byte*)(address + 1);
-		address->bytesPresent = (byte)count;
+		address->bytesPresent = (byte)byteCount;
 		address->type = type;
 		// Add the bytes from the source value and get the type of address.
 		iterateIpAddress(
 			start,
 			end,
 			address,
+			&springCount,
 			type,
 			callbackIpAddressBuild);
 		address->next = NULL;
diff --git a/tests/IpParserTests.cpp b/tests/IpParserTests.cpp
index 4ca08d00..f8d31c37 100644
--- a/tests/IpParserTests.cpp
+++ b/tests/IpParserTests.cpp
@@ -33,70 +33,74 @@ static bool CheckResult(byte* result, byte* expected, uint16_t size) {
 	return match;
 }
 
+static fiftyoneDegreesIpAddressEvidence* parseIpAddressString(const char * const ipString) {
+	const char * const end = ipString ? ipString + strlen(ipString) : nullptr;
+	return fiftyoneDegreesIpAddressParse(malloc, ipString, end);
+}
+
+ // ------------------------------------------------------------------------------
+ // IPv4 tests
+ // ------------------------------------------------------------------------------
+TEST(ParseIp, ParseIp_Ipv4_Low)
+{
+	const char* ip = "0.0.0.0";
+	fiftyoneDegreesIpAddressEvidence* const result = parseIpAddressString(ip);
+	byte expected[] = { 0, 0, 0, 0 };
+	EXPECT_TRUE(CheckResult(result->address, expected, sizeof(expected))) <<
+		L"Expected result to be '0.0.0.0'";
+	free(result);
+}
+TEST(ParseIp, ParseIp_Ipv4_High)
+{
+	fiftyoneDegreesIpAddressEvidence* const result = parseIpAddressString("255.255.255.255");
+	byte expected[] = { 255, 255, 255, 255 };
+	EXPECT_TRUE(CheckResult(result->address, expected, sizeof(expected)))
+		<< L"Expected result to be '255.255.255.255'";
+	free(result);
+}
+TEST(ParseIp, ParseIp_Ipv4_PortNumber)
+{
+	fiftyoneDegreesIpAddressEvidence* const result = parseIpAddressString("1.2.3.4:80");
+	byte expected[] = { 1, 2, 3, 4 };
+	EXPECT_TRUE(CheckResult(result->address, expected, sizeof(expected)))
+		<< L"Expected result to be '1.2.3.4'";
+	free(result);
+}
+TEST(ParseIp, ParseIp_Ipv4_CIDRFormat)
+{
+	fiftyoneDegreesIpAddressEvidence* const result = parseIpAddressString("1.2.3.4/32");
+	byte expected[] = { 1, 2, 3, 4 };
+	EXPECT_TRUE(CheckResult(result->address, expected, sizeof(expected)))
+		<< L"Expected result to be '1.2.3.4'";
+	free(result);
+}
 // ------------------------------------------------------------------------------
-// IPv4 tests
+// IPv6 tests
 // ------------------------------------------------------------------------------
-//TEST(ParseIp, ParseIp_Ipv4_Low)
-//{
-//	const char* ip = "0.0.0.0";
-//	const char* end = (ip + 6);
-//	fiftyoneDegreesIpAddressEvidence* result = parseIpAddress(malloc, ip, end);
-//	byte expected[] = { 0, 0, 0, 0 };
-//	EXPECT_TRUE(CheckResult(result->address, expected)) <<
-//		L"Expected result to be '0.0.0.0' not '" << result->address << "'";
-//}
-//TEST(ParseIp, ParseIp_Ipv4_High)
-//{
-//	byte* result = fiftyoneDegreesIpAddressParse("255.255.255.255");
-//	byte expected[] = { 255, 255, 255, 255 };
-//	EXPECT_TRUE(CheckResult(result, expected),
-//		L"Expected result to be '255.255.255.255'");
-//}
-//TEST(ParseIp, ParseIp_Ipv4_PortNumber)
-//{
-//	byte* result = fiftyoneDegreesIpAddressParse("1.2.3.4:80");
-//	byte expected[] = { 1, 2, 3, 4 };
-//	EXPECT_TRUE(CheckResult(result, expected),
-//		L"Expected result to be '1.2.3.4'");
-//}
-//TEST(ParseIp, ParseIp_Ipv4_CIDRFormat)
-//{
-//	byte* result = fiftyoneDegreesIpAddressParse("1.2.3.4/32");
-//	byte expected[] = { 1, 2, 3, 4 };
-//	EXPECT_TRUE(CheckResult(result, expected),
-//		L"Expected result to be '1.2.3.4'");
-//}
-//// ------------------------------------------------------------------------------
-//// IPv6 tests
-//// ------------------------------------------------------------------------------
-//TEST(ParseIp, ParseIp_Ipv6_Low)
-//{
-//	byte* result = fiftyoneDegreesIpAddressParse("0:0:0:0:0:0:0:0");
-//	byte expected[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-//	EXPECT_TRUE(CheckResult(result, expected),
-//		L"Expected result to be '0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0'");
-//}
-//TEST(ParseIp, ParseIp_Ipv6_Low_Abbreviated)
-//{
-//	byte* result = fiftyoneDegreesIpAddressParse("::");
-//	byte expected[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-//	EXPECT_TRUE(CheckResult(result, expected),
-//		L"Expected result to be '0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0'");
-//}
-//TEST(ParseIp, ParseIp_Ipv6_High)
-//{
-//	byte* result = fiftyoneDegreesIpAddressParse("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF");
-//	byte expected[] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 };
-//	EXPECT_TRUE(CheckResult(result, expected),
-//		L"Expected result to be '255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255'");
-//}
-//TEST(ParseIp, ParseIp_Ipv6_AbbreviatedStart)
-//{
-//	byte* result = fiftyoneDegreesIpAddressParse("::FFFF:FFFF:FFFF:FFFF");
-//	byte expected[] = { 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255 };
-//	EXPECT_TRUE(CheckResult(result, expected),
-//		L"Expected result to be '0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 255, 255, 255, 255'");
-//}
+TEST(ParseIp, ParseIp_Ipv6_Low)
+{
+	fiftyoneDegreesIpAddressEvidence* const result = parseIpAddressString("0:0:0:0:0:0:0:0");
+	byte expected[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+	EXPECT_TRUE(CheckResult(result->address, expected, sizeof(expected)))
+		<< L"Expected result to be '0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0'";
+	free(result);
+}
+TEST(ParseIp, ParseIp_Ipv6_Low_Abbreviated)
+{
+	fiftyoneDegreesIpAddressEvidence* const result = parseIpAddressString("::");
+	byte expected[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+	EXPECT_TRUE(CheckResult(result->address, expected, sizeof(expected)))
+		<< L"Expected result to be '0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0'";
+	free(result);
+}
+TEST(ParseIp, ParseIp_Ipv6_High)
+{
+	fiftyoneDegreesIpAddressEvidence* const result = parseIpAddressString("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF");
+	byte expected[] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 };
+	EXPECT_TRUE(CheckResult(result->address, expected, sizeof(expected)))
+		<< L"Expected result to be '255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255'";
+	free(result);
+}
 TEST(ParseIp, ParseIp_Ipv6_AbbreviatedStart)
 {
 	const char *ipv6AbbreviatedStart = "::FFFF:FFFF:FFFF:FFFF";
@@ -109,8 +113,8 @@ TEST(ParseIp, ParseIp_Ipv6_AbbreviatedStart)
 			ipv6AbbreviatedStart,
 			ipv6AbbreviatedStart + strlen(ipv6AbbreviatedStart));
 
-	EXPECT_TRUE(result != NULL) << "Abbreviated start IPv6 address "
-		"should be successfull parsed, where the address is " <<
+	EXPECT_TRUE(result != nullptr) << "Abbreviated start IPv6 address "
+		"should be successfully parsed, where the address is " <<
 		ipv6AbbreviatedStart << ".";
 
 	EXPECT_TRUE(result->type == FIFTYONE_DEGREES_IP_EVIDENCE_TYPE_IPV6) <<
@@ -122,43 +126,38 @@ TEST(ParseIp, ParseIp_Ipv6_AbbreviatedStart)
 		"The value of the abbreivated start IPv6 address is not correctly parsed.";
     free(result);
 }
-//TEST(ParseIp, ParseIp_Ipv6_AbbreviatedMiddle)
-//{
-//	byte* result = fiftyoneDegreesIpAddressParse("FFFF:FFFF::FFFF:FFFF");
-//	byte expected[] = { 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255 };
-//	EXPECT_TRUE(CheckResult(result, expected),
-//		L"Expected result to be '255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255'");
-//}
-//TEST(ParseIp, ParseIp_Ipv6_AbbreviatedEnd)
-//{
-//	byte* result = fiftyoneDegreesIpAddressParse("FFFF:FFFF:FFFF:FFFF::");
-//	byte expected[] = { 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0 };
-//	EXPECT_TRUE(CheckResult(result, expected),
-//		L"Expected result to be '255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0'");
-//}
-//TEST(ParseIp, ParseIp_Ipv6_PortNumber)
-//{
-//	byte* result = fiftyoneDegreesIpAddressParse("[2001::1]:80");
-//	byte expected[] = { 32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
-//	EXPECT_TRUE(CheckResult(result, expected),
-//		L"Expected result to be '32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1'");
-//}
-//TEST(ParseIp, ParseIp_Ipv6_CIDRFormat)
-//{
-//	byte* result = fiftyoneDegreesIpAddressParse("2001::1/128");
-//	byte expected[] = { 32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
-//	EXPECT_TRUE(CheckResult(result, expected),
-//		L"Expected result to be '32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1'");
-//}
-//
-//// ------------------------------------------------------------------------------
-//// Invalid data
-//// ------------------------------------------------------------------------------
-//TEST(ParseIp, ParseIp_Invalid_ipv4OutOfRange)
-//{
-//	byte* result = fiftyoneDegreesIpAddressParse("256.256.256.256");
-//	Assert::IsNull(result);
-//}
+TEST(ParseIp, ParseIp_Ipv6_AbbreviatedMiddle)
+{
+	fiftyoneDegreesIpAddressEvidence* const result = parseIpAddressString("FFFF:FFFF::FFFF:FFFF");
+	byte expected[] = { 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255 };
+	EXPECT_TRUE(CheckResult(result->address, expected, sizeof(expected)))
+		<< L"Expected result to be '255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255'";
+}
+TEST(ParseIp, ParseIp_Ipv6_AbbreviatedEnd)
+{
+	fiftyoneDegreesIpAddressEvidence* const result = parseIpAddressString("FFFF:FFFF:FFFF:FFFF::");
+	byte expected[] = { 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0 };
+	EXPECT_TRUE(CheckResult(result->address, expected, sizeof(expected)))
+		<< L"Expected result to be '255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0'";
+}
+TEST(ParseIp, ParseIp_Ipv6_PortNumber)
+{
+	fiftyoneDegreesIpAddressEvidence* const result = parseIpAddressString("[2001::1]:80");
+	byte expected[] = { 32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
+	EXPECT_TRUE(CheckResult(result->address, expected, sizeof(expected)))
+		<< L"Expected result to be '32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1'";
+}
+TEST(ParseIp, ParseIp_Ipv6_CIDRFormat)
+{
+	fiftyoneDegreesIpAddressEvidence* const result = parseIpAddressString("2001::1/128");
+	byte expected[] = { 32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
+	EXPECT_TRUE(CheckResult(result->address, expected, sizeof(expected)))
+		<< L"Expected result to be '32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1'";
+}
+
+// ------------------------------------------------------------------------------
+// Invalid data
+// ------------------------------------------------------------------------------
 TEST(ParseIp, ParseIp_Invalid_ipv4OutOfRange)
 {
 	const char *ipv4OutOfRange = "256.256.256.256";
@@ -171,7 +170,7 @@ TEST(ParseIp, ParseIp_Invalid_ipv4OutOfRange)
 			ipv4OutOfRange,
 			ipv4OutOfRange + strlen(ipv4OutOfRange));
 
-	EXPECT_TRUE(result != NULL) << "Out of range IPv4 address "
+	EXPECT_TRUE(result != nullptr) << "Out of range IPv4 address "
 		"should be successfull parsed, where the address is " <<
 		ipv4OutOfRange << ".";
 
@@ -187,57 +186,67 @@ TEST(ParseIp, ParseIp_Invalid_ipv4OutOfRange)
 }
 TEST(ParseIp, ParseIp_Invalid_ipv4TooMany)
 {
-	byte* result = fiftyoneDegreesIpAddressParse("1.2.3.4.5");
-	Assert::IsNull(result);
+	fiftyoneDegreesIpAddressEvidence* const result = parseIpAddressString("1.2.3.4.5");
+	EXPECT_FALSE(result);
+	free(result);
 }
 TEST(ParseIp, ParseIp_Invalid_ipv4TooFew)
 {
-	byte* result = fiftyoneDegreesIpAddressParse("1.2.3");
-	Assert::IsNull(result);
+	fiftyoneDegreesIpAddressEvidence* const result = parseIpAddressString("1.2.3");
+	EXPECT_FALSE(result);
+	free(result);
 }
 TEST(ParseIp, ParseIp_Invalid_letters)
 {
-	byte* result = fiftyoneDegreesIpAddressParse("a.b.c.d");
-	Assert::IsNull(result);
+	fiftyoneDegreesIpAddressEvidence* const result = parseIpAddressString("a.b.c.d");
+	EXPECT_FALSE(result);
+	free(result);
 }
 TEST(ParseIp, ParseIp_Invalid_emptyString)
 {
-	byte* result = fiftyoneDegreesIpAddressParse("");
-	Assert::IsNull(result);
+	fiftyoneDegreesIpAddressEvidence* const result = parseIpAddressString("");
+	EXPECT_FALSE(result);
+	free(result);
 }
 TEST(ParseIp, ParseIp_Invalid_null)
 {
-	byte* result = fiftyoneDegreesIpAddressParse(NULL);
-	Assert::IsNull(result);
+	fiftyoneDegreesIpAddressEvidence* const result = parseIpAddressString(nullptr);
+	EXPECT_FALSE(result);
+	free(result);
 }
 TEST(ParseIp, ParseIp_Invalid_Number)
 {
-	byte* result = fiftyoneDegreesIpAddressParse("1234");
-	Assert::IsNull(result);
+	fiftyoneDegreesIpAddressEvidence* const result = parseIpAddressString("1234");
+	EXPECT_FALSE(result);
+	free(result);
 }
 TEST(ParseIp, ParseIp_Invalid_ipv6OutOfRange)
 {
-	byte* result = fiftyoneDegreesIpAddressParse("10000::1");
-	Assert::IsNull(result);
+	fiftyoneDegreesIpAddressEvidence* const result = parseIpAddressString("10000::1");
+	EXPECT_FALSE(result);
+	free(result);
 }
 TEST(ParseIp, ParseIp_Invalid_ipv6InvalidLetter)
 {
-	byte* result = fiftyoneDegreesIpAddressParse("GFFF::1");
-	Assert::IsNull(result);
+	fiftyoneDegreesIpAddressEvidence* const result = parseIpAddressString("GFFF::1");
+	EXPECT_FALSE(result);
+	free(result);
 }
 TEST(ParseIp, ParseIp_Invalid_ipv6TooMany)
 {
-	byte* result = fiftyoneDegreesIpAddressParse("1:1:1:1:1:1:1:1:1");
-	Assert::IsNull(result);
+	fiftyoneDegreesIpAddressEvidence* const result = parseIpAddressString("1:1:1:1:1:1:1:1:1");
+	EXPECT_FALSE(result);
+	free(result);
 }
 TEST(ParseIp, ParseIp_Invalid_ipv6TooFew)
 {
-	byte* result = fiftyoneDegreesIpAddressParse("1:1:1:1:1:1:1");
-	Assert::IsNull(result);
+	fiftyoneDegreesIpAddressEvidence* const result = parseIpAddressString("1:1:1:1:1:1:1");
+	EXPECT_FALSE(result);
+	free(result);
 }
-//// ------------------------------------------------------------------------------
-//// Comparison
-//// ------------------------------------------------------------------------------
+// ------------------------------------------------------------------------------
+// Comparison
+// ------------------------------------------------------------------------------
 TEST(CompareIp, CompareIp_Ipv4_Bigger) {
 	unsigned char ipAddress1[FIFTYONE_DEGREES_IPV4_LENGTH] = {9, 8, 7, 6};
 	unsigned char ipAddress2[FIFTYONE_DEGREES_IPV4_LENGTH] = {9, 8, 6, 6};