diff options
Diffstat (limited to 'tinyusb/test/vendor/ceedling/plugins/fake_function_framework')
24 files changed, 1611 insertions, 0 deletions
diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/README.md b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/README.md new file mode 100755 index 00000000..8042775e --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/README.md @@ -0,0 +1,250 @@ +# A Fake Function Framework Plug-in for Ceedling + +This is a plug-in for [Ceedling](https://github.com/ThrowTheSwitch/Ceedling) to use the [Fake Function Framework](https://github.com/meekrosoft/fff) for mocking instead of CMock. + +Using fff provides less strict mocking than CMock, and allows for more loosely-coupled tests. +And, when tests fail -- since you get the actual line number of the failure -- it's a lot easier to figure out what went wrong. + +## Installing the plug-in + +To use the plugin you need to 1) get the contents of this repo and 2) configure your project to use it. + +### Get the source + +The easiest way to get the source is to just clone this repo into the Ceedling plugin folder for your existing Ceedling project. +(Don't have a Ceedling project already? [Here are instructions to create one.](http://www.electronvector.com/blog/try-embedded-test-driven-development-right-now-with-ceedling)) +From within `<your-project>/vendor/ceedling/plugins`, run: + +`git clone https://github.com/ElectronVector/fake_function_framework.git` + +This will create a new folder named `fake_function_framework` in the plugins folder. + +### Enable the plug-in. + +The plug-in is enabled from within your project.yml file. + +In the `:plugins` configuration, add `fake_function_framework` to the list of enabled plugins: + +```yaml +:plugins: + :load_paths: + - vendor/ceedling/plugins + :enabled: + - stdout_pretty_tests_report + - module_generator + - fake_function_framework +``` +*Note that you could put the plugin source in some other loaction. +In that case you'd need to add a new path the `:load_paths`.* + +## How to use it + +You use fff with Ceedling the same way you used to use CMock. +Modules can still be generated with the default module generator: `rake module:create[my_module]`. +If you want to "mock" `some_module.h` in your tests, just `#include "mock_some_module.h"`. +This creates a fake function for each of the functions defined in `some_module.h`. + +The name of each fake is the original function name with an appended `_fake`. +For example, if we're generating fakes for a stack module with `push` and `pop` functions, we would have the fakes `push_fake` and `pop_fake`. +These fakes are linked into our test executable so that any time our unit under test calls `push` or `pop` our fakes are called instead. + +Each of these fakes is actually a structure containing information about how the function was called, and what it might return. +We can use Unity to inspect these fakes in our tests, and verify the interactions of our units. +There is also a global structure named `fff` which we can use to check the sequence of calls. + +The fakes can also be configured to return particular values, so you can exercise the unit under test however you want. + +The examples below explain how to use fff to test a variety of module interactions. +Each example uses fakes for a "display" module, created from a display.h file with `#include "mock_display.h"`. The `display.h` file must exist and must contain the prototypes for the functions to be faked. + +### Test that a function was called once + +```c +void +test_whenTheDeviceIsReset_thenTheStatusLedIsTurnedOff() +{ + // When + event_deviceReset(); + + // Then + TEST_ASSERT_EQUAL(1, display_turnOffStatusLed_fake.call_count); +} +``` + +### Test that a function was NOT called + +```c +void +test_whenThePowerReadingIsLessThan5_thenTheStatusLedIsNotTurnedOn(void) +{ + // When + event_powerReadingUpdate(4); + + // Then + TEST_ASSERT_EQUAL(0, display_turnOnStatusLed_fake.call_count); +} +``` + +## Test that a single function was called with the correct argument + +```c +void +test_whenTheVolumeKnobIsMaxed_thenVolumeDisplayIsSetTo11(void) +{ + // When + event_volumeKnobMaxed(); + + // Then + TEST_ASSERT_EQUAL(1, display_setVolume_fake.call_count); + TEST_ASSERT_EQUAL(11, display_setVolume_fake.arg0_val); +} +``` + +## Test that calls are made in a particular sequence + +```c +void +test_whenTheModeSelectButtonIsPressed_thenTheDisplayModeIsCycled(void) +{ + // When + event_modeSelectButtonPressed(); + event_modeSelectButtonPressed(); + event_modeSelectButtonPressed(); + + // Then + TEST_ASSERT_EQUAL_PTR((void*)display_setModeToMinimum, fff.call_history[0]); + TEST_ASSERT_EQUAL_PTR((void*)display_setModeToMaximum, fff.call_history[1]); + TEST_ASSERT_EQUAL_PTR((void*)display_setModeToAverage, fff.call_history[2]); +} +``` + +## Fake a return value from a function + +```c +void +test_givenTheDisplayHasAnError_whenTheDeviceIsPoweredOn_thenTheDisplayIsPoweredDown(void) +{ + // Given + display_isError_fake.return_val = true; + + // When + event_devicePoweredOn(); + + // Then + TEST_ASSERT_EQUAL(1, display_powerDown_fake.call_count); +} +``` + +## Fake a function with a value returned by reference + +```c +void +test_givenTheUserHasTypedSleep_whenItIsTimeToCheckTheKeyboard_theDisplayIsPoweredDown(void) +{ + // Given + char mockedEntry[] = "sleep"; + void return_mock_value(char * entry, int length) + { + if (length > strlen(mockedEntry)) + { + strncpy(entry, mockedEntry, length); + } + } + display_getKeyboardEntry_fake.custom_fake = return_mock_value; + + // When + event_keyboardCheckTimerExpired(); + + // Then + TEST_ASSERT_EQUAL(1, display_powerDown_fake.call_count); +} +``` + +## Fake a function with a function pointer parameter + +``` +void +test_givenNewDataIsAvailable_whenTheDisplayHasUpdated_thenTheEventIsComplete(void) +{ + // A mock function for capturing the callback handler function pointer. + void(*registeredCallback)(void) = 0; + void mock_display_updateData(int data, void(*callback)(void)) + { + //Save the callback function. + registeredCallback = callback; + } + display_updateData_fake.custom_fake = mock_display_updateData; + + // Given + event_newDataAvailable(10); + + // When + if (registeredCallback != 0) + { + registeredCallback(); + } + + // Then + TEST_ASSERT_EQUAL(true, eventProcessor_isLastEventComplete()); +} +``` + +## Helper macros + +For convenience, there are also some helper macros that create new Unity-style asserts: + +- `TEST_ASSERT_CALLED(function)`: Asserts that a function was called once. +- `TEST_ASSERT_NOT_CALLED(function)`: Asserts that a function was never called. +- `TEST_ASSERT_CALLED_TIMES(times, function)`: Asserts that a function was called a particular number of times. +- `TEST_ASSERT_CALLED_IN_ORDER(order, function)`: Asserts that a function was called in a particular order. + +Here's how you might use one of these instead of simply checking the call_count value: + +```c +void +test_whenTheDeviceIsReset_thenTheStatusLedIsTurnedOff() +{ + // When + event_deviceReset(); + + // Then + // This how to directly use fff... + TEST_ASSERT_EQUAL(1, display_turnOffStatusLed_fake.call_count); + // ...and this is how to use the helper macro. + TEST_ASSERT_CALLED(display_turnOffStatusLed); +} +``` + +## Test setup + +All of the fake functions, and any fff global state are all reset automatically between each test. + +## CMock configuration + +Use still use some of the CMock configuration options for setting things like the mock prefix, and for including additional header files in the mock files. + +```yaml +:cmock: + :mock_prefix: mock_ + :includes: + - + :includes_h_pre_orig_header: + - + :includes_h_post_orig_header: + - + :includes_c_pre_header: + - + :includes_c_post_header: +``` + +## Running the tests + +There are unit and integration tests for the plug-in itself. +These are run with the default `rake` task. +The integration test runs the tests for the example project in examples/fff_example. +For the integration tests to succeed, this repository must be placed in a Ceedling tree in the plugins folder. + +## More examples + +There is an example project in examples/fff_example. +It shows how to use the plug-in with some full-size examples. diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/Rakefile b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/Rakefile new file mode 100755 index 00000000..bc559411 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/Rakefile @@ -0,0 +1,19 @@ +require 'rake' +require 'rspec/core/rake_task' + +desc "Run all rspecs" +RSpec::Core::RakeTask.new(:spec) do |t| + t.pattern = Dir.glob('spec/**/*_spec.rb') + t.rspec_opts = '--format documentation' + # t.rspec_opts << ' more options' +end + +desc "Run integration test on example" +task :integration_test do + chdir("./examples/fff_example") do + sh "rake clobber" + sh "rake test:all" + end +end + +task :default => [:spec, :integration_test]
\ No newline at end of file diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/project.yml b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/project.yml new file mode 100755 index 00000000..6bda2229 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/project.yml @@ -0,0 +1,71 @@ +--- + +# Notes: +# Sample project C code is not presently written to produce a release artifact. +# As such, release build options are disabled. +# This sample, therefore, only demonstrates running a collection of unit tests. + +:project: + :use_exceptions: FALSE + :use_test_preprocessor: TRUE + :use_auxiliary_dependencies: TRUE + :build_root: build +# :release_build: TRUE + :test_file_prefix: test_ + +#:release_build: +# :output: MyApp.out +# :use_assembly: FALSE + +:environment: + +:extension: + :executable: .out + +:paths: + :test: + - +:test/** + :source: + - src/** + :support: + +:defines: + # in order to add common defines: + # 1) remove the trailing [] from the :common: section + # 2) add entries to the :common: section (e.g. :test: has TEST defined) + :commmon: &common_defines [] + :test: + - *common_defines + - TEST + :test_preprocess: + - *common_defines + - TEST + +:cmock: + :mock_prefix: mock_ + :when_no_prototypes: :warn + :enforce_strict_ordering: TRUE + :plugins: + - :ignore + - :callback + :treat_as: + uint8: HEX8 + uint16: HEX16 + uint32: UINT32 + int8: INT8 + bool: UINT8 + +#:tools: +# Ceedling defaults to using gcc for compiling, linking, etc. +# As [:tools] is blank, gcc will be used (so long as it's in your system path) +# See documentation to configure a given toolchain for use + +:plugins: + :load_paths: + # This change from the default is for running Ceedling out of another folder. + - ../../../../plugins + :enabled: + - stdout_pretty_tests_report + - module_generator + - fake_function_framework +... diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/rakefile.rb b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/rakefile.rb new file mode 100755 index 00000000..e484d5fb --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/rakefile.rb @@ -0,0 +1,7 @@ +# This change from the default is for running Ceedling out of another folder. +PROJECT_CEEDLING_ROOT = "../../../.." +load "#{PROJECT_CEEDLING_ROOT}/lib/ceedling.rb" + +Ceedling.load_project + +task :default => %w[ test:all release ] diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/bar.c b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/bar.c new file mode 100755 index 00000000..6a403234 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/bar.c @@ -0,0 +1 @@ +#include "bar.h" diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/bar.h b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/bar.h new file mode 100755 index 00000000..febc5865 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/bar.h @@ -0,0 +1,14 @@ +#ifndef bar_H +#define bar_H + +#include "custom_types.h" + +void bar_turn_on(void); +void bar_print_message(const char * message); +void bar_print_message_formatted(const char * format, ...); +void bar_numbers(int one, int two, char three); +void bar_const_test(const char * a, char * const b, const int c); +custom_t bar_needs_custom_type(void); +const char * bar_return_const_ptr(int one); + +#endif // bar_H diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/custom_types.h b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/custom_types.h new file mode 100755 index 00000000..b426b32c --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/custom_types.h @@ -0,0 +1,6 @@ +#ifndef custom_types_H +#define custom_types_H + +typedef int custom_t; + +#endif diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/display.c b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/display.c new file mode 100755 index 00000000..2f03449b --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/display.c @@ -0,0 +1,7 @@ +#include <stdio.h> +#include "display.h" + +void display_turnOffStatusLed(void) +{ + printf("Display: Status LED off"); +}
\ No newline at end of file diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/display.h b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/display.h new file mode 100755 index 00000000..def29960 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/display.h @@ -0,0 +1,16 @@ +#include <stdbool.h> + +void display_turnOffStatusLed(void); +void display_turnOnStatusLed(void); +void display_setVolume(int level); +void display_setModeToMinimum(void); +void display_setModeToMaximum(void); +void display_setModeToAverage(void); +bool display_isError(void); +void display_powerDown(void); +void display_updateData(int data, void(*updateCompleteCallback)(void)); + +/* + The entry is returned (up to `length` bytes) in the provided `entry` buffer. +*/ +void display_getKeyboardEntry(char * entry, int length); diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/event_processor.c b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/event_processor.c new file mode 100755 index 00000000..916a9236 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/event_processor.c @@ -0,0 +1,93 @@ +/* + This module implements some business logic to test. + + Signal events by calling the functions on the module. +*/ + +#include <stdio.h> +#include <string.h> +#include "event_processor.h" +#include "display.h" + +void event_deviceReset(void) +{ + //printf ("Device reset\n"); + display_turnOffStatusLed(); +} + +void event_volumeKnobMaxed(void) +{ + display_setVolume(11); +} + +void event_powerReadingUpdate(int powerReading) +{ + if (powerReading >= 5) + { + display_turnOnStatusLed(); + } +} + +void event_modeSelectButtonPressed(void) +{ + static int mode = 0; + + if (mode == 0) + { + display_setModeToMinimum(); + mode++; + } + else if (mode == 1) + { + display_setModeToMaximum(); + mode++; + } + else if (mode == 2) + { + display_setModeToAverage(); + mode++; + } + else + { + mode = 0; + } +} + +void event_devicePoweredOn(void) +{ + if (display_isError()) + { + display_powerDown(); + } +} + +void event_keyboardCheckTimerExpired(void) +{ + char userEntry[100]; + + display_getKeyboardEntry(userEntry, 100); + + if (strcmp(userEntry, "sleep") == 0) + { + display_powerDown(); + } +} + +static bool event_lastComplete = false; + +/* Function called when the display update is complete. */ +static void displayUpdateComplete(void) +{ + event_lastComplete = true; +} + +void event_newDataAvailable(int data) +{ + event_lastComplete = false; + display_updateData(data, displayUpdateComplete); +} + +bool eventProcessor_isLastEventComplete(void) +{ + return event_lastComplete; +} diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/event_processor.h b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/event_processor.h new file mode 100755 index 00000000..a79e68c5 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/event_processor.h @@ -0,0 +1,11 @@ +#include <stdbool.h> + +void event_deviceReset(void); +void event_volumeKnobMaxed(void); +void event_powerReadingUpdate(int powerReading); +void event_modeSelectButtonPressed(void); +void event_devicePoweredOn(void); +void event_keyboardCheckTimerExpired(void); +void event_newDataAvailable(int data); + +bool eventProcessor_isLastEventComplete(void); diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/foo.c b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/foo.c new file mode 100755 index 00000000..c05b1154 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/foo.c @@ -0,0 +1,16 @@ +#include "foo.h" +#include "bar.h" +#include "subfolder/zzz.h" + +void foo_turn_on(void) { + bar_turn_on(); + zzz_sleep(1, "sleepy"); +} + +void foo_print_message(const char * message) { + bar_print_message(message); +} + +void foo_print_special_message(void) { + bar_print_message_formatted("The numbers are %d, %d and %d", 1, 2, 3); +} diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/foo.h b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/foo.h new file mode 100755 index 00000000..3fea6994 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/foo.h @@ -0,0 +1,8 @@ +#ifndef foo_H +#define foo_H + +void foo_turn_on(void); +void foo_print_message(const char * message); +void foo_print_special_message(void); + +#endif // foo_H diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/subfolder/zzz.c b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/subfolder/zzz.c new file mode 100755 index 00000000..85f370e1 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/subfolder/zzz.c @@ -0,0 +1 @@ +#include "zzz.h" diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/subfolder/zzz.h b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/subfolder/zzz.h new file mode 100755 index 00000000..32c52940 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/src/subfolder/zzz.h @@ -0,0 +1,6 @@ +#ifndef zzz_H +#define zzz_H + +int zzz_sleep(int time, char * name); + +#endif // zzz_H diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/test/test_event_processor.c b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/test/test_event_processor.c new file mode 100755 index 00000000..9f999443 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/test/test_event_processor.c @@ -0,0 +1,155 @@ +#include "unity.h" +#include "event_processor.h" +#include "mock_display.h" +#include <string.h> + +void setUp (void) +{ +} + +void tearDown (void) +{ +} +/* + Test that a single function was called. +*/ +void +test_whenTheDeviceIsReset_thenTheStatusLedIsTurnedOff() +{ + // When + event_deviceReset(); + + // Then + TEST_ASSERT_EQUAL(1, display_turnOffStatusLed_fake.call_count); + // or use the helper macro... + TEST_ASSERT_CALLED(display_turnOffStatusLed); +} + +/* + Test that a single function is NOT called. +*/ +void +test_whenThePowerReadingIsLessThan5_thenTheStatusLedIsNotTurnedOn(void) +{ + // When + event_powerReadingUpdate(4); + + // Then + TEST_ASSERT_EQUAL(0, display_turnOnStatusLed_fake.call_count); + // or use the helper macro... + TEST_ASSERT_NOT_CALLED(display_turnOffStatusLed); +} + +/* + Test that a single function was called with the correct arugment. +*/ +void +test_whenTheVolumeKnobIsMaxed_thenVolumeDisplayIsSetTo11(void) +{ + // When + event_volumeKnobMaxed(); + + // Then + TEST_ASSERT_EQUAL(1, display_setVolume_fake.call_count); + // or use the helper macro... + TEST_ASSERT_CALLED(display_setVolume); + TEST_ASSERT_EQUAL(11, display_setVolume_fake.arg0_val); +} + +/* + Test a sequence of calls. +*/ + +void +test_whenTheModeSelectButtonIsPressed_thenTheDisplayModeIsCycled(void) +{ + // When + event_modeSelectButtonPressed(); + event_modeSelectButtonPressed(); + event_modeSelectButtonPressed(); + + // Then + TEST_ASSERT_EQUAL_PTR((void *)display_setModeToMinimum, fff.call_history[0]); + TEST_ASSERT_EQUAL_PTR((void *)display_setModeToMaximum, fff.call_history[1]); + TEST_ASSERT_EQUAL_PTR((void *)display_setModeToAverage, fff.call_history[2]); + // or use the helper macros... + TEST_ASSERT_CALLED_IN_ORDER(0, display_setModeToMinimum); + TEST_ASSERT_CALLED_IN_ORDER(1, display_setModeToMaximum); + TEST_ASSERT_CALLED_IN_ORDER(2, display_setModeToAverage); +} + +/* + Mock a return value from a function. +*/ +void +test_givenTheDisplayHasAnError_whenTheDeviceIsPoweredOn_thenTheDisplayIsPoweredDown(void) +{ + // Given + display_isError_fake.return_val = true; + + // When + event_devicePoweredOn(); + + // Then + TEST_ASSERT_EQUAL(1, display_powerDown_fake.call_count); + // or use the helper macro... + TEST_ASSERT_CALLED(display_powerDown); +} + +/* + Mock a sequence of calls with return values. +*/ + +/* + Mocking a function with a value returned by reference. +*/ +void +test_givenTheUserHasTypedSleep_whenItIsTimeToCheckTheKeyboard_theDisplayIsPoweredDown(void) +{ + // Given + char mockedEntry[] = "sleep"; + void return_mock_value(char * entry, int length) + { + if (length > strlen(mockedEntry)) + { + strncpy(entry, mockedEntry, length); + } + } + display_getKeyboardEntry_fake.custom_fake = return_mock_value; + + // When + event_keyboardCheckTimerExpired(); + + // Then + TEST_ASSERT_EQUAL(1, display_powerDown_fake.call_count); + // or use the helper macro... + TEST_ASSERT_CALLED(display_powerDown); +} + +/* + Mock a function with a function pointer parameter. +*/ +void +test_givenNewDataIsAvailable_whenTheDisplayHasUpdated_thenTheEventIsComplete(void) +{ + // A mock function for capturing the callback handler function pointer. + void(*registeredCallback)(void) = 0; + void mock_display_updateData(int data, void(*callback)(void)) + { + //Save the callback function. + registeredCallback = callback; + } + display_updateData_fake.custom_fake = mock_display_updateData; + + // Given + event_newDataAvailable(10); + + // When + if (registeredCallback != 0) + { + registeredCallback(); + } + + // Then + TEST_ASSERT_EQUAL(true, eventProcessor_isLastEventComplete()); +} diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/test/test_foo.c b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/test/test_foo.c new file mode 100755 index 00000000..12dd61a1 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/examples/fff_example/test/test_foo.c @@ -0,0 +1,47 @@ +#include "unity.h" +#include "foo.h" +#include "mock_bar.h" +#include "mock_zzz.h" + +void setUp(void) +{ +} + +void tearDown(void) +{ +} + +void test_foo(void) +{ + //When + foo_turn_on(); + + //Then + TEST_ASSERT_EQUAL(1, bar_turn_on_fake.call_count); + TEST_ASSERT_EQUAL(1, zzz_sleep_fake.call_count); + TEST_ASSERT_EQUAL_STRING("sleepy", zzz_sleep_fake.arg1_val); +} + +void test_foo_again(void) +{ + //When + foo_turn_on(); + + //Then + TEST_ASSERT_EQUAL(1, bar_turn_on_fake.call_count); +} + +void test_foo_mock_with_const(void) +{ + foo_print_message("123"); + + TEST_ASSERT_EQUAL(1, bar_print_message_fake.call_count); + TEST_ASSERT_EQUAL_STRING("123", bar_print_message_fake.arg0_val); +} + +void test_foo_mock_with_variable_args(void) +{ + foo_print_special_message(); + TEST_ASSERT_EQUAL(1, bar_print_message_formatted_fake.call_count); + TEST_ASSERT_EQUAL_STRING("The numbers are %d, %d and %d", bar_print_message_formatted_fake.arg0_val); +} diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/lib/fake_function_framework.rb b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/lib/fake_function_framework.rb new file mode 100755 index 00000000..51a90b3a --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/lib/fake_function_framework.rb @@ -0,0 +1,87 @@ +require 'ceedling/plugin' +require 'fff_mock_generator' + +class FakeFunctionFramework < Plugin + + # Set up Ceedling to use this plugin. + def setup + # Get the location of this plugin. + @plugin_root = File.expand_path(File.join(File.dirname(__FILE__), '..')) + puts "Using fake function framework (fff)..." + + # Switch out the cmock_builder with our own. + @ceedling[:cmock_builder].cmock = FffMockGeneratorForCMock.new(@ceedling[:setupinator].config_hash[:cmock]) + + # Add the path to fff.h to the include paths. + COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR << "#{@plugin_root}/vendor/fff" + COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR << "#{@plugin_root}/src" + end + + def post_runner_generate(arg_hash) + # After the test runner file has been created, append the FFF globals + # definition to the end of the test runner. These globals will be shared by + # all mocks linked into the test. + File.open(arg_hash[:runner_file], 'a') do |f| + f.puts + f.puts "//=======Defintions of FFF variables=====" + f.puts %{#include "fff.h"} + f.puts "DEFINE_FFF_GLOBALS;" + end + end + +end # class FakeFunctionFramework + +class FffMockGeneratorForCMock + + def initialize(options=nil) + @cm_config = CMockConfig.new(options) + @cm_parser = CMockHeaderParser.new(@cm_config) + @silent = (@cm_config.verbosity < 2) + + # These are the additional files to include in the mock files. + @includes_h_pre_orig_header = (@cm_config.includes || @cm_config.includes_h_pre_orig_header || []).map{|h| h =~ /</ ? h : "\"#{h}\""} + @includes_h_post_orig_header = (@cm_config.includes_h_post_orig_header || []).map{|h| h =~ /</ ? h : "\"#{h}\""} + @includes_c_pre_header = (@cm_config.includes_c_pre_header || []).map{|h| h =~ /</ ? h : "\"#{h}\""} + @includes_c_post_header = (@cm_config.includes_c_post_header || []).map{|h| h =~ /</ ? h : "\"#{h}\""} + end + + def setup_mocks(files) + [files].flatten.each do |src| + generate_mock (src) + end + end + + def generate_mock (header_file_to_mock) + module_name = File.basename(header_file_to_mock, '.h') + puts "Creating mock for #{module_name}..." unless @silent + mock_name = @cm_config.mock_prefix + module_name + @cm_config.mock_suffix + mock_path = @cm_config.mock_path + if @cm_config.subdir + # If a subdirectory has been configured, append it to the mock path. + mock_path = "#{mock_path}/#{@cm_config.subdir}" + end + full_path_for_mock = "#{mock_path}/#{mock_name}" + + # Parse the header file so we know what to mock. + parsed_header = @cm_parser.parse(module_name, File.read(header_file_to_mock)) + + # Create the directory if it doesn't exist. + mkdir_p full_path_for_mock.pathmap("%d") + + # Generate the mock header file. + puts "Creating mock: #{full_path_for_mock}.h" + + # Create the mock header. + File.open("#{full_path_for_mock}.h", 'w') do |f| + f.write(FffMockGenerator.create_mock_header(module_name, mock_name, parsed_header, + @includes_h_pre_orig_header, @includes_h_post_orig_header)) + end + + # Create the mock source file. + File.open("#{full_path_for_mock}.c", 'w') do |f| + f.write(FffMockGenerator.create_mock_source(mock_name, parsed_header, + @includes_c_pre_orig_header, @includes_c_post_orig_header)) + end + end + +end diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/lib/fff_mock_generator.rb b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/lib/fff_mock_generator.rb new file mode 100755 index 00000000..9dc03a65 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/lib/fff_mock_generator.rb @@ -0,0 +1,163 @@ +# Creates mock files from parsed header files that can be linked into applications. +# The mocks created are compatible with CMock for use with Ceedling. + +class FffMockGenerator + + def self.create_mock_header(module_name, mock_name, parsed_header, pre_includes=nil, + post_includes=nil) + output = StringIO.new + write_opening_include_guard(mock_name, output) + output.puts + write_extra_includes(pre_includes, output) + write_header_includes(module_name, output) + write_extra_includes(post_includes, output) + output.puts + write_typedefs(parsed_header, output) + output.puts + write_function_declarations(parsed_header, output) + output.puts + write_control_function_prototypes(mock_name, output) + output.puts + write_closing_include_guard(mock_name, output) + output.string + end + + def self.create_mock_source (mock_name, parsed_header, pre_includes=nil, + post_includes=nil) + output = StringIO.new + write_extra_includes(pre_includes, output) + write_source_includes(mock_name, output) + write_extra_includes(post_includes, output) + output.puts + write_function_definitions(parsed_header, output) + output.puts + write_control_function_definitions(mock_name, parsed_header, output) + output.string + end + + private + +# Header file generation functions. + + def self.write_opening_include_guard(mock_name, output) + output.puts "#ifndef #{mock_name}_H" + output.puts "#define #{mock_name}_H" + end + + def self.write_header_includes(module_name, output) + output.puts %{#include "fff.h"} + output.puts %{#include "fff_unity_helper.h"} + output.puts %{#include "#{module_name}.h"} + end + + def self.write_typedefs(parsed_header, output) + return unless parsed_header.key?(:typedefs) + parsed_header[:typedefs].each do |typedef| + output.puts typedef + end + end + + def self.write_function_declarations(parsed_header, output) + write_function_macros("DECLARE", parsed_header, output) + end + + + def self.write_control_function_prototypes(mock_name, output) + output.puts "void #{mock_name}_Init(void);" + output.puts "void #{mock_name}_Verify(void);" + output.puts "void #{mock_name}_Destroy(void);" + end + + def self.write_closing_include_guard(mock_name, output) + output.puts "#endif // #{mock_name}_H" + end + +# Source file generation functions. + + def self.write_source_includes (mock_name, output) + output.puts "#include <string.h>" + output.puts %{#include "fff.h"} + output.puts %{#include "#{mock_name}.h"} + end + + def self.write_function_definitions(parsed_header, output) + write_function_macros("DEFINE", parsed_header, output) + end + + def self.write_control_function_definitions(mock_name, parsed_header, output) + output.puts "void #{mock_name}_Init(void)" + output.puts "{" + # In the init function, reset the FFF globals. These are used for things + # like the call history. + output.puts " FFF_RESET_HISTORY();" + + # Also, reset all of the fakes. + if parsed_header[:functions] + parsed_header[:functions].each do |function| + output.puts " RESET_FAKE(#{function[:name]})" + end + end + output.puts "}" + output.puts "void #{mock_name}_Verify(void)" + output.puts "{" + output.puts "}" + output.puts "void #{mock_name}_Destroy(void)" + output.puts "{" + output.puts "}" + end + +# Shared functions. + + def self.write_extra_includes(includes, output) + if includes + includes.each {|inc| output.puts "#include #{inc}\n"} + end + end + + def self.write_function_macros(macro_type, parsed_header, output) + return unless parsed_header.key?(:functions) + parsed_header[:functions].each do |function| + name = function[:name] + return_type = function[:return][:type] + if function.has_key? :modifier + # Prepend any modifier. If there isn't one, trim any leading whitespace. + return_type = "#{function[:modifier]} #{return_type}".lstrip + end + arg_count = function[:args].size + + # Check for variable arguments. + var_arg_suffix = "" + if function[:var_arg] + # If there are are variable arguments, then we need to add this argument + # to the count, update the suffix that will get added to the macro. + arg_count += 1 + var_arg_suffix = "_VARARG" + end + + # Generate the correct macro. + if return_type == 'void' + output.print "#{macro_type}_FAKE_VOID_FUNC#{arg_count}#{var_arg_suffix}(#{name}" + else + output.print "#{macro_type}_FAKE_VALUE_FUNC#{arg_count}#{var_arg_suffix}(#{return_type}, #{name}" + end + + # Append each argument type. + function[:args].each do |arg| + output.print ", " + if arg[:const?] + output.print "const " + end + output.print "#{arg[:type]}" + end + + # If this argument list ends with a variable argument, add it here at the end. + if function[:var_arg] + output.print ", ..." + end + + # Close the declaration. + output.puts ");" + end + end + +end diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/fff_mock_header_generator_spec.rb b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/fff_mock_header_generator_spec.rb new file mode 100755 index 00000000..e6ac11dd --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/fff_mock_header_generator_spec.rb @@ -0,0 +1,304 @@ +require 'stringio' +require 'fff_mock_generator.rb' +require 'header_generator.rb' + +# Test the contents of the .h file created for the mock. +describe "FffMockGenerator.create_mock_header" do + + context "when there is nothing to mock," do + let(:mock_header) { + parsed_header = {} + FffMockGenerator.create_mock_header("display", "mock_display", parsed_header) + } + it "then the generated header file starts with an opening include guard" do + expect(mock_header).to start_with( + "#ifndef mock_display_H\n" + + "#define mock_display_H") + end + it "then the generated file ends with a closing include guard" do + expect(mock_header).to end_with( + "#endif // mock_display_H\n") + end + it "then the generated file includes the fff header" do + expect(mock_header).to include( + %{#include "fff.h"\n}) + end + it "then the generated file has a prototype for the init function" do + expect(mock_header).to include( + "void mock_display_Init(void);") + end + it "then the generated file has a prototype for the verify function" do + expect(mock_header).to include( + "void mock_display_Verify(void);") + end + it "then the generated file has a prototype for the destroy function" do + expect(mock_header).to include( + "void mock_display_Destroy(void);") + end + end + + context "when there is a function with no args and a void return," do + let(:mock_header) { + parsed_header = create_cmock_style_parsed_header( + [{:name => 'display_turnOffStatusLed', :return_type => 'void'}]) + FffMockGenerator.create_mock_header("display", "mock_display", parsed_header) + } + it "then the generated header file starts with an opening include guard" do + expect(mock_header).to start_with( + "#ifndef mock_display_H\n" + + "#define mock_display_H") + end + it "then the generated header file contains a fake function declaration" do + expect(mock_header).to include( + "DECLARE_FAKE_VOID_FUNC0(display_turnOffStatusLed);" + ) + end + it "then the generated file ends with a closing include guard" do + expect(mock_header).to end_with( + "#endif // mock_display_H\n") + end + end + + context "when there is a function with no args and a bool return," do + let(:mock_header) { + parsed_header = create_cmock_style_parsed_header( + [{:name => 'display_isError', :return_type => 'bool'}]) + FffMockGenerator.create_mock_header("display", "mock_display", parsed_header) + } + it "then the generated file contains the fake function declaration" do + expect(mock_header).to include( + "DECLARE_FAKE_VALUE_FUNC0(bool, display_isError);" + ) + end + end + + context "when there is a function with no args and an int return," do + let(:mock_header) { + parsed_header = create_cmock_style_parsed_header( + [{:name => 'display_isError', :return_type => 'int'}]) + FffMockGenerator.create_mock_header("display", "mock_display", parsed_header) + } + it "then the generated file contains the fake function declaration" do + expect(mock_header).to include( + "DECLARE_FAKE_VALUE_FUNC0(int, display_isError);" + ) + end + end + + context "when there is a function with args and a void return," do + let(:mock_header) { + parsed_header = create_cmock_style_parsed_header( + [{:name => 'display_setVolume', :return_type => 'void', :args => ['int']}]) + FffMockGenerator.create_mock_header("display", "mock_display", parsed_header) + } + it "then the generated file contains the fake function declaration" do + expect(mock_header).to include( + "DECLARE_FAKE_VOID_FUNC1(display_setVolume, int);" + ) + end + end + + context "when there is a function with args and a value return," do + let(:mock_header) { + parsed_header = create_cmock_style_parsed_header( + [{:name => 'a_function', :return_type => 'int', :args => ['char *']}]) + FffMockGenerator.create_mock_header("display", "mock_display", parsed_header) + } + it "then the generated file contains the fake function declaration" do + expect(mock_header).to include( + "FAKE_VALUE_FUNC1(int, a_function, char *);" + ) + end + end + + context "when there is a function with many args and a void return," do + let(:mock_header) { + parsed_header = create_cmock_style_parsed_header( + [{:name => 'a_function', :return_type => 'void', + :args => ['int', 'char *', 'int', 'int', 'bool', 'applesauce']}]) + FffMockGenerator.create_mock_header("display", "mock_display", parsed_header) + } + it "then the generated file contains the fake function declaration" do + expect(mock_header).to include( + "DECLARE_FAKE_VOID_FUNC6(a_function, int, char *, int, int, bool, applesauce);" + ) + end + end + + context "when there are multiple functions," do + let(:mock_header) { + parsed_header = create_cmock_style_parsed_header( + [ {:name => 'a_function', :return_type => 'int', :args => ['char *']}, + {:name => 'another_function', :return_type => 'void'}, + {:name => 'three', :return_type => 'bool', :args => ['float', 'int']} + ]) + FffMockGenerator.create_mock_header("display", "mock_display", parsed_header) + } + it "then the generated file contains the first fake function declaration" do + expect(mock_header).to include( + "DECLARE_FAKE_VALUE_FUNC1(int, a_function, char *);" + ) + end + it "then the generated file contains the second fake function declaration" do + expect(mock_header).to include( + "DECLARE_FAKE_VOID_FUNC0(another_function);" + ) + end + it "then the generated file contains the third fake function declaration" do + expect(mock_header).to include( + "DECLARE_FAKE_VALUE_FUNC2(bool, three, float, int);" + ) + end + end + + context "when there is a typedef," do + let(:mock_header) { + parsed_header = create_cmock_style_parsed_header( + nil, ["typedef void (*displayCompleteCallback) (void);"]) + FffMockGenerator.create_mock_header("display", "mock_display", parsed_header) + } + it "then the generated file contains the typedef" do + expect(mock_header).to include( + "typedef void (*displayCompleteCallback) (void);" + ) + end + end + + context "when there is a void function with variable arguments" do + let(:mock_header){ + parsed_header = {} + parsed_header[:functions] = [{ + :name => "function_with_var_args", + :return => {:type => "void"}, + :var_arg => "...", + :args => [{:type => 'char *'}] + }] + FffMockGenerator.create_mock_header("display", "mock_display", parsed_header) + } + it "then the generated file contains the vararg declaration" do + expect(mock_header).to include( + "DECLARE_FAKE_VOID_FUNC2_VARARG(function_with_var_args, char *, ...)" + ) + end + end + + context "when there is a function with a return value and variable arguments" do + let(:mock_header){ + parsed_header = {} + parsed_header[:functions] = [{ + :name => "function_with_var_args", + :return => {:type => "int"}, + :var_arg => "...", + :args => [{:type => 'char *'}] + }] + FffMockGenerator.create_mock_header("display", "mock_display", parsed_header) + } + it "then the generated file contains the vararg declaration" do + expect(mock_header).to include( + "DECLARE_FAKE_VALUE_FUNC2_VARARG(int, function_with_var_args, char *, ...)" + ) + end + end + + context "when there is a void function with variable arguments and " + + "additional arguments" do + let(:mock_header){ + parsed_header = {} + parsed_header[:functions] = [{ + :name => "function_with_var_args", + :return => {:type => "void"}, + :var_arg => "...", + :args => [{:type => 'char *'}, {:type => 'int'}] + }] + FffMockGenerator.create_mock_header("display", "mock_display", parsed_header) + } + it "then the generated file contains the vararg declaration" do + expect(mock_header).to include( + "DECLARE_FAKE_VOID_FUNC3_VARARG(function_with_var_args, char *, int, ...)" + ) + end + end + + context "when there is a function with a pointer to a const value" do + let(:mock_header){ + parsed_header = {} + parsed_header[:functions] = [{ + :name => "const_test_function", + :return => {:type => "void"}, + :args => [{:type => "char *", :name => "a", :ptr? => false, :const? => true}, + {:type => "char *", :name => "b", :ptr? => false, :const? => false}] + }] + FffMockGenerator.create_mock_header("display", "mock_display", parsed_header) + } + it "then the generated file contains the correct const argument in the declaration" do + expect(mock_header).to include( + "DECLARE_FAKE_VOID_FUNC2(const_test_function, const char *, char *)" + ) + end + end + + context "when there is a function that returns a const pointer" do + let(:mock_header){ + parsed_header = {} + parsed_header[:functions] = [{ + :name => "return_const_pointer_test_function", + :modifier => "const", + :return => {:type => "char *" }, + :args => [{:type => "int", :name => "a"}] + }] + FffMockGenerator.create_mock_header("display", "mock_display", parsed_header) + } + it "then the generated file contains the correct const return value in the declaration" do + expect(mock_header).to include( + "DECLARE_FAKE_VALUE_FUNC1(const char *, return_const_pointer_test_function, int)" + ) + end + end + + context "when there is a function that returns a const int" do + let(:mock_header){ + parsed_header = {} + parsed_header[:functions] = [{ + :name => "return_const_int_test_function", + :modifier => "const", + :return => {:type => "int" }, + :args => [] + }] + FffMockGenerator.create_mock_header("display", "mock_display", parsed_header) + } + it "then the generated file contains the correct const return value in the declaration" do + expect(mock_header).to include( + "DECLARE_FAKE_VALUE_FUNC0(const int, return_const_int_test_function)" + ) + end + end + + context "when there are pre-includes" do + let(:mock_header) { + parsed_header = {} + FffMockGenerator.create_mock_header("display", "mock_display", parsed_header, + [%{"another_header.h"}]) + } + it "then they are included before the other files" do + expect(mock_header).to include( + %{#include "another_header.h"\n} + + %{#include "fff.h"} + ) + end + end + + context "when there are post-includes" do + let(:mock_header) { + parsed_header = {} + FffMockGenerator.create_mock_header("display", "mock_display", parsed_header, + nil, [%{"another_header.h"}]) + } + it "then they are included after the other files" do + expect(mock_header).to include( + %{#include "display.h"\n} + + %{#include "another_header.h"\n} + ) + end + end + +end diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/fff_mock_source_generator_spec.rb b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/fff_mock_source_generator_spec.rb new file mode 100755 index 00000000..364f8521 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/fff_mock_source_generator_spec.rb @@ -0,0 +1,149 @@ +require 'stringio' +require 'fff_mock_generator.rb' + +# Test the contents of the .c file created for the mock. +describe "FffMockGenerator.create_mock_source" do + + context "when there is nothing to mock," do + let(:mock_source) { + parsed_header = {} + FffMockGenerator.create_mock_source("mock_my_module", parsed_header) + } + it "then the generated file includes the fff header" do + expect(mock_source).to include( + # fff.h also requires including string.h + %{#include <string.h>\n} + + %{#include "fff.h"} + ) + end + it "then the generated file includes the mock header" do + expect(mock_source).to include( + %{#include "mock_my_module.h"\n} + ) + end + it "then the generated file defines the init function" do + expect(mock_source).to include( + "void mock_my_module_Init(void)\n" + + "{\n" + + " FFF_RESET_HISTORY();\n" + + "}" + ) + end + it "then the generated file defines the verify function" do + expect(mock_source).to include( + "void mock_my_module_Verify(void)\n" + + "{\n" + + "}" + ) + end + it "then the generated file defines the destroy function" do + expect(mock_source).to include( + "void mock_my_module_Destroy(void)\n" + + "{\n" + + "}" + ) + end + end + + context "when there are multiple functions," do + let(:mock_source) { + parsed_header = create_cmock_style_parsed_header( + [ {:name => 'a_function', :return_type => 'int', :args => ['char *']}, + {:name => 'another_function', :return_type => 'void'}, + {:name => 'three', :return_type => 'bool', :args => ['float', 'int']} + ]) + FffMockGenerator.create_mock_source("mock_display", parsed_header) + } + it "then the generated file contains the first fake function definition" do + expect(mock_source).to include( + "DEFINE_FAKE_VALUE_FUNC1(int, a_function, char *);" + ) + end + it "then the generated file contains the second fake function definition" do + expect(mock_source).to include( + "DEFINE_FAKE_VOID_FUNC0(another_function);" + ) + end + it "then the generated file contains the third fake function definition" do + expect(mock_source).to include( + "DEFINE_FAKE_VALUE_FUNC2(bool, three, float, int);" + ) + end + it "then the init function resets all of the fakes" do + expect(mock_source).to include( + "void mock_display_Init(void)\n" + + "{\n" + + " FFF_RESET_HISTORY();\n" + + " RESET_FAKE(a_function)\n" + + " RESET_FAKE(another_function)\n" + + " RESET_FAKE(three)\n" + + "}" + ) + end + end + + context "when there is a void function with variable arguments and " + + "additional arguments" do + let(:mock_source){ + parsed_header = {} + parsed_header[:functions] = [{ + :name => "function_with_var_args", + :return => {:type => "void"}, + :var_arg => "...", + :args => [{:type => 'char *'}, {:type => 'int'}] + }] + FffMockGenerator.create_mock_source("mock_display", parsed_header) + } + it "then the generated file contains the vararg definition" do + expect(mock_source).to include( + "DEFINE_FAKE_VOID_FUNC3_VARARG(function_with_var_args, char *, int, ...)" + ) + end + end + + context "when there is a function with a pointer to a const value" do + let(:mock_source){ + parsed_header = {} + parsed_header[:functions] = [{ + :name => "const_test_function", + :return => {:type => "void"}, + :args => [{:type => "char *", :name => "a", :ptr? => false, :const? => true}, + {:type => "char *", :name => "b", :ptr? => false, :const? => false}] + }] + FffMockGenerator.create_mock_source("mock_display", parsed_header) + } + it "then the generated file contains the correct const argument in the declaration" do + expect(mock_source).to include( + "DEFINE_FAKE_VOID_FUNC2(const_test_function, const char *, char *)" + ) + end + end + + context "when there are pre-includes" do + let(:mock_source) { + parsed_source = {} + FffMockGenerator.create_mock_source("mock_display", parsed_source, + [%{"another_header.h"}]) + } + it "then they are included before the other files" do + expect(mock_source).to include( + %{#include "another_header.h"\n} + + %{#include <string.h>} + ) + end + end + + context "when there are post-includes" do + let(:mock_source) { + parsed_source = {} + FffMockGenerator.create_mock_source("mock_display", parsed_source, + nil, [%{"another_header.h"}]) + } + it "then they are included before the other files" do + expect(mock_source).to include( + %{#include "mock_display.h"\n} + + %{#include "another_header.h"\n} + ) + end + end +end
\ No newline at end of file diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/header_generator.rb b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/header_generator.rb new file mode 100755 index 00000000..cda27844 --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/header_generator.rb @@ -0,0 +1,51 @@ +# Create a CMock-style parsed header hash. This the type of hash created by +# CMock when parsing header files for automock generation. It contains all of +# includes, typedefs and functions (with return types and arguments) parsed from +# the header file. +def create_cmock_style_parsed_header(functions, typedefs = nil) + parsed_header = { + :includes => nil, + :functions => [], + :typedefs => [] + } + + # Add the typedefs. + if typedefs + typedefs.each do |typedef| + parsed_header[:typedefs] << typedef + end + end + + # Add the functions. + if functions + functions.each do |function| + # Build the array of arguments. + args = [] + if function.key?(:args) + function[:args].each do |arg| + args << { + :type => arg + } + end + end + parsed_header[:functions] << { + :name => function[:name], + :modifier => "", + :return => { + :type => function[:return_type], + :name => "cmock_to_return", + :ptr? => false, + :const? => false, + :str => "void cmock_to_return", + :void? => true + }, + :var_arg => nil, + :args_string => "void", + :args => args, + :args_call => "", + :contains_ptr? => false + } + end + end + parsed_header +end
\ No newline at end of file diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/spec_helper.rb b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/spec_helper.rb new file mode 100755 index 00000000..25dc80ac --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/spec/spec_helper.rb @@ -0,0 +1,96 @@ +# This file was generated by the `rspec --init` command. Conventionally, all +# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. +# The generated `.rspec` file contains `--require spec_helper` which will cause +# this file to always be loaded, without a need to explicitly require it in any +# files. +# +# Given that it is always loaded, you are encouraged to keep this file as +# light-weight as possible. Requiring heavyweight dependencies from this file +# will add to the boot time of your test suite on EVERY test run, even for an +# individual file that may not need all of that loaded. Instead, consider making +# a separate helper file that requires the additional dependencies and performs +# the additional setup, and require it from the spec files that actually need +# it. +# +# The `.rspec` file also contains a few flags that are not defaults but that +# users commonly want. +# +# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration +RSpec.configure do |config| + # rspec-expectations config goes here. You can use an alternate + # assertion/expectation library such as wrong or the stdlib/minitest + # assertions if you prefer. + config.expect_with :rspec do |expectations| + # This option will default to `true` in RSpec 4. It makes the `description` + # and `failure_message` of custom matchers include text for helper methods + # defined using `chain`, e.g.: + # be_bigger_than(2).and_smaller_than(4).description + # # => "be bigger than 2 and smaller than 4" + # ...rather than: + # # => "be bigger than 2" + expectations.include_chain_clauses_in_custom_matcher_descriptions = true + end + + # rspec-mocks config goes here. You can use an alternate test double + # library (such as bogus or mocha) by changing the `mock_with` option here. + config.mock_with :rspec do |mocks| + # Prevents you from mocking or stubbing a method that does not exist on + # a real object. This is generally recommended, and will default to + # `true` in RSpec 4. + mocks.verify_partial_doubles = true + end + +# The settings below are suggested to provide a good initial experience +# with RSpec, but feel free to customize to your heart's content. +=begin + # These two settings work together to allow you to limit a spec run + # to individual examples or groups you care about by tagging them with + # `:focus` metadata. When nothing is tagged with `:focus`, all examples + # get run. + config.filter_run :focus + config.run_all_when_everything_filtered = true + + # Allows RSpec to persist some state between runs in order to support + # the `--only-failures` and `--next-failure` CLI options. We recommend + # you configure your source control system to ignore this file. + config.example_status_persistence_file_path = "spec/examples.txt" + + # Limits the available syntax to the non-monkey patched syntax that is + # recommended. For more details, see: + # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/ + # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ + # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode + config.disable_monkey_patching! + + # This setting enables warnings. It's recommended, but in some cases may + # be too noisy due to issues in dependencies. + config.warnings = true + + # Many RSpec users commonly either run the entire suite or an individual + # file, and it's useful to allow more verbose output when running an + # individual spec file. + if config.files_to_run.one? + # Use the documentation formatter for detailed output, + # unless a formatter has already been configured + # (e.g. via a command-line flag). + config.default_formatter = 'doc' + end + + # Print the 10 slowest examples and example groups at the + # end of the spec run, to help surface which specs are running + # particularly slow. + config.profile_examples = 10 + + # Run specs in random order to surface order dependencies. If you find an + # order dependency and want to debug it, you can fix the order by providing + # the seed, which is printed after each run. + # --seed 1234 + config.order = :random + + # Seed global randomization in this process using the `--seed` CLI option. + # Setting this allows you to use `--seed` to deterministically reproduce + # test failures related to randomization by passing the same `--seed` value + # as the one that triggered the failure. + Kernel.srand config.seed +=end +end diff --git a/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/src/fff_unity_helper.h b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/src/fff_unity_helper.h new file mode 100755 index 00000000..de3db44a --- /dev/null +++ b/tinyusb/test/vendor/ceedling/plugins/fake_function_framework/src/fff_unity_helper.h @@ -0,0 +1,33 @@ +#ifndef fff_unity_helper_H +#define fff_unity_helper_H + +/* + FFF helper macros for Unity. +*/ + +/* + Fail if the function was not called the expected number of times. +*/ +#define TEST_ASSERT_CALLED_TIMES(times_, function_) \ + TEST_ASSERT_EQUAL_MESSAGE(times_, \ + function_ ## _fake.call_count, \ + "Function " #function_ " called the incorrect number of times.") +/* + Fail if the function was not called exactly once. +*/ +#define TEST_ASSERT_CALLED(function_) TEST_ASSERT_CALLED_TIMES(1, function_) + +/* + Fail if the function was called 1 or more times. +*/ +#define TEST_ASSERT_NOT_CALLED(function_) TEST_ASSERT_CALLED_TIMES(0, function_) + +/* + Fail if the function was not called in this particular order. +*/ +#define TEST_ASSERT_CALLED_IN_ORDER(order_, function_) \ + TEST_ASSERT_EQUAL_PTR_MESSAGE((void *) function_, \ + fff.call_history[order_], \ + "Function " #function_ " not called in order " #order_ ) + +#endif
\ No newline at end of file |