Add 'features/FEATURE_COMMON_PAL/mbed-client-randlib/' from commit '26cdd3904f3042c21155a39e940fafb266af20d2'

git-subtree-dir: features/FEATURE_COMMON_PAL/mbed-client-randlib
git-subtree-mainline: 6aedb5aeb7
git-subtree-split: 26cdd3904f
pull/3240/head
Seppo Takalo 2016-11-09 15:13:57 +02:00
commit 8c669c6f40
20 changed files with 1547 additions and 0 deletions

View File

@ -0,0 +1 @@
output/*

View File

@ -0,0 +1,2 @@
linux/*
test/*

View File

@ -0,0 +1,2 @@
Unless specifically indicated otherwise in a file, files are licensed
under the Apache 2.0 license, as can be found in: apache-2.0.txt

View File

@ -0,0 +1,5 @@
SRCS := $(wildcard source/*)
LIB := librand.a
EXPORT_HEADERS := mbed-client-randlib
include ../exported_rules.mk

View File

@ -0,0 +1,56 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
You must give any other recipients of the Work or Derivative Works a copy of this License; and
You must cause any modified files to carry prominent notices stating that You changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2014-2015 ARM Limited. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* Licensed 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.
*/
#ifndef ARM_HAL_RANDOM_H_
#define ARM_HAL_RANDOM_H_
#ifdef __cplusplus
extern "C" {
#endif
/**
* \brief This function performs Random number driver init.
*/
extern void arm_random_module_init(void);
/**
* \brief Get random library seed value.
*
* This function should return as random a value as possible, using
* hardware sources. Repeated calls should return different values if
* at all possible.
*/
extern uint32_t arm_random_seed_get(void);
#ifdef __cplusplus
}
#endif
#endif /* ARM_HAL_RANDOM_H_ */

View File

@ -0,0 +1,149 @@
/*
* Copyright (c) 2014-2015 ARM Limited. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* Licensed 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.
*/
/**
* \file randLIB.h
* \brief Pseudo Random Library API:
*
*
* \section net-boot Network Bootstrap Control API:
* - randLIB_seed_random(), Set seed for pseudo random
* - randLIB_get_8bit(), Generate 8-bit random number
* - randLIB_get_16bit(),Generate 16-bit random number
* - randLIB_get_32bit(),Generate 32-bit random number
* - randLIB_get_n_bytes_random(), Generate n-bytes random numbers
*
*/
#ifndef RANDLIB_H_
#define RANDLIB_H_
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* This library is made for getting random numbers for Timing needs in protocols.
*
* **not safe to use for security or cryptographic operations.**
*
*/
/**
* \brief Init seed for Pseudo Random.
*
* Makes call(s) to the platform's arm_random_seed_get() to seed the
* pseudo-random generator.
*
* \return None
*
*/
extern void randLIB_seed_random(void);
/**
* \brief Update seed for pseudo-random generator
*
* Adds seed information to existing generator, to perturb the
* sequence.
* \param seed 64 bits of data to add to the seed.
*/
extern void randLIB_add_seed(uint64_t seed);
/**
* \brief Generate 8-bit random number.
*
* \param None
* \return 8-bit random number
*
*/
extern uint8_t randLIB_get_8bit(void);
/**
* \brief Generate 16-bit random number.
*
* \param None
* \return 16-bit random number
*
*/
extern uint16_t randLIB_get_16bit(void);
/**
* \brief Generate 32-bit random number.
*
* \param None
* \return 32-bit random number
*
*/
extern uint32_t randLIB_get_32bit(void);
/**
* \brief Generate 64-bit random number.
*
* \param None
* \return 64-bit random number
*
*/
extern uint64_t randLIB_get_64bit(void);
/**
* \brief Generate n-bytes random numbers.
*
* \param data_ptr pointer where random will be stored
* \param count how many bytes need random
*
* \return data_ptr
*/
extern void *randLIB_get_n_bytes_random(void *data_ptr, uint8_t count);
/**
* \brief Generate a random number within a range.
*
* The result is linearly distributed in the range [min..max], inclusive.
*
* \param min minimum value that can be generated
* \param max maximum value that can be generated
*/
uint16_t randLIB_get_random_in_range(uint16_t min, uint16_t max);
/**
* \brief Randomise a base 32-bit number by a jitter factor
*
* The result is linearly distributed in the jitter range, which is expressed
* as fixed-point unsigned 1.15 values. For example, to produce a number in the
* range [0.75 * base, 1.25 * base], set min_factor to 0x6000 and max_factor to
* 0xA000.
*
* Result is clamped to 0xFFFFFFFF if it overflows.
*
* \param base The base 32-bit value
* \param min_factor The minimum value for the random factor
* \param max_factor The maximum value for the random factor
*/
uint32_t randLIB_randomise_base(uint32_t base, uint16_t min_factor, uint16_t max_factor);
#ifdef RANDLIB_PRNG
/* \internal Reset the PRNG state to zero (invalid) */
void randLIB_reset(void);
#endif
#ifdef __cplusplus
}
#endif
#endif /* RANDLIB_H_ */

View File

@ -0,0 +1,13 @@
{
"name": "nanostack-randlib",
"version": "1.2.0",
"description": "Pseudo random library used by mbed-client and 6LoWPAN stack.",
"keywords": [],
"homepage": "https://github.com/ARMmbed/mbed-client-randlib",
"license": "Apache-2.0",
"extraIncludes": [
"mbed-client-randlib"
],
"dependencies": {},
"targetDependencies": {}
}

View File

