about summary refs log blame commit diff stats
path: root/dirent/tests/t-strverscmp.c
blob: fcb044f8d246348da27f157dba0615436854c2e3 (plain) (tree)













































































































































































































                                                                              
/*
 * Test program to make sure that strverscmp works correctly
 *
 * Copyright (C) 1998-2019 Toni Ronkko
 * This file is part of dirent.  Dirent may be freely distributed
 * under the MIT license.  For all details and documentation, see
 * https://github.com/tronkko/dirent
 */

/* Include prototype for strverscmp */
#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <dirent.h>
#include <ctype.h>

int
main(
	int argc, char *argv[])
{
	(void) argc;
	(void) argv;

	/* Strings without digits are compared as in strcmp() */
	assert(strverscmp("", "") == 0);
	assert(strverscmp("abc", "abc") == 0);
	assert(strverscmp("a", "b") < 0);
	assert(strverscmp("b", "a") > 0);

	/* Shorter string is smaller, other things being equal */
	assert(strverscmp("a", "aa") < 0);
	assert(strverscmp("aa", "a") > 0);
	assert(strverscmp("abcdef", "abcdefg") < 0);
	assert(strverscmp("abcdefg", "abcdef") > 0);

	/* Integers with equal length are compared as in strcmp() */
	assert(strverscmp("0", "0") == 0);
	assert(strverscmp("000", "000") == 0);
	assert(strverscmp("1", "2") < 0);
	assert(strverscmp("2", "1") > 0);
	assert(strverscmp("001", "100") < 0);
	assert(strverscmp("100", "001") > 0);
	assert(strverscmp("2020-07-01", "2020-07-02") < 0);
	assert(strverscmp("2020-07-02", "2020-07-01") > 0);
	assert(strverscmp("jan999", "jan999") == 0);

	/* Integers of different length are compared as numbers */
	assert(strverscmp("jan9", "jan10") < 0);
	assert(strverscmp("jan10", "jan9") > 0);
	assert(strverscmp("999", "1000") < 0);
	assert(strverscmp("1000", "999") > 0);
	assert(strverscmp("t12-1000", "t12-9999") < 0);
	assert(strverscmp("t12-9999", "t12-1000") > 0);
	assert(strverscmp("1000", "10001") < 0);
	assert(strverscmp("10001", "1000") > 0);
	assert(strverscmp("1000!", "10001") < 0);
	assert(strverscmp("10001", "1000!") > 0);
	assert(strverscmp("1000Z", "10001") < 0);
	assert(strverscmp("10001", "1000Z") > 0);

	/* If numbers starts with zero, then longer number is smaller */
	assert(strverscmp("00", "0") < 0);
	assert(strverscmp("0", "00") > 0);
	assert(strverscmp("a000", "a00") < 0);
	assert(strverscmp("a00", "a000") > 0);
	assert(strverscmp("0000", "000") < 0);
	assert(strverscmp("000", "0000") > 0);
	assert(strverscmp("0000", "000!") < 0);
	assert(strverscmp("000!", "0000") > 0);
	assert(strverscmp("0000", "000Z") < 0);
	assert(strverscmp("000Z", "0000") > 0);
	assert(strverscmp("0000", "000Z") < 0);
	assert(strverscmp("000Z", "0000") > 0);
	assert(strverscmp("1.01", "1.0") < 0);
	assert(strverscmp("1.0", "1.01") > 0);
	assert(strverscmp("1.01", "1.0!") < 0);
	assert(strverscmp("1.0!", "1.01") > 0);
	assert(strverscmp("1.01", "1.0~") < 0);
	assert(strverscmp("1.0~", "1.01") > 0);

	/* Number having more leading zeros is considered smaller */
	assert(strverscmp("item-0001", "item-001") < 0);
	assert(strverscmp("item-001", "item-0001") > 0);
	assert(strverscmp("item-001", "item-01") < 0);
	assert(strverscmp("item-01", "item-001") > 0);
	assert(strverscmp(".0001000", ".001") < 0);
	assert(strverscmp(".001", ".0001000") > 0);
	assert(strverscmp(".0001000", ".01") < 0);
	assert(strverscmp(".01", ".0001000") > 0);
	assert(strverscmp(".0001000", ".1") < 0);
	assert(strverscmp(".1", ".0001000") > 0);
	assert(strverscmp("1.0002", "1.0010000") < 0);
	assert(strverscmp("1.0010000", "1.0002") > 0);

	/* Number starting with zero is smaller than any number */
	assert(strverscmp("item-009", "item-1") < 0);
	assert(strverscmp("item-1", "item-009") > 0);
	assert(strverscmp("item-099", "item-2") < 0);
	assert(strverscmp("item-2", "item-099") > 0);

	/* Number vs alphabetical comparison */
	assert(strverscmp("1.001", "1.00!") < 0);
	assert(strverscmp("1.00!", "1.001") > 0);
	assert(strverscmp("1.001", "1.00x") < 0);
	assert(strverscmp("1.00x", "1.001") > 0);
	assert(strverscmp("1", "x") < 0);
	assert(strverscmp("x", "1") > 0);
	assert(strverscmp("1", "!") > 0);
	assert(strverscmp("!", "1") < 0);

	/* Handling the end of string */
	assert(strverscmp("01", "011") < 0);
	assert(strverscmp("011", "01") > 0);
	assert(strverscmp("0100", "01000") < 0);
	assert(strverscmp("01000", "0100") > 0);
	assert(strverscmp("1", "1!") < 0);
	assert(strverscmp("1!", "1") > 0);
	assert(strverscmp("1", "1z") < 0);
	assert(strverscmp("1z", "1") > 0);

	/* Ordering 000 < 00 < 01 < 010 < 09 < 0 < 1 < 9 < 10 */
	assert(strverscmp("000", "00") < 0);
	assert(strverscmp("000", "01") < 0);
	assert(strverscmp("000", "010") < 0);
	assert(strverscmp("000", "09") < 0);
	assert(strverscmp("000", "0") < 0);
	assert(strverscmp("000", "1") < 0);
	assert(strverscmp("000", "9") < 0);
	assert(strverscmp("000", "10") < 0);

	assert(strverscmp("00", "01") < 0);
	assert(strverscmp("00", "010") < 0);
	assert(strverscmp("00", "09") < 0);
	assert(strverscmp("00", "0") < 0);
	assert(strverscmp("00", "1") < 0);
	assert(strverscmp("00", "9") < 0);
	assert(strverscmp("00", "10") < 0);

	assert(strverscmp("01", "010") < 0);
	assert(strverscmp("01", "09") < 0);
	assert(strverscmp("01", "0") < 0);
	assert(strverscmp("01", "1") < 0);
	assert(strverscmp("01", "9") < 0);
	assert(strverscmp("01", "10") < 0);

	assert(strverscmp("010", "09") < 0);
	assert(strverscmp("010", "0") < 0);
	assert(strverscmp("010", "1") < 0);
	assert(strverscmp("010", "9") < 0);
	assert(strverscmp("010", "10") < 0);

	assert(strverscmp("09", "0") < 0);
	assert(strverscmp("09", "1") < 0);
	assert(strverscmp("09", "9") < 0);
	assert(strverscmp("09", "10") < 0);

	assert(strverscmp("0", "1") < 0);
	assert(strverscmp("0", "9") < 0);
	assert(strverscmp("0", "10") < 0);

	assert(strverscmp("1", "9") < 0);
	assert(strverscmp("1", "10") < 0);

	assert(strverscmp("9", "10") < 0);

	/* Compare speed */
	{
#define LENGTH 100
#define REPEAT 1000000
		char a[LENGTH+1];
		char b[LENGTH+1];
		size_t i;
		size_t j;
		char letters[] = "01234567890123456789abdefghjkpqrtwxyz-/.";
		size_t n = strlen(letters);

		/* Repeat test */
		for(i = 0; i < REPEAT; i++) {
			int diff1;
			int diff2;

			/* Generate two random strings of LENGTH characters */
			for(j = 0; j < LENGTH; j++) {
				a[j] = letters[rand() % n];
				b[j] = letters[rand() % n];
			}
			a[j] = '\0';
			b[j] = '\0';

			/* Compare strings in both directions */
			diff1 = strverscmp(a, b);
			diff2 = strverscmp(b, a);

			/* Must give identical result in both directions */
			assert((diff1 < 0 && diff2 > 0)
				|| (diff1 == 0 && diff2 == 0)
				|| (diff1 > 0 && diff2 < 0));
		}
	}

	printf("OK\n");
	return EXIT_SUCCESS;
}