Repository: celix Updated Branches: refs/heads/develop c5bc7496c -> 8e6e4572a
CELIX-323: moved version and version_range from framework to tests (Note that the mocks are still in the framework) Project: http://git-wip-us.apache.org/repos/asf/celix/repo Commit: http://git-wip-us.apache.org/repos/asf/celix/commit/8e6e4572 Tree: http://git-wip-us.apache.org/repos/asf/celix/tree/8e6e4572 Diff: http://git-wip-us.apache.org/repos/asf/celix/diff/8e6e4572 Branch: refs/heads/develop Commit: 8e6e4572ae1eb308b8f01f06ce22de47c5e64b8b Parents: c5bc749 Author: Bjoern Petri <[email protected]> Authored: Mon Dec 14 14:39:13 2015 +0100 Committer: Bjoern Petri <[email protected]> Committed: Mon Dec 14 14:39:13 2015 +0100 ---------------------------------------------------------------------- utils/private/include/version_private.h | 41 +++ utils/private/include/version_range_private.h | 41 +++ utils/private/src/version.c | 242 ++++++++++++++ utils/private/src/version_range.c | 179 +++++++++++ utils/private/test/version_range_test.cpp | 254 +++++++++++++++ utils/private/test/version_test.cpp | 356 +++++++++++++++++++++ utils/public/include/version.h | 161 ++++++++++ utils/public/include/version_range.h | 111 +++++++ 8 files changed, 1385 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/celix/blob/8e6e4572/utils/private/include/version_private.h ---------------------------------------------------------------------- diff --git a/utils/private/include/version_private.h b/utils/private/include/version_private.h new file mode 100644 index 0000000..15e5c89 --- /dev/null +++ b/utils/private/include/version_private.h @@ -0,0 +1,41 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you under the Apache License, Version 2.0 (the + *"License"); you may not use this file except in compliance + *with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ +/* + * version_private.h + * + * \date Dec 18, 2012 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ + + +#ifndef VERSION_PRIVATE_H_ +#define VERSION_PRIVATE_H_ + +#include "version.h" + +struct version { + int major; + int minor; + int micro; + char *qualifier; +}; + + +#endif /* VERSION_PRIVATE_H_ */ http://git-wip-us.apache.org/repos/asf/celix/blob/8e6e4572/utils/private/include/version_range_private.h ---------------------------------------------------------------------- diff --git a/utils/private/include/version_range_private.h b/utils/private/include/version_range_private.h new file mode 100644 index 0000000..dfccd59 --- /dev/null +++ b/utils/private/include/version_range_private.h @@ -0,0 +1,41 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you under the Apache License, Version 2.0 (the + *"License"); you may not use this file except in compliance + *with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ +/* + * version_range_private.h + * + * \date Dec 18, 2012 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ + + +#ifndef VERSION_RANGE_PRIVATE_H_ +#define VERSION_RANGE_PRIVATE_H_ + +#include "version_range.h" + +struct versionRange { + version_pt low; + bool isLowInclusive; + version_pt high; + bool isHighInclusive; + +}; + +#endif /* VERSION_RANGE_PRIVATE_H_ */ http://git-wip-us.apache.org/repos/asf/celix/blob/8e6e4572/utils/private/src/version.c ---------------------------------------------------------------------- diff --git a/utils/private/src/version.c b/utils/private/src/version.c new file mode 100644 index 0000000..3f8ddfa --- /dev/null +++ b/utils/private/src/version.c @@ -0,0 +1,242 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you under the Apache License, Version 2.0 (the + *"License"); you may not use this file except in compliance + *with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ +/* + * version.c + * + * \date Jul 12, 2010 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "celix_errno.h" +#include "version_private.h" + +celix_status_t version_createVersion(int major, int minor, int micro, char * qualifier, version_pt *version) { + celix_status_t status = CELIX_SUCCESS; + + if (*version != NULL) { + status = CELIX_ILLEGAL_ARGUMENT; + } else { + *version = (version_pt) malloc(sizeof(**version)); + if (!*version) { + status = CELIX_ENOMEM; + } else { + unsigned int i; + + (*version)->major = major; + (*version)->minor = minor; + (*version)->micro = micro; + if (qualifier == NULL) { + qualifier = ""; + } + (*version)->qualifier = strdup(qualifier); + + if (major < 0) { + status = CELIX_ILLEGAL_ARGUMENT; + } + if (minor < 0) { + status = CELIX_ILLEGAL_ARGUMENT; + } + if (micro < 0) { + status = CELIX_ILLEGAL_ARGUMENT; + } + + for (i = 0; i < strlen(qualifier); i++) { + char ch = qualifier[i]; + if (('A' <= ch) && (ch <= 'Z')) { + continue; + } + if (('a' <= ch) && (ch <= 'z')) { + continue; + } + if (('0' <= ch) && (ch <= '9')) { + continue; + } + if ((ch == '_') || (ch == '-')) { + continue; + } + status = CELIX_ILLEGAL_ARGUMENT; + break; + } + } + } + + return status; +} + +celix_status_t version_clone(version_pt version, version_pt *clone) { + return version_createVersion(version->major, version->minor, version->micro, version->qualifier, clone); +} + +celix_status_t version_destroy(version_pt version) { + version->major = 0; + version->minor = 0; + version->micro = 0; + free(version->qualifier); + version->qualifier = NULL; + free(version); + return CELIX_SUCCESS; +} + +celix_status_t version_createVersionFromString(char * versionStr, version_pt *version) { + celix_status_t status = CELIX_SUCCESS; + + int major = 0; + int minor = 0; + int micro = 0; + char * qualifier = NULL; + + char delims[] = "."; + char *token = NULL; + char *last = NULL; + + int i = 0; + + token = strtok_r(versionStr, delims, &last); + if (token != NULL) { + for (i = 0; i < strlen(token); i++) { + char ch = token[i]; + if (('0' <= ch) && (ch <= '9')) { + continue; + } + status = CELIX_ILLEGAL_ARGUMENT; + break; + } + major = atoi(token); + token = strtok_r(NULL, delims, &last); + if (token != NULL) { + for (i = 0; i < strlen(token); i++) { + char ch = token[i]; + if (('0' <= ch) && (ch <= '9')) { + continue; + } + status = CELIX_ILLEGAL_ARGUMENT; + break; + } + minor = atoi(token); + token = strtok_r(NULL, delims, &last); + if (token != NULL) { + for (i = 0; i < strlen(token); i++) { + char ch = token[i]; + if (('0' <= ch) && (ch <= '9')) { + continue; + } + status = CELIX_ILLEGAL_ARGUMENT; + break; + } + micro = atoi(token); + token = strtok_r(NULL, delims, &last); + if (token != NULL) { + qualifier = strdup(token); + token = strtok_r(NULL, delims, &last); + if (token != NULL) { + *version = NULL; + status = CELIX_ILLEGAL_ARGUMENT; + } + } + } + } + } + if (status == CELIX_SUCCESS) { + status = version_createVersion(major, minor, micro, qualifier, version); + } + + if (qualifier != NULL) { + free(qualifier); + } + + return status; +} + +celix_status_t version_createEmptyVersion(version_pt *version) { + return version_createVersion(0, 0, 0, "", version); +} + +celix_status_t version_getMajor(version_pt version, int *major) { + celix_status_t status = CELIX_SUCCESS; + *major = version->major; + return status; +} + +celix_status_t version_getMinor(version_pt version, int *minor) { + celix_status_t status = CELIX_SUCCESS; + *minor = version->minor; + return status; +} + +celix_status_t version_getMicro(version_pt version, int *micro) { + celix_status_t status = CELIX_SUCCESS; + *micro = version->micro; + return status; +} + +celix_status_t version_getQualifier(version_pt version, char **qualifier) { + celix_status_t status = CELIX_SUCCESS; + *qualifier = version->qualifier; + return status; +} + +celix_status_t version_compareTo(version_pt version, version_pt compare, int *result) { + celix_status_t status = CELIX_SUCCESS; + if (compare == version) { + *result = 0; + } else { + int res = version->major - compare->major; + if (res != 0) { + *result = res; + } else { + res = version->minor - compare->minor; + if (res != 0) { + *result = res; + } else { + res = version->micro - compare->micro; + if (res != 0) { + *result = res; + } else { + *result = strcmp(version->qualifier, compare->qualifier); + } + } + } + } + + return status; +} + +celix_status_t version_toString(version_pt version, char **string) { + celix_status_t status = CELIX_SUCCESS; + if (strlen(version->qualifier) > 0) { + char str[512]; + int written = snprintf(str, 512, "%d.%d.%d.%s", version->major, version->minor, version->micro, version->qualifier); + if (written >= 512 || written < 0) { + status = CELIX_BUNDLE_EXCEPTION; + } + *string = strdup(str); + } else { + char str[512]; + int written = snprintf(str, 512, "%d.%d.%d", version->major, version->minor, version->micro); + if (written >= 512 || written < 0) { + status = CELIX_BUNDLE_EXCEPTION; + } + *string = strdup(str); + } + return status; +} http://git-wip-us.apache.org/repos/asf/celix/blob/8e6e4572/utils/private/src/version_range.c ---------------------------------------------------------------------- diff --git a/utils/private/src/version_range.c b/utils/private/src/version_range.c new file mode 100644 index 0000000..bb3d82e --- /dev/null +++ b/utils/private/src/version_range.c @@ -0,0 +1,179 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you under the Apache License, Version 2.0 (the + *"License"); you may not use this file except in compliance + *with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ +/* + * version_range.c + * + * \date Jul 12, 2010 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ + +#include <stdlib.h> +#include <string.h> + +#include "version_range_private.h" + +celix_status_t versionRange_createVersionRange(version_pt low, bool isLowInclusive, + version_pt high, bool isHighInclusive, version_range_pt *range) { + celix_status_t status = CELIX_SUCCESS; + *range = (version_range_pt) malloc(sizeof(**range)); + if (!*range) { + status = CELIX_ENOMEM; + } else { + (*range)->low = low; + (*range)->isLowInclusive = isLowInclusive; + (*range)->high = high; + (*range)->isHighInclusive = isHighInclusive; + } + + return status; +} + +celix_status_t versionRange_destroy(version_range_pt range) { + if (range->high != NULL) { + version_destroy(range->high); + } + if (range->low != NULL) { + version_destroy(range->low); + } + + range->high = NULL; + range->isHighInclusive = false; + range->low = NULL; + range->isLowInclusive = false; + + free(range); + + return CELIX_SUCCESS; +} + +celix_status_t versionRange_createInfiniteVersionRange(version_range_pt *range) { + celix_status_t status; + + version_pt version = NULL; + status = version_createEmptyVersion(&version); + if (status == CELIX_SUCCESS) { + status = versionRange_createVersionRange(version, true, NULL, true, range); + } + + return status; +} + +celix_status_t versionRange_isInRange(version_range_pt versionRange, version_pt version, bool *inRange) { + celix_status_t status; + if (versionRange->high == NULL) { + int cmp; + status = version_compareTo(version, versionRange->low, &cmp); + if (status == CELIX_SUCCESS) { + *inRange = (cmp >= 0); + } + } else if (versionRange->isLowInclusive && versionRange->isHighInclusive) { + int low, high; + status = version_compareTo(version, versionRange->low, &low); + if (status == CELIX_SUCCESS) { + status = version_compareTo(version, versionRange->high, &high); + if (status == CELIX_SUCCESS) { + *inRange = (low >= 0) && (high <= 0); + } + } + } else if (versionRange->isHighInclusive) { + int low, high; + status = version_compareTo(version, versionRange->low, &low); + if (status == CELIX_SUCCESS) { + status = version_compareTo(version, versionRange->high, &high); + if (status == CELIX_SUCCESS) { + *inRange = (low > 0) && (high <= 0); + } + } + } else if (versionRange->isLowInclusive) { + int low, high; + status = version_compareTo(version, versionRange->low, &low); + if (status == CELIX_SUCCESS) { + status = version_compareTo(version, versionRange->high, &high); + if (status == CELIX_SUCCESS) { + *inRange = (low >= 0) && (high < 0); + } + } + } else { + int low, high; + status = version_compareTo(version, versionRange->low, &low); + if (status == CELIX_SUCCESS) { + status = version_compareTo(version, versionRange->high, &high); + if (status == CELIX_SUCCESS) { + *inRange = (low > 0) && (high < 0); + } + } + } + + return status; +} + +celix_status_t versionRange_parse(char * rangeStr, version_range_pt *range) { + celix_status_t status; + if (strchr(rangeStr, ',') != NULL) { + int vlowL = strcspn(rangeStr+1, ","); + char * vlow = (char *) malloc(sizeof(char) * (vlowL + 1)); + if (!vlow) { + status = CELIX_ENOMEM; + } else { + int vhighL; + char * vhigh; + vlow = strncpy(vlow, rangeStr+1, vlowL); + vlow[vlowL] = '\0'; + vhighL = strlen(rangeStr+1) - vlowL - 2; + vhigh = (char *) malloc(sizeof(char) * (vhighL+1)); + if (!vhigh) { + status = CELIX_ENOMEM; + } else { + version_pt versionLow = NULL; + int rangeL = strlen(rangeStr); + char start = rangeStr[0]; + char end = rangeStr[rangeL-1]; + + vhigh = strncpy(vhigh, rangeStr+vlowL+2, vhighL); + vhigh[vhighL] = '\0'; + status = version_createVersionFromString(vlow, &versionLow); + if (status == CELIX_SUCCESS) { + version_pt versionHigh = NULL; + status = version_createVersionFromString(vhigh, &versionHigh); + if (status == CELIX_SUCCESS) { + status = versionRange_createVersionRange( + versionLow, + start == '[', + versionHigh, + end ==']', + range + ); + } + } + free(vhigh); + } + free(vlow); + + } + } else { + version_pt version = NULL; + status = version_createVersionFromString(rangeStr, &version); + if (status == CELIX_SUCCESS) { + status = versionRange_createVersionRange(version, true, NULL, false, range); + } + } + + return status; +} http://git-wip-us.apache.org/repos/asf/celix/blob/8e6e4572/utils/private/test/version_range_test.cpp ---------------------------------------------------------------------- diff --git a/utils/private/test/version_range_test.cpp b/utils/private/test/version_range_test.cpp new file mode 100644 index 0000000..1e1336c --- /dev/null +++ b/utils/private/test/version_range_test.cpp @@ -0,0 +1,254 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you under the Apache License, Version 2.0 (the + *"License"); you may not use this file except in compliance + *with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ +/* + * version_range_test.cpp + * + * \date Dec 18, 2012 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ + +#include "CppUTest/TestHarness.h" +#include "CppUTest/TestHarness_c.h" +#include "CppUTest/CommandLineTestRunner.h" +#include "CppUTestExt/MockSupport.h" +#include "string.h" + +extern "C" +{ +#include "version_range_private.h" +#include "version_private.h" + +#include "celix_log.h" + +framework_logger_pt logger = (framework_logger_pt) 0x42; +} + +int main(int argc, char** argv) { + return RUN_ALL_TESTS(argc, argv); +} + +static char* my_strdup(const char* s) { + if (s == NULL) { + return NULL; + } + + size_t len = strlen(s); + + char *d = (char*) calloc(len + 1, sizeof(char)); + + if (d == NULL) { + return NULL; + } + + strncpy(d, s, len); + return d; +} + +//----------------------TESTGROUP DEFINES---------------------- + +TEST_GROUP(version_range) { + + void setup(void) { + } + + void teardown() { + mock().checkExpectations(); + mock().clear(); + } +}; + +TEST(version_range, create) { + celix_status_t status = CELIX_SUCCESS; + version_range_pt range = NULL; + version_pt version = (version_pt) malloc(sizeof(*version)); + + status = versionRange_createVersionRange(version, false, version, true, &range); + LONGS_EQUAL(CELIX_SUCCESS, status); + CHECK_C((range != NULL)); + LONGS_EQUAL(true, range->isHighInclusive); + LONGS_EQUAL(false, range->isLowInclusive); + POINTERS_EQUAL(version, range->low); + POINTERS_EQUAL(version, range->high); + + mock().expectNCalls(2, "version_destroy") + .withParameter("version", version); + + versionRange_destroy(range); + free(version); +} + +TEST(version_range, createInfinite) { + celix_status_t status = CELIX_SUCCESS; + version_range_pt range = NULL; + version_pt version = (version_pt) malloc(sizeof(*version)); + version->major = 1; + version->minor = 2; + version->micro = 3; + + mock() + .expectOneCall("version_createEmptyVersion") + .withOutputParameterReturning("version", &version, sizeof("version")); + status = versionRange_createInfiniteVersionRange(&range); + LONGS_EQUAL(CELIX_SUCCESS, status); + CHECK_C(range != NULL); + LONGS_EQUAL(true, range->isHighInclusive); + LONGS_EQUAL(true, range->isLowInclusive); + POINTERS_EQUAL(version, range->low); + POINTERS_EQUAL(NULL, range->high); + + mock().expectOneCall("version_destroy") + .withParameter("version", version); + + versionRange_destroy(range); + free(version); +} + +TEST(version_range, isInRange) { + bool result; + version_range_pt range = NULL; + version_pt version = (version_pt) malloc(sizeof(*version)); + version->major = 1; + version->minor = 2; + version->micro = 3; + + version_pt low = (version_pt) malloc(sizeof(*low)); + low->major = 1; + low->minor = 2; + low->micro = 3; + + version_pt high = (version_pt) malloc(sizeof(*high)); + high->major = 1; + high->minor = 2; + high->micro = 3; + + int stat = 1; + mock() + .expectNCalls(5, "version_compareTo") + .withParameter("version", version) + .withParameter("compare", low) + .withOutputParameterReturning("result", &stat, sizeof(int)); + int stat2 = -1; + mock() + .expectNCalls(4, "version_compareTo") + .withParameter("version", version) + .withParameter("compare", high) + .withOutputParameterReturning("result", &stat2, sizeof(int)); + + versionRange_createVersionRange(low, true, high, true, &range); + LONGS_EQUAL(CELIX_SUCCESS, versionRange_isInRange(range, version, &result)); + LONGS_EQUAL(true, result); + + mock().expectOneCall("version_destroy") + .withParameter("version", low); + mock().expectOneCall("version_destroy") + .withParameter("version", high); + versionRange_destroy(range); + + versionRange_createVersionRange(low, true, NULL, true, &range); + LONGS_EQUAL(CELIX_SUCCESS, versionRange_isInRange(range, version, &result)); + LONGS_EQUAL(true, result); + + mock().expectOneCall("version_destroy") + .withParameter("version", low); + versionRange_destroy(range); + + versionRange_createVersionRange(low, false, high, true, &range); + LONGS_EQUAL(CELIX_SUCCESS, versionRange_isInRange(range, version, &result)); + LONGS_EQUAL(true, result); + + mock().expectOneCall("version_destroy") + .withParameter("version", low); + mock().expectOneCall("version_destroy") + .withParameter("version", high); + versionRange_destroy(range); + + versionRange_createVersionRange(low, true, high, false, &range); + LONGS_EQUAL(CELIX_SUCCESS, versionRange_isInRange(range, version, &result)); + LONGS_EQUAL(true, result); + + mock().expectOneCall("version_destroy") + .withParameter("version", low); + mock().expectOneCall("version_destroy") + .withParameter("version", high); + versionRange_destroy(range); + + versionRange_createVersionRange(low, false, high, false, &range); + LONGS_EQUAL(CELIX_SUCCESS, versionRange_isInRange(range, version, &result)); + LONGS_EQUAL(true, result); + + mock().expectOneCall("version_destroy") + .withParameter("version", low); + mock().expectOneCall("version_destroy") + .withParameter("version", high); + versionRange_destroy(range); + + free(version); + free(high); + free(low); +} + +TEST(version_range, parse) { + version_range_pt range = NULL; + version_pt low = (version_pt) malloc(sizeof(*low)); + version_pt high = (version_pt) malloc(sizeof(*high)); + char * version = my_strdup("[1.2.3,7.8.9]"); + low->major = 1; + low->minor = 2; + low->micro = 3; + + high->major = 7; + high->minor = 8; + high->micro = 9; + + mock().expectOneCall("version_destroy") + .withParameter("version", high); + + mock().expectNCalls(2, "version_destroy") + .withParameter("version", low); + + mock().expectOneCall("version_createVersionFromString") + .withParameter("versionStr", "1.2.3") + .withOutputParameterReturning("version", &low, sizeof(low)); + + mock().expectOneCall("version_createVersionFromString") + .withParameter("versionStr", "7.8.9") + .withOutputParameterReturning("version", &high, sizeof(high)); + + LONGS_EQUAL(CELIX_SUCCESS, versionRange_parse(version, &range)); + + versionRange_destroy(range); + free(version); + version = my_strdup("[1.2.3"); + + mock().expectOneCall("version_createVersionFromString") + .withParameter("versionStr", "[1.2.3") + .withOutputParameterReturning("version", &low, sizeof(low)); + + LONGS_EQUAL(CELIX_SUCCESS, versionRange_parse(version, &range)); + + versionRange_destroy(range); + free(version); + free(high); + free(low); +} + + + + http://git-wip-us.apache.org/repos/asf/celix/blob/8e6e4572/utils/private/test/version_test.cpp ---------------------------------------------------------------------- diff --git a/utils/private/test/version_test.cpp b/utils/private/test/version_test.cpp new file mode 100644 index 0000000..e1b0eee --- /dev/null +++ b/utils/private/test/version_test.cpp @@ -0,0 +1,356 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you under the Apache License, Version 2.0 (the + *"License"); you may not use this file except in compliance + *with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ +/* + * version_test.cpp + * + * \date Dec 18, 2012 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ +#include <string.h> + +#include "CppUTest/TestHarness.h" +#include "CppUTest/TestHarness_c.h" +#include "CppUTest/CommandLineTestRunner.h" +#include "CppUTestExt/MockSupport.h" + +extern "C" +{ +#include "version_private.h" +#include "celix_log.h" + +framework_logger_pt logger = (framework_logger_pt) 0x666; +} + +int main(int argc, char** argv) { + return RUN_ALL_TESTS(argc, argv); +} + +static char* my_strdup(const char* s){ + if(s==NULL){ + return NULL; + } + + size_t len = strlen(s); + + char *d = (char*) calloc (len + 1,sizeof(char)); + + if (d == NULL){ + return NULL; + } + + strncpy (d,s,len); + return d; +} + +TEST_GROUP(version) { + + void setup(void) { + } + + void teardown() { + mock().checkExpectations(); + mock().clear(); + } + +}; + + +TEST(version, create) { + version_pt version = NULL; + char * str; + +// str = my_strdup("abc"); +// status = version_createVersion(1, 2, 3, str, &version); +// LONGS_EQUAL(CELIX_ILLEGAL_ARGUMENT, status); + + str = my_strdup("abc"); + LONGS_EQUAL(CELIX_SUCCESS, version_createVersion(1, 2, 3, str, &version)); + CHECK_C(version != NULL); + LONGS_EQUAL(1, version->major); + LONGS_EQUAL(2, version->minor); + LONGS_EQUAL(3, version->micro); + STRCMP_EQUAL("abc", version->qualifier); + + version_destroy(version); + version = NULL; + LONGS_EQUAL(CELIX_SUCCESS, version_createVersion(1, 2, 3, NULL, &version)); + CHECK_C(version != NULL); + LONGS_EQUAL(1, version->major); + LONGS_EQUAL(2, version->minor); + LONGS_EQUAL(3, version->micro); + STRCMP_EQUAL("", version->qualifier); + + version_destroy(version); + version = NULL; + free(str); + str = my_strdup("abc"); + LONGS_EQUAL(CELIX_ILLEGAL_ARGUMENT, version_createVersion(-1, -2, -3, str, &version)); + + version_destroy(version); + version = NULL; + free(str); + str = my_strdup("abc|xyz"); + LONGS_EQUAL(CELIX_ILLEGAL_ARGUMENT, version_createVersion(1, 2, 3, str, &version)); + + version_destroy(version); + free(str); +} + +TEST(version, clone) { + version_pt version = NULL, clone = NULL; + char * str; + + str = my_strdup("abc"); + LONGS_EQUAL(CELIX_SUCCESS, version_createVersion(1, 2, 3, str, &version)); + LONGS_EQUAL(CELIX_SUCCESS, version_clone(version, &clone)); + CHECK_C(version != NULL); + LONGS_EQUAL(1, clone->major); + LONGS_EQUAL(2, clone->minor); + LONGS_EQUAL(3, clone->micro); + STRCMP_EQUAL("abc", clone->qualifier); + + version_destroy(clone); + version_destroy(version); + free(str); +} + +TEST(version, createFromString) { + version_pt version = NULL; + celix_status_t status = CELIX_SUCCESS; + char * str; + + str = my_strdup("1"); + LONGS_EQUAL(CELIX_SUCCESS, version_createVersionFromString(str, &version)); + CHECK_C(version != NULL); + LONGS_EQUAL(1, version->major); + + version_destroy(version); + + free(str); + str = my_strdup("a"); + LONGS_EQUAL(CELIX_ILLEGAL_ARGUMENT, version_createVersionFromString(str, &version)); + + free(str); + str = my_strdup("1.a"); + LONGS_EQUAL(CELIX_ILLEGAL_ARGUMENT, version_createVersionFromString(str, &version)); + + free(str); + str = my_strdup("1.1.a"); + LONGS_EQUAL(CELIX_ILLEGAL_ARGUMENT, version_createVersionFromString(str, &version)); + + free(str); + str = my_strdup("-1"); + LONGS_EQUAL(CELIX_ILLEGAL_ARGUMENT, version_createVersionFromString(str, &version)); + + free(str); + str = my_strdup("1.2"); + version = NULL; + LONGS_EQUAL(CELIX_SUCCESS, version_createVersionFromString(str, &version)); + CHECK_C(version != NULL); + LONGS_EQUAL(1, version->major); + LONGS_EQUAL(2, version->minor); + + version_destroy(version); + + free(str); + str = my_strdup("1.2.3"); + version = NULL; + status = version_createVersionFromString(str, &version); + LONGS_EQUAL(CELIX_SUCCESS, status); + CHECK_C(version != NULL); + LONGS_EQUAL(1, version->major); + LONGS_EQUAL(2, version->minor); + LONGS_EQUAL(3, version->micro); + + version_destroy(version); + free(str); + str = my_strdup("1.2.3.abc"); + version = NULL; + status = version_createVersionFromString(str, &version); + LONGS_EQUAL(CELIX_SUCCESS, status); + CHECK_C(version != NULL); + LONGS_EQUAL(1, version->major); + LONGS_EQUAL(2, version->minor); + LONGS_EQUAL(3, version->micro); + STRCMP_EQUAL("abc", version->qualifier); + + version_destroy(version); + free(str); + str = my_strdup("1.2.3.abc_xyz"); + version = NULL; + status = version_createVersionFromString(str, &version); + LONGS_EQUAL(CELIX_SUCCESS, status); + CHECK_C(version != NULL); + LONGS_EQUAL(1, version->major); + LONGS_EQUAL(2, version->minor); + LONGS_EQUAL(3, version->micro); + STRCMP_EQUAL("abc_xyz", version->qualifier); + + version_destroy(version); + free(str); + str = my_strdup("1.2.3.abc-xyz"); + version = NULL; + status = version_createVersionFromString(str, &version); + LONGS_EQUAL(CELIX_SUCCESS, status); + CHECK_C(version != NULL); + LONGS_EQUAL(1, version->major); + LONGS_EQUAL(2, version->minor); + LONGS_EQUAL(3, version->micro); + STRCMP_EQUAL("abc-xyz", version->qualifier); + + version_destroy(version); + free(str); + str = my_strdup("1.2.3.abc|xyz"); + status = version_createVersionFromString(str, &version); + LONGS_EQUAL(CELIX_ILLEGAL_ARGUMENT, status); + + free(str); +} + +TEST(version, createEmptyVersion) { + version_pt version = NULL; + celix_status_t status = CELIX_SUCCESS; + + status = version_createEmptyVersion(&version); + LONGS_EQUAL(CELIX_SUCCESS, status); + CHECK_C(version != NULL); + LONGS_EQUAL(0, version->major); + LONGS_EQUAL(0, version->minor); + LONGS_EQUAL(0, version->micro); + STRCMP_EQUAL("", version->qualifier); + + version_destroy(version); +} + +TEST(version, getters) { + version_pt version = NULL; + celix_status_t status = CELIX_SUCCESS; + char * str; + int major, minor, micro; + char *qualifier; + + str = my_strdup("abc"); + status = version_createVersion(1, 2, 3, str, &version); + LONGS_EQUAL(CELIX_SUCCESS, status); + CHECK_C(version != NULL); + + version_getMajor(version, &major); + LONGS_EQUAL(1, major); + + version_getMinor(version, &minor); + LONGS_EQUAL(2, minor); + + version_getMicro(version, µ); + LONGS_EQUAL(3, micro); + + version_getQualifier(version, &qualifier); + STRCMP_EQUAL("abc", qualifier); + + version_destroy(version); + free(str); +} + +TEST(version, compare) { + version_pt version = NULL, compare = NULL; + celix_status_t status = CELIX_SUCCESS; + char * str; + int result; + + // Base version to compare + str = my_strdup("abc"); + status = version_createVersion(1, 2, 3, str, &version); + LONGS_EQUAL(CELIX_SUCCESS, status); + CHECK_C(version != NULL); + + // Compare equality + free(str); + str = my_strdup("abc"); + compare = NULL; + status = version_createVersion(1, 2, 3, str, &compare); + LONGS_EQUAL(CELIX_SUCCESS, status); + CHECK_C(version != NULL); + status = version_compareTo(version, compare, &result); + LONGS_EQUAL(CELIX_SUCCESS, status); + LONGS_EQUAL(0, result); + + // Compare against a higher version + free(str); + str = my_strdup("bcd"); + version_destroy(compare); + compare = NULL; + status = version_createVersion(1, 2, 3, str, &compare); + LONGS_EQUAL(CELIX_SUCCESS, status); + CHECK_C(version != NULL); + status = version_compareTo(version, compare, &result); + LONGS_EQUAL(CELIX_SUCCESS, status); + CHECK(result < 0); + + // Compare againts a lower version + free(str); + str = my_strdup("abc"); + version_destroy(compare); + compare = NULL; + status = version_createVersion(1, 1, 3, str, &compare); + LONGS_EQUAL(CELIX_SUCCESS, status); + CHECK_C(version != NULL); + status = version_compareTo(version, compare, &result); + LONGS_EQUAL(CELIX_SUCCESS, status); + CHECK(result > 0); + + version_destroy(compare); + version_destroy(version); + free(str); +} + +TEST(version, toString) { + version_pt version = NULL; + celix_status_t status = CELIX_SUCCESS; + char * str; + char *result = NULL; + + str = my_strdup("abc"); + status = version_createVersion(1, 2, 3, str, &version); + LONGS_EQUAL(CELIX_SUCCESS, status); + CHECK_C(version != NULL); + + status = version_toString(version, &result); + LONGS_EQUAL(CELIX_SUCCESS, status); + CHECK_C(result != NULL); + STRCMP_EQUAL("1.2.3.abc", result); + free(result); + + version_destroy(version); + version = NULL; + status = version_createVersion(1, 2, 3, NULL, &version); + LONGS_EQUAL(CELIX_SUCCESS, status); + CHECK_C(version != NULL); + + status = version_toString(version, &result); + LONGS_EQUAL(CELIX_SUCCESS, status); + CHECK_C(result != NULL); + STRCMP_EQUAL("1.2.3", result); + + version_destroy(version); + free(result); + free(str); +} + + + http://git-wip-us.apache.org/repos/asf/celix/blob/8e6e4572/utils/public/include/version.h ---------------------------------------------------------------------- diff --git a/utils/public/include/version.h b/utils/public/include/version.h new file mode 100644 index 0000000..ca1a2fa --- /dev/null +++ b/utils/public/include/version.h @@ -0,0 +1,161 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you under the Apache License, Version 2.0 (the + *"License"); you may not use this file except in compliance + *with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ +/* + * version.h + * + * \date Jul 12, 2010 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ + +#ifndef VERSION_H_ +#define VERSION_H_ + +#include "celix_errno.h" +/** + * The definition of the version_pt abstract data type. + */ +typedef struct version * version_pt; + +/** + * Creates a new version_pt using the supplied arguments. + * + * @param major Major component of the version identifier. + * @param minor Minor component of the version identifier. + * @param micro Micro component of the version identifier. + * @param qualifier Qualifier component of the version identifier. If + * <code>null</code> is specified, then the qualifier will be set to + * the empty string. + * @param version The created version_pt + * @return Status code indication failure or success: + * - CELIX_SUCCESS when no errors are encountered. + * - CELIX_ENOMEM If allocating memory for <code>version</code> failed. + * - CELIX_ILLEGAL_ARGUMENT If the numerical components are negative + * or the qualifier string is invalid. + */ +celix_status_t version_createVersion(int major, int minor, int micro, char * qualifier, version_pt *version); + +celix_status_t version_destroy(version_pt version); + +/** + * Creates a clone of <code>version</code>. + * + * @param version The version to clone + * @param clone The cloned version + * @return Status code indication failure or success: + * - CELIX_SUCCESS when no errors are encountered. + * - CELIX_ENOMEM If allocating memory for <code>version</code> failed. + * - CELIX_ILLEGAL_ARGUMENT If the numerical components are negative + * or the qualifier string is invalid. + */ +celix_status_t version_clone(version_pt version, version_pt *clone); + +/** + * Creates a version identifier from the specified string. + * + * <p> + * Here is the grammar for version strings. + * + * <pre> + * version ::= major('.'minor('.'micro('.'qualifier)?)?)? + * major ::= digit+ + * minor ::= digit+ + * micro ::= digit+ + * qualifier ::= (alpha|digit|'_'|'-')+ + * digit ::= [0..9] + * alpha ::= [a..zA..Z] + * </pre> + * + * There must be no whitespace in version. + * + * @param versionStr String representation of the version identifier. + * @param version The created version_pt + * @return Status code indication failure or success: + * - CELIX_SUCCESS when no errors are encountered. + * - CELIX_ENOMEM If allocating memory for <code>version</code> failed. + * - CELIX_ILLEGAL_ARGUMENT If the numerical components are negative, + * the qualifier string is invalid or <code>versionStr</code> is improperly formatted. + */ +celix_status_t version_createVersionFromString(char * versionStr, version_pt *version); + +/** + * The empty version "0.0.0". + * + * @param version The created version_pt + * @return Status code indication failure or success: + * - CELIX_SUCCESS when no errors are encountered. + * - CELIX_ENOMEM If allocating memory for <code>version</code> failed. + * - CELIX_ILLEGAL_ARGUMENT If the numerical components are negative, + * the qualifier string is invalid or <code>versionStr</code> is improperly formatted. + */ +celix_status_t version_createEmptyVersion(version_pt *version); + +celix_status_t version_getMajor(version_pt version, int *major); +celix_status_t version_getMinor(version_pt version, int *minor); +celix_status_t version_getMicro(version_pt version, int *micro); +celix_status_t version_getQualifier(version_pt version, char **qualifier); + +/** + * Compares this <code>Version</code> object to another object. + * + * <p> + * A version is considered to be <b>less than </b> another version if its + * major component is less than the other version's major component, or the + * major components are equal and its minor component is less than the other + * version's minor component, or the major and minor components are equal + * and its micro component is less than the other version's micro component, + * or the major, minor and micro components are equal and it's qualifier + * component is less than the other version's qualifier component (using + * <code>String.compareTo</code>). + * + * <p> + * A version is considered to be <b>equal to</b> another version if the + * major, minor and micro components are equal and the qualifier component + * is equal (using <code>String.compareTo</code>). + * + * @param version The <code>version_pt</code> to be compared with <code>compare</code>. + * @param compare The <code>version_pt</code> to be compared with <code>version</code>. + * @param result A negative integer, zero, or a positive integer if <code>version</code> is + * less than, equal to, or greater than the <code>compare</code>. + * @return Status code indication failure or success: + * - CELIX_SUCCESS when no errors are encountered. + */ +celix_status_t version_compareTo(version_pt version, version_pt compare, int *result); + +/** + * Returns the string representation of <code>version</code> identifier. + * + * <p> + * The format of the version string will be <code>major.minor.micro</code> + * if qualifier is the empty string or + * <code>major.minor.micro.qualifier</code> otherwise. + * + * @return The string representation of this version identifier. + * @param version The <code>version_pt</code> to get the string representation from. + * @param string Pointer to the string (char *) in which the result will be placed. + * @return Status code indication failure or success: + * - CELIX_SUCCESS when no errors are encountered. + */ +celix_status_t version_toString(version_pt version, char **string); + +/** + * @} + */ + +#endif /* VERSION_H_ */ http://git-wip-us.apache.org/repos/asf/celix/blob/8e6e4572/utils/public/include/version_range.h ---------------------------------------------------------------------- diff --git a/utils/public/include/version_range.h b/utils/public/include/version_range.h new file mode 100644 index 0000000..a979eca --- /dev/null +++ b/utils/public/include/version_range.h @@ -0,0 +1,111 @@ +/** + *Licensed to the Apache Software Foundation (ASF) under one + *or more contributor license agreements. See the NOTICE file + *distributed with this work for additional information + *regarding copyright ownership. The ASF licenses this file + *to you under the Apache License, Version 2.0 (the + *"License"); you may not use this file except in compliance + *with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + *Unless required by applicable law or agreed to in writing, + *software distributed under the License is distributed on an + *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + *specific language governing permissions and limitations + *under the License. + */ +/* + * version_range.h + * + * \date Jul 12, 2010 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ + +#ifndef VERSION_RANGE_H_ +#define VERSION_RANGE_H_ + +/** + * @defgroup VersionRange Version Range functions + * @ingroup framework + * @{ + */ + +#include "celixbool.h" +#include "celix_errno.h" +#include "version.h" + +/** + * Type definition for the version_range_pt abstract data type. + */ +typedef struct versionRange * version_range_pt; + +/** + * Creates a new <code>version_range_pt</code>. + * + * @param low Lower bound version + * @param isLowInclusive True if lower bound should be included in the range + * @param high Upper bound version + * @param isHighInclusive True if upper bound should be included in the range + * @param versionRange The created range + * @return Status code indication failure or success: + * - CELIX_SUCCESS when no errors are encountered. + * - CELIX_ENOMEM If allocating memory for <code>versionRange</code> failed. + */ +celix_status_t versionRange_createVersionRange(version_pt low, bool isLowInclusive, version_pt high, bool isHighInclusive, version_range_pt *versionRange); + +/** + * Creates an infinite version range using ::version_createEmptyVersion for the low version, + * NULL for the high version and high and low inclusive set to true. + * + * @param range The created range + * @return Status code indication failure or success: + * - CELIX_SUCCESS when no errors are encountered. + * - CELIX_ENOMEM If allocating memory for <code>range</code> failed. + */ +celix_status_t versionRange_createInfiniteVersionRange(version_range_pt *range); + +celix_status_t versionRange_destroy(version_range_pt range); + +/** + * Determine if the specified version is part of the version range or not. + * + * @param versionRange The range to check <code>version</code> against. + * @param version The version to check. + * @param inRange True if the specified version is included in this version range, false otherwise. + * @return Status code indication failure or success: + * - CELIX_SUCCESS when no errors are encountered. + */ +celix_status_t versionRange_isInRange(version_range_pt versionRange, version_pt version, bool *inRange); + +/** + * Parses a version range from the specified string. + * + * <p> + * Here is the grammar for version range strings. + * + * <pre> + * version-range ::= interval | atleast + * interval ::= ( '[' | '(' ) floor ',' ceiling ( ']' | ')' ) + * atleast ::= version + * floor ::= version + * ceiling ::= version + * </pre> + * + * @param rangeStr String representation of the version range. + * @param range The created version_range_pt. + * @return Status code indication failure or success: + * - CELIX_SUCCESS when no errors are encountered. + * - CELIX_ENOMEM If allocating memory for <code>versionRange</code> failed. + * - CELIX_ILLEGAL_ARGUMENT If the numerical components are negative, + * the qualifier string is invalid or <code>versionStr</code> is impropertly formatted. + */ +celix_status_t versionRange_parse(char * rangeStr, version_range_pt *range); + +/** + * @} + */ + +#endif /* VERSION_RANGE_H_ */