@ -0,0 +1,266 @@
/*
* Copyright (c) 2014-2015 ARM Limited. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
* Licensed 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.
*/
#include <stdint.h>
#include <limits.h>
#include "randLIB.h"
#include "platform/arm_hal_random.h"
/**
* This library is made for getting random numbers for timing needs in
* protocols, plus to generate dynamic ports, random IDs etc.
*
* **not safe to use for security or cryptographic operations.**
*
* Base implementation is a pseudo-RNG, but may also use a system RNG.
* Replay of sequence by reseeding is not possible.
*
* Base pseudo-RNG is the xoroshiro128+ generator by Marsaglia, Blackman and
* Vigna:
*
* http://xoroshiro.di.unimi.it/
*
* Certainly not the fastest for 32-bit or smaller platforms, but speed
* is not critical. None of the long operations in the core are actually hard,
* unlike the divisions and multiplies in the utility functions below, where we
* do try to keep the operations narrow.
*/
/* On some platforms, read from a system RNG, rather than use our own */
/* RANDLIB_PRNG disables this and forces use of the PRNG (useful for test only?) */
#ifndef RANDLIB_PRNG
#ifdef __linux
#define RANDOM_DEVICE "/dev/urandom"
#endif
#endif // RANDLIB_PRNG
/* RAM usage - 16 bytes of state (or a FILE * pointer and underlying FILE, which
* will include a buffer) */
#ifdef RANDOM_DEVICE
#include <stdio.h>
static FILE *random_file;
#else
static uint64_t state[2];
#endif
#ifdef RANDLIB_PRNG
void randLIB_reset(void)
{
state[0] = 0;
state[1] = 0;
}
#endif
#ifndef RANDOM_DEVICE
static inline uint64_t rol(uint64_t n, int bits)
{
return (n << bits) | (n >> (64 - bits));
}
/* Lower-quality generator used only for initial seeding, if platform
* isn't returning multiple seeds itself. Multiplies are rather heavy
* for lower-end platforms, but this is initialisation only.
*/
static uint64_t splitmix64(uint64_t *seed)
{
uint64_t z = (*seed += UINT64_C(0x9E3779B97F4A7C15));
z = (z ^ (z >> 30)) * UINT64_C(0xBF58476D1CE4E5B9);
z = (z ^ (z >> 27)) * UINT64_C(0x94D049BB133111EB);
return z ^ (z >> 31);
}
#endif // RANDOM_DEVICE
void randLIB_seed_random(void)
{
#ifdef RANDOM_DEVICE
if (!random_file) {
random_file = fopen(RANDOM_DEVICE, "rb");
}
#else
arm_random_module_init();
/* We exclusive-OR with the current state, in case they make this call
* multiple times,or in case someone has called randLIB_add_seed before
* this. We don't want to potentially lose entropy.
*/
/* Spell out expressions so we get known ordering of 4 seed calls */
uint64_t s = (uint64_t) arm_random_seed_get() << 32;
state[0] ^= ( s | arm_random_seed_get());
s = (uint64_t) arm_random_seed_get() << 32;
state[1] ^= s | arm_random_seed_get();
/* This check serves to both to stir the state if the platform is returning
* constant seeding values, and to avoid the illegal all-zero state.
*/
if (state[0] == state[1]) {
randLIB_add_seed(state[0]);
}
#endif // RANDOM_DEVICE
}
void randLIB_add_seed(uint64_t seed)
{
#ifndef RANDOM_DEVICE
state[0] ^= splitmix64(&seed);
state[1] ^= splitmix64(&seed);
/* This is absolutely necessary, but I challenge you to add it to line coverage */
if (state[1] == 0 && state[0] == 0) {
state[0] = 1;
}
#endif
}
uint8_t randLIB_get_8bit(void)
{
uint64_t r = randLIB_get_64bit();
return (uint8_t) (r >> 56);
}
uint16_t randLIB_get_16bit(void)
{
uint64_t r = randLIB_get_64bit();
return (uint16_t) (r >> 48);
}
uint32_t randLIB_get_32bit(void)
{
uint64_t r = randLIB_get_64bit();
return (uint32_t) (r >> 32);
}
uint64_t randLIB_get_64bit(void)
{
#ifdef RANDOM_DEVICE
if (!random_file) {
return 0;
}
uint64_t result;
if (fread(&result, sizeof result, 1, random_file) != 1) {
result = 0;
}
return result;
#else
const uint64_t s0 = state[0];
uint64_t s1 = state[1];
const uint64_t result = s0 + s1;
s1 ^= s0;
state[0] = rol(s0, 55) ^ s1 ^ (s1 << 14);
state[1] = rol(s1, 36);
return result;
#endif
}
void *randLIB_get_n_bytes_random(void *ptr, uint8_t count)
{
uint8_t *data_ptr = ptr;
uint64_t r = 0;
for (uint_fast8_t i = 0; i < count; i++) {
/* Take 8 bytes at a time */
if (i % 8 == 0) {
r = randLIB_get_64bit();
} else {
r >>= 8;
}
data_ptr[i] = (uint8_t) r;
}
return data_ptr;
}
uint16_t randLIB_get_random_in_range(uint16_t min, uint16_t max)
{
/* This special case is potentially common, particularly in this routine's
* first user (Trickle), so worth catching immediately */
if (min == max) {
return min;
}
#if UINT_MAX >= 0xFFFFFFFF
const unsigned int rand_max = 0xFFFFFFFFu; // will use rand32
#else
const unsigned int rand_max = 0xFFFFu; // will use rand16
/* 16-bit arithmetic below fails in this extreme case; we can optimise it */
if (max - min == 0xFFFF) {
return randLIB_get_16bit();
}
#endif
/* We get rand_max values from rand16 or 32() in the range [0..rand_max-1], and
* need to divvy them up into the number of values we need. And reroll any
* odd values off the end as we insist every value having equal chance.
*
* Using the range [0..rand_max-1] saves long division on the band
* calculation - it means rand_max ends up always being rerolled.
*
* Eg, range(1,2), rand_max = 0xFFFF:
* We have 2 bands of size 0x7FFF (0xFFFF/2).
*
* We roll: 0x0000..0x7FFE -> 1
* 0x7FFF..0xFFFD -> 2
* 0xFFFE..0xFFFF -> reroll
* (calculating band size as 0x10000/2 would have avoided the reroll cases)
*
* Eg, range(1,3), rand_max = 0xFFFFFFFF:
* We have 3 bands of size 0x55555555 (0xFFFFFFFF/3).
*
* We roll: 0x00000000..0x555555554 -> 1
* 0x55555555..0xAAAAAAAA9 -> 2
* 0xAAAAAAAA..0xFFFFFFFFE -> 3
* 0xFFFFFFFF -> reroll
*
* (Bias problem clearly pretty insignificant there, but gets worse as
* range increases).
*/
const unsigned int values_needed = max + 1 - min;
/* Avoid the need for long division, at the expense of fractionally
* increasing reroll chance. */
const unsigned int band_size = rand_max / values_needed;
const unsigned int top_of_bands = band_size * values_needed;
unsigned int result;
do {
#if UINT_MAX > 0xFFFF
result = randLIB_get_32bit();
#else
result = randLIB_get_16bit();
#endif
} while (result >= top_of_bands);
return min + (uint16_t)(result / band_size);
}
uint32_t randLIB_randomise_base(uint32_t base, uint16_t min_factor, uint16_t max_factor)
{
uint16_t random_factor = randLIB_get_random_in_range(min_factor, max_factor);
/* 32x16-bit long multiplication, to get 48-bit result */
uint32_t hi = (base >> 16) * random_factor;
uint32_t lo = (base & 0xFFFF) * random_factor;
/* Add halves, and take top 32 bits of 48-bit result */
uint32_t res = hi + (lo >> 16);
/* Randomisation factor is *2^15, so need to shift up 1 more bit, avoiding overflow */
if (res & 0x80000000) {
res = 0xFFFFFFFF;
} else {
res = (res << 1) | ((lo >> 15) & 1);
}
return res;
}

