Add unit test for the version parser
This commit is contained in:
parent
a9526ae663
commit
7c7ba729f5
61
src/include/version.h
Normal file
61
src/include/version.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/* Copyright (c) 2022 Barcelona Supercomputing Center (BSC)
|
||||||
|
* SPDX-License-Identifier: MIT */
|
||||||
|
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
version_parse(const char *version, int tuple[3])
|
||||||
|
{
|
||||||
|
char buf[64];
|
||||||
|
|
||||||
|
if (strlen(version) >= 64) {
|
||||||
|
err("parse_version: version too long: %s\n", version);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(buf, version);
|
||||||
|
|
||||||
|
char *str = buf;
|
||||||
|
char *which[] = { "major", "minor", "patch" };
|
||||||
|
char *delim[] = { ".", ".", ".-" };
|
||||||
|
char *save = NULL;
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
char *num = strtok_r(str, delim[i], &save);
|
||||||
|
|
||||||
|
/* Subsequent calls need NULL as string */
|
||||||
|
str = NULL;
|
||||||
|
|
||||||
|
if (num == NULL) {
|
||||||
|
err("parse_version: missing %s number: %s\n",
|
||||||
|
which[i], version);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
char *endptr = NULL;
|
||||||
|
int v = (int) strtol(num, &endptr, 10);
|
||||||
|
|
||||||
|
if (errno != 0 || endptr == num || endptr[0] != '\0') {
|
||||||
|
err("parse_version: failed to parse %s number: %s\n",
|
||||||
|
which[i], version);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v < 0) {
|
||||||
|
err("parse_version: invalid negative %s number: %s\n",
|
||||||
|
which[i], version);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tuple[i] = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -17,6 +17,7 @@
|
|||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "ovni.h"
|
#include "ovni.h"
|
||||||
#include "parson.h"
|
#include "parson.h"
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
/* Data per process */
|
/* Data per process */
|
||||||
struct ovni_rproc rproc = {0};
|
struct ovni_rproc rproc = {0};
|
||||||
@ -24,57 +25,6 @@ struct ovni_rproc rproc = {0};
|
|||||||
/* Data per thread */
|
/* Data per thread */
|
||||||
_Thread_local struct ovni_rthread rthread = {0};
|
_Thread_local struct ovni_rthread rthread = {0};
|
||||||
|
|
||||||
static int
|
|
||||||
parse_version(const char *version, int tuple[3])
|
|
||||||
{
|
|
||||||
char buf[64];
|
|
||||||
|
|
||||||
if (strlen(version) >= 64) {
|
|
||||||
err("parse_version: version too long: %s\n", version);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpy(buf, version);
|
|
||||||
|
|
||||||
char *str = buf;
|
|
||||||
char *which[] = { "major", "minor", "patch" };
|
|
||||||
char *delim[] = { ".", ".", ".-" };
|
|
||||||
char *save = NULL;
|
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++) {
|
|
||||||
char *num = strtok_r(str, delim[i], &save);
|
|
||||||
|
|
||||||
/* Subsequent calls need NULL as string */
|
|
||||||
str = NULL;
|
|
||||||
|
|
||||||
if (num == NULL) {
|
|
||||||
err("parse_version: missing %s number: %s\n",
|
|
||||||
which[i], version);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
char *endptr = NULL;
|
|
||||||
int v = (int) strtol(num, &endptr, 10);
|
|
||||||
|
|
||||||
if (errno != 0 || endptr == num || endptr[0] != '\0') {
|
|
||||||
err("parse_version: failed to parse %s number: %s\n",
|
|
||||||
which[i], version);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (v < 0) {
|
|
||||||
err("parse_version: invalid negative %s number: %s\n",
|
|
||||||
which[i], version);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
tuple[i] = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ovni_version_check_str(const char *version)
|
void ovni_version_check_str(const char *version)
|
||||||
{
|
{
|
||||||
if (version == NULL)
|
if (version == NULL)
|
||||||
@ -83,10 +33,10 @@ void ovni_version_check_str(const char *version)
|
|||||||
int provided[3];
|
int provided[3];
|
||||||
int expected[3];
|
int expected[3];
|
||||||
|
|
||||||
if (parse_version(version, provided) != 0)
|
if (version_parse(version, provided) != 0)
|
||||||
die("failed to parse provided version \"%s\"\n", version);
|
die("failed to parse provided version \"%s\"\n", version);
|
||||||
|
|
||||||
if (parse_version(OVNI_LIB_VERSION, expected) != 0)
|
if (version_parse(OVNI_LIB_VERSION, expected) != 0)
|
||||||
die("failed to parse expected version \"%s\"\n", OVNI_LIB_VERSION);
|
die("failed to parse expected version \"%s\"\n", OVNI_LIB_VERSION);
|
||||||
|
|
||||||
/* Match the major */
|
/* Match the major */
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2022 Barcelona Supercomputing Center (BSC)
|
# Copyright (c) 2022 Barcelona Supercomputing Center (BSC)
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
# Example: unit_test(abc.c)
|
unit_test(version.c)
|
||||||
|
45
test/unit/version.c
Normal file
45
test/unit/version.c
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#include "version.h"
|
||||||
|
|
||||||
|
struct testcase {
|
||||||
|
int rc;
|
||||||
|
char *version;
|
||||||
|
int tuple[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
struct testcase cases[] = {
|
||||||
|
/* Good */
|
||||||
|
{ 0, "0.0.0", { 0, 0, 0 } },
|
||||||
|
{ 0, "1.0.0", { 1, 0, 0 } },
|
||||||
|
{ 0, "0.1.0", { 0, 1, 0 } },
|
||||||
|
{ 0, "0.0.1", { 0, 0, 1 } },
|
||||||
|
{ 0, "1.2.3-rc1", { 1, 2, 3 } },
|
||||||
|
/* Bad */
|
||||||
|
{ -1, "-1.0.0", { 0, 0, 0 } },
|
||||||
|
{ -1, "1.2", { 0, 0, 0 } },
|
||||||
|
{ -1, "1", { 0, 0, 0 } },
|
||||||
|
{ -1, "1.O.O", { 0, 0, 0 } },
|
||||||
|
{ -1, "1.2.3rc", { 0, 0, 0 } },
|
||||||
|
};
|
||||||
|
|
||||||
|
int n = sizeof(cases) / sizeof(cases[0]);
|
||||||
|
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
struct testcase *c = &cases[i];
|
||||||
|
int tuple[3] = { 0 };
|
||||||
|
|
||||||
|
if (version_parse(c->version, tuple) != c->rc)
|
||||||
|
die("wrong return value\n");
|
||||||
|
|
||||||
|
if (c->rc != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (int j = 0; j < 3; j++) {
|
||||||
|
if (tuple[j] != c->tuple[j])
|
||||||
|
die("wrong parsed version\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user