View File

@ -0,0 +1,23 @@
#scan for folders having "Makefile" in them and remove 'this' to prevent loop
ifeq ($(OS),Windows_NT)
all:
clean:
else
DIRS := $(filter-out ./, $(sort $(dir $(shell find . -name 'Makefile'))))
all:
for dir in $(DIRS); do \
cd $$dir; make gcov; cd ..;\
done
clean:
for dir in $(DIRS); do \
cd $$dir; make clean; cd ..;\
done
rm -rf ../source/*gcov ../source/*gcda ../source/*o
rm -rf stubs/*gcov stubs/*gcda stubs/*o
rm -rf results/*
rm -rf coverages/*
rm -rf results
rm -rf coverages
endif

View File

@ -0,0 +1,562 @@
#---------
#
# MakefileWorker.mk
#
# Include this helper file in your makefile
# It makes
# A static library
# A test executable
#
# See this example for parameter settings
# examples/Makefile
#
#----------
# Inputs - these variables describe what to build
#
# INCLUDE_DIRS - Directories used to search for include files.
# This generates a -I for each directory
# SRC_DIRS - Directories containing source file to built into the library
# SRC_FILES - Specific source files to build into library. Helpful when not all code
# in a directory can be built for test (hopefully a temporary situation)
# TEST_SRC_DIRS - Directories containing unit test code build into the unit test runner
# These do not go in a library. They are explicitly included in the test runner
# TEST_SRC_FILES - Specific source files to build into the unit test runner
# These do not go in a library. They are explicitly included in the test runner
# MOCKS_SRC_DIRS - Directories containing mock source files to build into the test runner
# These do not go in a library. They are explicitly included in the test runner
#----------
# You can adjust these variables to influence how to build the test target
# and where to put and name outputs
# See below to determine defaults
# COMPONENT_NAME - the name of the thing being built
# TEST_TARGET - name the test executable. By default it is
# $(COMPONENT_NAME)_tests
# Helpful if you want 1 > make files in the same directory with different
# executables as output.
# CPPUTEST_HOME - where CppUTest home dir found
# TARGET_PLATFORM - Influences how the outputs are generated by modifying the
# CPPUTEST_OBJS_DIR and CPPUTEST_LIB_DIR to use a sub-directory under the
# normal objs and lib directories. Also modifies where to search for the
# CPPUTEST_LIB to link against.
# CPPUTEST_OBJS_DIR - a directory where o and d files go
# CPPUTEST_LIB_DIR - a directory where libs go
# CPPUTEST_ENABLE_DEBUG - build for debug
# CPPUTEST_USE_MEM_LEAK_DETECTION - Links with overridden new and delete
# CPPUTEST_USE_STD_CPP_LIB - Set to N to keep the standard C++ library out
# of the test harness
# CPPUTEST_USE_GCOV - Turn on coverage analysis
# Clean then build with this flag set to Y, then 'make gcov'
# CPPUTEST_MAPFILE - generate a map file
# CPPUTEST_WARNINGFLAGS - overly picky by default
# OTHER_MAKEFILE_TO_INCLUDE - a hook to use this makefile to make
# other targets. Like CSlim, which is part of fitnesse
# CPPUTEST_USE_VPATH - Use Make's VPATH functionality to support user
# specification of source files and directories that aren't below
# the user's Makefile in the directory tree, like:
# SRC_DIRS += ../../lib/foo
# It defaults to N, and shouldn't be necessary except in the above case.
#----------
#
# Other flags users can initialize to sneak in their settings
# CPPUTEST_CXXFLAGS - flags for the C++ compiler
# CPPUTEST_CPPFLAGS - flags for the C++ AND C preprocessor
# CPPUTEST_CFLAGS - flags for the C complier
# CPPUTEST_LDFLAGS - Linker flags
#----------
# Some behavior is weird on some platforms. Need to discover the platform.
# Platforms
UNAME_OUTPUT = "$(shell uname -a)"
MACOSX_STR = Darwin
MINGW_STR = MINGW
CYGWIN_STR = CYGWIN
LINUX_STR = Linux
SUNOS_STR = SunOS
UNKNWOWN_OS_STR = Unknown
# Compilers
CC_VERSION_OUTPUT ="$(shell $(CXX) -v 2>&1)"
CLANG_STR = clang
SUNSTUDIO_CXX_STR = SunStudio
UNAME_OS = $(UNKNWOWN_OS_STR)
ifeq ($(findstring $(MINGW_STR),$(UNAME_OUTPUT)),$(MINGW_STR))
UNAME_OS = $(MINGW_STR)
endif
ifeq ($(findstring $(CYGWIN_STR),$(UNAME_OUTPUT)),$(CYGWIN_STR))
UNAME_OS = $(CYGWIN_STR)
endif
ifeq ($(findstring $(LINUX_STR),$(UNAME_OUTPUT)),$(LINUX_STR))
UNAME_OS = $(LINUX_STR)
endif
ifeq ($(findstring $(MACOSX_STR),$(UNAME_OUTPUT)),$(MACOSX_STR))
UNAME_OS = $(MACOSX_STR)
#lion has a problem with the 'v' part of -a
UNAME_OUTPUT = "$(shell uname -pmnrs)"
endif
ifeq ($(findstring $(SUNOS_STR),$(UNAME_OUTPUT)),$(SUNOS_STR))
UNAME_OS = $(SUNOS_STR)
SUNSTUDIO_CXX_ERR_STR = CC -flags
ifeq ($(findstring $(SUNSTUDIO_CXX_ERR_STR),$(CC_VERSION_OUTPUT)),$(SUNSTUDIO_CXX_ERR_STR))
CC_VERSION_OUTPUT ="$(shell $(CXX) -V 2>&1)"
COMPILER_NAME = $(SUNSTUDIO_CXX_STR)
endif
endif
ifeq ($(findstring $(CLANG_STR),$(CC_VERSION_OUTPUT)),$(CLANG_STR))
COMPILER_NAME = $(CLANG_STR)
endif
#Kludge for mingw, it does not have cc.exe, but gcc.exe will do
ifeq ($(UNAME_OS),$(MINGW_STR))
CC := gcc
endif
#And another kludge. Exception handling in gcc 4.6.2 is broken when linking the
# Standard C++ library as a shared library. Unbelievable.
ifeq ($(UNAME_OS),$(MINGW_STR))
CPPUTEST_LDFLAGS += -static
endif
ifeq ($(UNAME_OS),$(CYGWIN_STR))
CPPUTEST_LDFLAGS += -static
endif
#Kludge for MacOsX gcc compiler on Darwin9 who can't handle pendantic
ifeq ($(UNAME_OS),$(MACOSX_STR))
ifeq ($(findstring Version 9,$(UNAME_OUTPUT)),Version 9)
CPPUTEST_PEDANTIC_ERRORS = N
endif
endif
ifndef COMPONENT_NAME
COMPONENT_NAME = name_this_in_the_makefile
endif
# Debug on by default
ifndef CPPUTEST_ENABLE_DEBUG
CPPUTEST_ENABLE_DEBUG = Y
endif
# new and delete for memory leak detection on by default
ifndef CPPUTEST_USE_MEM_LEAK_DETECTION
CPPUTEST_USE_MEM_LEAK_DETECTION = Y
endif
# Use the standard C library
ifndef CPPUTEST_USE_STD_C_LIB
CPPUTEST_USE_STD_C_LIB = Y
endif
# Use the standard C++ library
ifndef CPPUTEST_USE_STD_CPP_LIB
CPPUTEST_USE_STD_CPP_LIB = Y
endif
# Use gcov, off by default
ifndef CPPUTEST_USE_GCOV
CPPUTEST_USE_GCOV = N
endif
ifndef CPPUTEST_PEDANTIC_ERRORS
CPPUTEST_PEDANTIC_ERRORS = Y
endif
# Default warnings
ifndef CPPUTEST_WARNINGFLAGS
CPPUTEST_WARNINGFLAGS = -Wall -Wextra -Wshadow -Wswitch-default -Wswitch-enum -Wconversion
ifeq ($(CPPUTEST_PEDANTIC_ERRORS), Y)
# CPPUTEST_WARNINGFLAGS += -pedantic-errors
CPPUTEST_WARNINGFLAGS += -pedantic
endif
ifeq ($(UNAME_OS),$(LINUX_STR))
CPPUTEST_WARNINGFLAGS += -Wsign-conversion
endif
CPPUTEST_CXX_WARNINGFLAGS = -Woverloaded-virtual
CPPUTEST_C_WARNINGFLAGS = -Wstrict-prototypes
endif
#Wonderful extra compiler warnings with clang
ifeq ($(COMPILER_NAME),$(CLANG_STR))
# -Wno-disabled-macro-expansion -> Have to disable the macro expansion warning as the operator new overload warns on that.
# -Wno-padded -> I sort-of like this warning but if there is a bool at the end of the class, it seems impossible to remove it! (except by making padding explicit)
# -Wno-global-constructors Wno-exit-time-destructors -> Great warnings, but in CppUTest it is impossible to avoid as the automatic test registration depends on the global ctor and dtor
# -Wno-weak-vtables -> The TEST_GROUP macro declares a class and will automatically inline its methods. Thats ok as they are only in one translation unit. Unfortunately, the warning can't detect that, so it must be disabled.
CPPUTEST_CXX_WARNINGFLAGS += -Weverything -Wno-disabled-macro-expansion -Wno-padded -Wno-global-constructors -Wno-exit-time-destructors -Wno-weak-vtables
CPPUTEST_C_WARNINGFLAGS += -Weverything -Wno-padded
endif
# Uhm. Maybe put some warning flags for SunStudio here?
ifeq ($(COMPILER_NAME),$(SUNSTUDIO_CXX_STR))
CPPUTEST_CXX_WARNINGFLAGS =
CPPUTEST_C_WARNINGFLAGS =
endif
# Default dir for temporary files (d, o)
ifndef CPPUTEST_OBJS_DIR
ifndef TARGET_PLATFORM
CPPUTEST_OBJS_DIR = objs
else
CPPUTEST_OBJS_DIR = objs/$(TARGET_PLATFORM)
endif
endif
# Default dir for the outout library
ifndef CPPUTEST_LIB_DIR
ifndef TARGET_PLATFORM
CPPUTEST_LIB_DIR = lib
else
CPPUTEST_LIB_DIR = lib/$(TARGET_PLATFORM)
endif
endif
# No map by default
ifndef CPPUTEST_MAP_FILE
CPPUTEST_MAP_FILE = N
endif
# No extentions is default
ifndef CPPUTEST_USE_EXTENSIONS
CPPUTEST_USE_EXTENSIONS = N
endif
# No VPATH is default
ifndef CPPUTEST_USE_VPATH
CPPUTEST_USE_VPATH := N
endif
# Make empty, instead of 'N', for usage in $(if ) conditionals
ifneq ($(CPPUTEST_USE_VPATH), Y)
CPPUTEST_USE_VPATH :=
endif
ifndef TARGET_PLATFORM
#CPPUTEST_LIB_LINK_DIR = $(CPPUTEST_HOME)/lib
CPPUTEST_LIB_LINK_DIR = /usr/lib/x86_64-linux-gnu
else
CPPUTEST_LIB_LINK_DIR = $(CPPUTEST_HOME)/lib/$(TARGET_PLATFORM)
endif
# --------------------------------------
# derived flags in the following area
# --------------------------------------
# Without the C library, we'll need to disable the C++ library and ...
ifeq ($(CPPUTEST_USE_STD_C_LIB), N)
CPPUTEST_USE_STD_CPP_LIB = N
CPPUTEST_USE_MEM_LEAK_DETECTION = N
CPPUTEST_CPPFLAGS += -DCPPUTEST_STD_C_LIB_DISABLED
CPPUTEST_CPPFLAGS += -nostdinc
endif
CPPUTEST_CPPFLAGS += -DCPPUTEST_COMPILATION
ifeq ($(CPPUTEST_USE_MEM_LEAK_DETECTION), N)
CPPUTEST_CPPFLAGS += -DCPPUTEST_MEM_LEAK_DETECTION_DISABLED
else
ifndef CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE
CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE = -include $(CPPUTEST_HOME)/include/CppUTest/MemoryLeakDetectorNewMacros.h
endif
ifndef CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE
CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE = -include $(CPPUTEST_HOME)/include/CppUTest/MemoryLeakDetectorMallocMacros.h
endif
endif
ifeq ($(CPPUTEST_ENABLE_DEBUG), Y)
CPPUTEST_CXXFLAGS += -g
CPPUTEST_CFLAGS += -g
CPPUTEST_LDFLAGS += -g
endif
ifeq ($(CPPUTEST_USE_STD_CPP_LIB), N)
CPPUTEST_CPPFLAGS += -DCPPUTEST_STD_CPP_LIB_DISABLED
ifeq ($(CPPUTEST_USE_STD_C_LIB), Y)
CPPUTEST_CXXFLAGS += -nostdinc++
endif
endif
ifdef $(GMOCK_HOME)
GTEST_HOME = $(GMOCK_HOME)/gtest
CPPUTEST_CPPFLAGS += -I$(GMOCK_HOME)/include
GMOCK_LIBRARY = $(GMOCK_HOME)/lib/.libs/libgmock.a
LD_LIBRARIES += $(GMOCK_LIBRARY)
CPPUTEST_CPPFLAGS += -DINCLUDE_GTEST_TESTS
CPPUTEST_WARNINGFLAGS =
CPPUTEST_CPPFLAGS += -I$(GTEST_HOME)/include -I$(GTEST_HOME)
GTEST_LIBRARY = $(GTEST_HOME)/lib/.libs/libgtest.a
LD_LIBRARIES += $(GTEST_LIBRARY)
endif
ifeq ($(CPPUTEST_USE_GCOV), Y)
CPPUTEST_CXXFLAGS += -fprofile-arcs -ftest-coverage
CPPUTEST_CFLAGS += -fprofile-arcs -ftest-coverage
endif
CPPUTEST_CXXFLAGS += $(CPPUTEST_WARNINGFLAGS) $(CPPUTEST_CXX_WARNINGFLAGS)
CPPUTEST_CPPFLAGS += $(CPPUTEST_WARNINGFLAGS)
CPPUTEST_CXXFLAGS += $(CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE)
CPPUTEST_CPPFLAGS += $(CPPUTEST_MEMLEAK_DETECTOR_MALLOC_MACRO_FILE)
CPPUTEST_CFLAGS += $(CPPUTEST_C_WARNINGFLAGS)
TARGET_MAP = $(COMPONENT_NAME).map.txt
ifeq ($(CPPUTEST_MAP_FILE), Y)
CPPUTEST_LDFLAGS += -Wl,-map,$(TARGET_MAP)
endif
# Link with CppUTest lib
CPPUTEST_LIB = $(CPPUTEST_LIB_LINK_DIR)/libCppUTest.a
ifeq ($(CPPUTEST_USE_EXTENSIONS), Y)
CPPUTEST_LIB += $(CPPUTEST_LIB_LINK_DIR)/libCppUTestExt.a
endif
ifdef CPPUTEST_STATIC_REALTIME
LD_LIBRARIES += -lrt
endif
TARGET_LIB = \
$(CPPUTEST_LIB_DIR)/lib$(COMPONENT_NAME).a
ifndef TEST_TARGET
ifndef TARGET_PLATFORM
TEST_TARGET = $(COMPONENT_NAME)_tests
else
TEST_TARGET = $(COMPONENT_NAME)_$(TARGET_PLATFORM)_tests
endif
endif
#Helper Functions
get_src_from_dir = $(wildcard $1/*.cpp) $(wildcard $1/*.cc) $(wildcard $1/*.c)
get_dirs_from_dirspec = $(wildcard $1)
get_src_from_dir_list = $(foreach dir, $1, $(call get_src_from_dir,$(dir)))
__src_to = $(subst .c,$1, $(subst .cc,$1, $(subst .cpp,$1,$(if $(CPPUTEST_USE_VPATH),$(notdir $2),$2))))
src_to = $(addprefix $(CPPUTEST_OBJS_DIR)/,$(call __src_to,$1,$2))
src_to_o = $(call src_to,.o,$1)
src_to_d = $(call src_to,.d,$1)
src_to_gcda = $(call src_to,.gcda,$1)
src_to_gcno = $(call src_to,.gcno,$1)
time = $(shell date +%s)
delta_t = $(eval minus, $1, $2)
debug_print_list = $(foreach word,$1,echo " $(word)";) echo;
#Derived
STUFF_TO_CLEAN += $(TEST_TARGET) $(TEST_TARGET).exe $(TARGET_LIB) $(TARGET_MAP)
SRC += $(call get_src_from_dir_list, $(SRC_DIRS)) $(SRC_FILES)
OBJ = $(call src_to_o,$(SRC))
STUFF_TO_CLEAN += $(OBJ)
TEST_SRC += $(call get_src_from_dir_list, $(TEST_SRC_DIRS)) $(TEST_SRC_FILES)
TEST_OBJS = $(call src_to_o,$(TEST_SRC))
STUFF_TO_CLEAN += $(TEST_OBJS)
MOCKS_SRC += $(call get_src_from_dir_list, $(MOCKS_SRC_DIRS))
MOCKS_OBJS = $(call src_to_o,$(MOCKS_SRC))
STUFF_TO_CLEAN += $(MOCKS_OBJS)
ALL_SRC = $(SRC) $(TEST_SRC) $(MOCKS_SRC)
# If we're using VPATH
ifeq ($(CPPUTEST_USE_VPATH), Y)
# gather all the source directories and add them
VPATH += $(sort $(dir $(ALL_SRC)))
# Add the component name to the objs dir path, to differentiate between same-name objects
CPPUTEST_OBJS_DIR := $(addsuffix /$(COMPONENT_NAME),$(CPPUTEST_OBJS_DIR))
endif
#Test coverage with gcov
GCOV_OUTPUT = gcov_output.txt
GCOV_REPORT = gcov_report.txt
GCOV_ERROR = gcov_error.txt
GCOV_GCDA_FILES = $(call src_to_gcda, $(ALL_SRC))
GCOV_GCNO_FILES = $(call src_to_gcno, $(ALL_SRC))
TEST_OUTPUT = $(TEST_TARGET).txt
STUFF_TO_CLEAN += \
$(GCOV_OUTPUT)\
$(GCOV_REPORT)\
$(GCOV_REPORT).html\
$(GCOV_ERROR)\
$(GCOV_GCDA_FILES)\
$(GCOV_GCNO_FILES)\
$(TEST_OUTPUT)
#The gcda files for gcov need to be deleted before each run
#To avoid annoying messages.
GCOV_CLEAN = $(SILENCE)rm -f $(GCOV_GCDA_FILES) $(GCOV_OUTPUT) $(GCOV_REPORT) $(GCOV_ERROR)
RUN_TEST_TARGET = $(SILENCE) $(GCOV_CLEAN) ; echo "Running $(TEST_TARGET)"; ./$(TEST_TARGET) $(CPPUTEST_EXE_FLAGS) -ojunit
ifeq ($(CPPUTEST_USE_GCOV), Y)
ifeq ($(COMPILER_NAME),$(CLANG_STR))
LD_LIBRARIES += --coverage
else
LD_LIBRARIES += -lgcov
endif
endif
INCLUDES_DIRS_EXPANDED = $(call get_dirs_from_dirspec, $(INCLUDE_DIRS))
INCLUDES += $(foreach dir, $(INCLUDES_DIRS_EXPANDED), -I$(dir))
MOCK_DIRS_EXPANDED = $(call get_dirs_from_dirspec, $(MOCKS_SRC_DIRS))
INCLUDES += $(foreach dir, $(MOCK_DIRS_EXPANDED), -I$(dir))
CPPUTEST_CPPFLAGS += $(INCLUDES) $(CPPUTESTFLAGS)
DEP_FILES = $(call src_to_d, $(ALL_SRC))
STUFF_TO_CLEAN += $(DEP_FILES) $(PRODUCTION_CODE_START) $(PRODUCTION_CODE_END)
STUFF_TO_CLEAN += $(STDLIB_CODE_START) $(MAP_FILE) cpputest_*.xml junit_run_output
# We'll use the CPPUTEST_CFLAGS etc so that you can override AND add to the CppUTest flags
CFLAGS = $(CPPUTEST_CFLAGS) $(CPPUTEST_ADDITIONAL_CFLAGS)
CPPFLAGS = $(CPPUTEST_CPPFLAGS) $(CPPUTEST_ADDITIONAL_CPPFLAGS)
CXXFLAGS = $(CPPUTEST_CXXFLAGS) $(CPPUTEST_ADDITIONAL_CXXFLAGS)
LDFLAGS = $(CPPUTEST_LDFLAGS) $(CPPUTEST_ADDITIONAL_LDFLAGS)
# Don't consider creating the archive a warning condition that does STDERR output
ARFLAGS := $(ARFLAGS)c
DEP_FLAGS=-MMD -MP
# Some macros for programs to be overridden. For some reason, these are not in Make defaults
RANLIB = ranlib
# Targets
.PHONY: all
all: start $(TEST_TARGET)
$(RUN_TEST_TARGET)
.PHONY: start
start: $(TEST_TARGET)
$(SILENCE)START_TIME=$(call time)
.PHONY: all_no_tests
all_no_tests: $(TEST_TARGET)
.PHONY: flags
flags:
@echo
@echo "OS ${UNAME_OS}"
@echo "Compile C and C++ source with CPPFLAGS:"
@$(call debug_print_list,$(CPPFLAGS))
@echo "Compile C++ source with CXXFLAGS:"
@$(call debug_print_list,$(CXXFLAGS))
@echo "Compile C source with CFLAGS:"
@$(call debug_print_list,$(CFLAGS))
@echo "Link with LDFLAGS:"
@$(call debug_print_list,$(LDFLAGS))
@echo "Link with LD_LIBRARIES:"
@$(call debug_print_list,$(LD_LIBRARIES))
@echo "Create libraries with ARFLAGS:"
@$(call debug_print_list,$(ARFLAGS))
TEST_DEPS = $(TEST_OBJS) $(MOCKS_OBJS) $(PRODUCTION_CODE_START) $(TARGET_LIB) $(USER_LIBS) $(PRODUCTION_CODE_END) $(CPPUTEST_LIB) $(STDLIB_CODE_START)
test-deps: $(TEST_DEPS)
$(TEST_TARGET): $(TEST_DEPS)
@echo Linking $@
$(SILENCE)$(CXX) -o $@ $^ $(LD_LIBRARIES) $(LDFLAGS)
$(TARGET_LIB): $(OBJ)
@echo Building archive $@
$(SILENCE)mkdir -p $(dir $@)
$(SILENCE)$(AR) $(ARFLAGS) $@ $^
$(SILENCE)$(RANLIB) $@
test: $(TEST_TARGET)
$(RUN_TEST_TARGET) | tee $(TEST_OUTPUT)
vtest: $(TEST_TARGET)
$(RUN_TEST_TARGET) -v | tee $(TEST_OUTPUT)
$(CPPUTEST_OBJS_DIR)/%.o: %.cc
@echo compiling $(notdir $<)
$(SILENCE)mkdir -p $(dir $@)
$(SILENCE)$(COMPILE.cpp) $(DEP_FLAGS) $(OUTPUT_OPTION) $<
$(CPPUTEST_OBJS_DIR)/%.o: %.cpp
@echo compiling $(notdir $<)
$(SILENCE)mkdir -p $(dir $@)
$(SILENCE)$(COMPILE.cpp) $(DEP_FLAGS) $(OUTPUT_OPTION) $<
$(CPPUTEST_OBJS_DIR)/%.o: %.c
@echo compiling $(notdir $<)
$(SILENCE)mkdir -p $(dir $@)
$(SILENCE)$(COMPILE.c) $(DEP_FLAGS) $(OUTPUT_OPTION) $<
ifneq "$(MAKECMDGOALS)" "clean"
-include $(DEP_FILES)
endif
.PHONY: clean
clean:
@echo Making clean
$(SILENCE)$(RM) $(STUFF_TO_CLEAN)
$(SILENCE)rm -rf gcov objs #$(CPPUTEST_OBJS_DIR)
$(SILENCE)rm -rf $(CPPUTEST_LIB_DIR)
$(SILENCE)find . -name "*.gcno" | xargs rm -f
$(SILENCE)find . -name "*.gcda" | xargs rm -f
#realclean gets rid of all gcov, o and d files in the directory tree
#not just the ones made by this makefile
.PHONY: realclean
realclean: clean
$(SILENCE)rm -rf gcov
$(SILENCE)find . -name "*.gdcno" | xargs rm -f
$(SILENCE)find . -name "*.[do]" | xargs rm -f
gcov: test
ifeq ($(CPPUTEST_USE_VPATH), Y)
$(SILENCE)gcov --object-directory $(CPPUTEST_OBJS_DIR) $(SRC) >> $(GCOV_OUTPUT) 2>> $(GCOV_ERROR)
else
$(SILENCE)for d in $(SRC_DIRS) ; do \
gcov --object-directory $(CPPUTEST_OBJS_DIR)/$$d $$d/*.c $$d/*.cpp >> $(GCOV_OUTPUT) 2>>$(GCOV_ERROR) ; \
done
$(SILENCE)for f in $(SRC_FILES) ; do \
gcov --object-directory $(CPPUTEST_OBJS_DIR)/$$f $$f >> $(GCOV_OUTPUT) 2>>$(GCOV_ERROR) ; \
done
endif
# $(CPPUTEST_HOME)/scripts/filterGcov.sh $(GCOV_OUTPUT) $(GCOV_ERROR) $(GCOV_REPORT) $(TEST_OUTPUT)
/usr/share/cpputest/scripts/filterGcov.sh $(GCOV_OUTPUT) $(GCOV_ERROR) $(GCOV_REPORT) $(TEST_OUTPUT)
$(SILENCE)cat $(GCOV_REPORT)
$(SILENCE)mkdir -p gcov
$(SILENCE)mv *.gcov gcov
$(SILENCE)mv gcov_* gcov
@echo "See gcov directory for details"
.PHONEY: format
format:
$(CPPUTEST_HOME)/scripts/reformat.sh $(PROJECT_HOME_DIR)
.PHONEY: debug
debug:
@echo
@echo "Target Source files:"
@$(call debug_print_list,$(SRC))
@echo "Target Object files:"
@$(call debug_print_list,$(OBJ))
@echo "Test Source files:"
@$(call debug_print_list,$(TEST_SRC))
@echo "Test Object files:"
@$(call debug_print_list,$(TEST_OBJS))
@echo "Mock Source files:"
@$(call debug_print_list,$(MOCKS_SRC))
@echo "Mock Object files:"
@$(call debug_print_list,$(MOCKS_OBJS))
@echo "All Input Dependency files:"
@$(call debug_print_list,$(DEP_FILES))
@echo Stuff to clean:
@$(call debug_print_list,$(STUFF_TO_CLEAN))
@echo Includes:
@$(call debug_print_list,$(INCLUDES))
-include $(OTHER_MAKEFILE_TO_INCLUDE)

View File

@ -0,0 +1,18 @@
#--- Inputs ----#
CPPUTEST_HOME = /usr
CPPUTEST_USE_EXTENSIONS = Y
CPPUTEST_USE_VPATH = Y
CPPUTEST_USE_GCOV = Y
CPP_PLATFORM = gcc
INCLUDE_DIRS =\
.\
../common\
../stubs\
../../../..\
../../../../source\
../../../../mbed-client-randlib\
/usr/include\
$(CPPUTEST_HOME)/include\
CPPUTESTFLAGS = -D__thumb2__ -w
CPPUTEST_CFLAGS += -std=gnu99

View File

@ -0,0 +1,18 @@
include ../makefile_defines.txt
COMPONENT_NAME = randLIB_unit
#This must be changed manually
SRC_FILES = \
../../../../source/randLIB.c
TEST_SRC_FILES = \
main.cpp \
randlibtest.cpp \
test_randlib.c \
../stubs/random_stub.c \
include ../MakefileWorker.mk
CPPUTESTFLAGS += -DFEA_TRACE_SUPPORT -DRANDLIB_PRNG

View File

@ -0,0 +1,15 @@
/*
* Copyright (c) 2015 ARM. All rights reserved.
*/
#include "CppUTest/CommandLineTestRunner.h"
#include "CppUTest/TestPlugin.h"
#include "CppUTest/TestRegistry.h"
#include "CppUTestExt/MockSupportPlugin.h"
int main(int ac, char** av)
{
return CommandLineTestRunner::RunAllTests(ac, av);
}
IMPORT_TEST_GROUP(randLIB);

View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2016 ARM. All rights reserved.
*/
#include "CppUTest/TestHarness.h"
#include "test_randlib.h"
TEST_GROUP(randLIB)
{
void setup()
{
}
void teardown()
{
}
};
TEST(randLIB, test_randLIB_seed_random)
{
CHECK(test_randLIB_seed_random());
}
TEST(randLIB, test_randLIB_get_8bit)
{
CHECK(test_randLIB_get_8bit());
}
TEST(randLIB, test_randLIB_get_16bit)
{
CHECK(test_randLIB_get_16bit());
}
TEST(randLIB, test_randLIB_get_32bit)
{
CHECK(test_randLIB_get_32bit());
}
TEST(randLIB, test_randLIB_get_64bit)
{
CHECK(test_randLIB_get_64bit());
}
TEST(randLIB, test_randLIB_get_n_bytes_random)
{
CHECK(test_randLIB_get_n_bytes_random());
}
TEST(randLIB, test_randLIB_get_random_in_range)
{
CHECK(test_randLIB_get_random_in_range());
}
TEST(randLIB, test_randLIB_randomise_base)
{
CHECK(test_randLIB_randomise_base());
}

View File

@ -0,0 +1,195 @@
/*
* Copyright (c) 2016 ARM. All rights reserved.
*/
#include "test_randlib.h"
#include <string.h>
#include <inttypes.h>
#include "randLIB.h"
bool test_randLIB_seed_random()
{
randLIB_reset();
randLIB_seed_random();
return true;
}
bool test_randLIB_get_8bit()
{
randLIB_reset();
randLIB_seed_random();
uint8_t test = randLIB_get_8bit();
if( test == 0 ) {
test = randLIB_get_8bit();
if( test == 0 ) {
return false;
}
}
return true;
}
bool test_randLIB_get_16bit()
{
randLIB_reset();
randLIB_seed_random();
uint16_t test = randLIB_get_16bit();
if( test == 0 ) {
test = randLIB_get_16bit();
if( test == 0 ) {
return false;
}
}
return true;
}
bool test_randLIB_get_32bit()
{
randLIB_reset();
randLIB_seed_random();
uint32_t test = randLIB_get_32bit();
if( test == 0 ) {
test = randLIB_get_32bit();
if( test == 0 ) {
return false;
}
}
return true;
}
static bool test_output(uint32_t seed, bool seed_inc, const uint64_t expected[8])
{
random_stub_set_seed(seed, seed_inc);
randLIB_reset();
randLIB_seed_random();
for (int i = 0; i < 8; i++) {
if (randLIB_get_64bit() != expected[i]) {
return false;
}
}
return true;
}
bool test_randLIB_get_64bit()
{
/* Initial 8 xoroshiro128+ values with initial seed of
* (0x0000000100000002, 0x00000003000000004).
*/
static const uint64_t expected1234[] = {
UINT64_C(0x0000000400000006),
UINT64_C(0x0100806200818026),
UINT64_C(0x2a30826271904706),
UINT64_C(0x918d7ea50109290d),
UINT64_C(0x5dcbd701c1e1c64c),
UINT64_C(0xaa129b152055f299),
UINT64_C(0x4c95c2b1e1038a4d),
UINT64_C(0x6479e7a3a75d865a)
};
if (!test_output(1, true, expected1234)) {
goto fail;
}
/* If passed all zero seeds, seeding should detect this
* and use splitmix64 to create the actual seed
* (0xe220a8397b1dcdaf, 0x6e789e6aa1b965f4),
* and produce this output:
*/
static const uint64_t expected0000[] = {
UINT64_C(0x509946a41cd733a3),
UINT64_C(0x00885667b1934bfa),
UINT64_C(0x1061f9ad258fd5d5),
UINT64_C(0x3f8be44897a4317c),
UINT64_C(0x60da683bea50e6ab),
UINT64_C(0xd6b52f5379de1de0),
UINT64_C(0x2608bc9fedc5b750),
UINT64_C(0xb9fac9c7ec9de02a)
};
if (!test_output(0, false, expected0000)) {
goto fail;
}
/* If passed all "4" seeds, seeding should detect this
* and use splitmix64 to create the actual seed
* (0x03910b0eab9b37e1, 0x0b309ab53d42b2a2),
* and produce this output:
*/
static const uint64_t expected4444[] = {
UINT64_C(0x0ec1a5c3e8ddea83),
UINT64_C(0x09e710b8faf5a491),
UINT64_C(0xd4102776f79448b4),
UINT64_C(0x5d61988b60091900),
UINT64_C(0xf6c8a72a9c72cb4b),
UINT64_C(0xb06923e0cf0f2fb1),
UINT64_C(0x24bbed475153f573),
UINT64_C(0xfff0b4bd08c5581f),
};
if (!test_output(4, false, expected4444)) {
goto fail;
}
/* Last test used constant seed of 4, which is the default */
return true;
fail:
/* Put back the default seed of 4 (other tests might rely on it) */
random_stub_set_seed(4, false);
return false;
}
bool test_randLIB_get_n_bytes_random()
{
randLIB_reset();
randLIB_seed_random();
uint8_t dat[5];
void *ret = randLIB_get_n_bytes_random(dat, 5);
if(ret != dat){
return false;
}
uint8_t dat2[5];
randLIB_get_n_bytes_random(dat2, 5);
if (memcmp(dat, dat2, 5) == 0) {
return false;
}
return true;
}
bool test_randLIB_get_random_in_range()
{
randLIB_reset();
randLIB_seed_random();
uint16_t ret = randLIB_get_random_in_range(2, 2);
if( ret != 2 ){
return false;
}
ret = randLIB_get_random_in_range(2, 3);
if( ret != 2 && ret != 3){
return false;
}
ret = randLIB_get_random_in_range(0, 0xFFFF);
return true;
}
bool test_randLIB_randomise_base()
{
randLIB_reset();
randLIB_seed_random();
uint32_t ret = randLIB_randomise_base(0,0,0);
if( ret ){
return false;
}
ret = randLIB_randomise_base(0xffff0000,0x8888,0x8888);
if( ret != 0xffffffff ){
return false;
}
return true;
}

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2016 ARM. All rights reserved.
*/
#ifndef TEST_RANDLIB_H
#define TEST_RANDLIB_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
bool test_randLIB_seed_random();
bool test_randLIB_get_8bit();
bool test_randLIB_get_16bit();
bool test_randLIB_get_32bit();
bool test_randLIB_get_64bit();
bool test_randLIB_get_n_bytes_random();
bool test_randLIB_get_random_in_range();
bool test_randLIB_randomise_base();
#ifdef __cplusplus
}
#endif
#endif // TEST_RANDLIB_H

View File

@ -0,0 +1,43 @@
#!/bin/bash
echo
echo Build mbed client randlib unit tests
echo
# Remember to add new test folder to Makefile
make clean
make all
echo
echo Create results
echo
mkdir results
find ./ -name '*.xml' | xargs cp -t ./results/
echo
echo Create coverage document
echo
mkdir coverages
cd coverages
#copy the .gcda & .gcno for all test projects (no need to modify
#cp ../../../source/*.gc* .
#find ../ -name '*.gcda' | xargs cp -t .
#find ../ -name '*.gcno' | xargs cp -t .
#find . -name "test*" -type f -delete
#find . -name "*test*" -type f -delete
#find . -name "*stub*" -type f -delete
#rm -rf main.*
lcov -q -d ../. -c -o app.info
lcov -q -r app.info "/test*" -o app.info
lcov -q -r app.info "/usr*" -o app.info
genhtml --no-branch-coverage app.info
cd ..
echo
echo
echo
echo Have a nice bug hunt!
echo
echo
echo

View File

@ -0,0 +1,24 @@
#include <stdbool.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdarg.h>
bool allow_open = true;
int __real_open(const char *path, int flags, ...);
int __wrap_open(const char *path, int flags, ...)
{
if (allow_open) {
if (flags & O_CREAT) {
va_list vl;
va_start(vl,flags);
mode_t mode = va_arg(vl, mode_t);
va_end(vl);
return __real_open(path, flags, mode);
} else {
return __real_open(path, flags);
}
} else {
return -1;
}
}

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2016, ARM Limited, All Rights Reserved
*/
#include "random_stub.h"
static uint32_t seed_value = 4;
static bool seed_inc = false;
void arm_random_module_init(void)
{
}
uint32_t arm_random_seed_get(void)
{
uint32_t result = seed_value;
if (seed_inc) {
++seed_value;
}
return result;
}
void random_stub_set_seed(uint32_t value, bool increment)
{
seed_value = value;
seed_inc = increment;
}