C/C++ Samples
Introduction
The samples are provided with with the Desktop installation package. They are self-documented (using doxygen formatting) and this content will be attached to the test report whenever a sample is executed. They are readily executable using our off-target (desktop) environment and can easily be built and executed. In every case, you can include a sample(s) simply by copying its source files to the SDK's sample_src directory and rebuilding the testapp.
The samples were created to be as simple as possible while sufficiently demonstrating the topic at hand. In particular, the samples are very light on core application logic (that is, the source under test) -- they focus instead on the code that leverages STRIDE to define and execute tests. As you review the sample code, if you find yourself confused about which code is the test logic and which is the source under test, try reading the source file comments to discern this.
What you need to do
In order to get the full benefit from the samples, we recommend you do the following:
- follow the reference wiki links we provide in the main sample articles. These links provide rich technical information on the topics covered by the sample. These are also articles you will likely refer to in the future when you are implementing your own tests.
- read/review all sample source code prior to running. The samples consist almost entirely of source code, so it makes sense to use a source code editor (one you are familiar with) for this purpose.
- build and execute the samples using the off-target framework. If you completed your installation as instructed above, it should be fully functional when executing them.
- review the reports that are produced when you run the samples. The reports give you a feel for how data is reported in the STRIDE Framework. The extracted documentation is also provided in the report.
- For most samples, we provide some observations that help summarize aspects of the results that might be of interest to you. These observations are not necessarily comprehensive - in fact, we hope you'll discover other interesting features in the samples that we haven't mentioned.
Background
The STRIDE Framework provides support for implementation of tests in the native C/C++ used by the device under test. These samples are a collection of source code that demonstrate the techniques for creating and executing target-based (native code) tests using the STRIDE Framework. Once written, these tests are compiled using the device toolchain and are harnessed, via the STRIDE Intercept Module, into one or more applications under test on the device. These tests have the unique advantage of executing in real-time on the device itself, allowing the tests to operate under actual device conditions during test.
Please review the following reference articles before proceeding:
Why would I want to write tests in native code ?
Here are some of the scenarios for which on-target test harnessing is particularly advantageous:
- Direct API testing
- If you want to validate native APIs by driving the APIs directly, native code is the simplest way to do so. STRIDE provides convenient assertion macros to validate your variable states. API testing can also be combined with native test point tests (using Test Point instrumentation) to provide deeper validation of expected behavior of the units under test.
- Unit testing of C objects or C++ classes
- The STRIDE native tests execute in the same context as the rest of your code, so it's possible to fully unit test any objects that can be created in your actual application code.
- Validation logic that requires sensitive timing thresholds
- Sometimes it's only possible to validate tight timing scenarios on-target.
- High-volume data processing scenarios
- In some cases, the volume of data being processed and validated for a particular test scenario is to large to be easily handled by an off-target harness. In that case, native test units provide a convenient way to write tests that validate that data without shipping the data to the host during testing.
What's more, you might simply prefer to write your test logic in C or C++ (as opposed to perl on the host). If that's the case, we don't discourage you from using a toolset that your more comfortable with - particularly if it enables you to start writing tests without a new language learning curve.
Are There Any Disadvantages ?
Sure. Most of the disadvantages of native on-target tests concern the device build process. If your device build is particularly slow (on the order of hours or days), then adding and running new tests can become a tedious waiting game. Testing is always well served by shorter build cycles, and on-target tests are particularly sensitive to this.
In some cases, the additional code space requirements of native tests is a concern, but this is also mitigated by ever-increasing device storage capacities. On platforms that support multiple processes (e.g. Linux or Windows), it's possible to bundle tests into one or more separate test process, which further mitigates the code space concern by isolating the test code in one or more separate applications.
Targeting the Samples
Note that the C/C++ samples are typically built and run in the STRIDE Off-Target Environment, which is the recommended training environment.
However, once you have STRIDE integrated into your target build, these samples can also be migrated to your target system to provide reference examples and to completely verify your target install.
Introductory Samples
This is the place to start for on target tests in native code. These samples are meant to serve as a basic overview of many native testing features and techniques. If you are interested in writing tests in C/C++ that ultimately run on the device, we recommend building and running these tests, then reviewing the test source code test output.
- Test Intro Sample
- For C-only environments this is the place to start. These samples are meant to serve as a basic overview of many STRIDE testing features and techniques from a C perspective. If you haven't already done so, we recommend building and running these tests, then reviewing the test source code test output. The process of including this sample as well as running it and publishing results is covered in building an Off-Target TestApp article.
- Test Intro Cpp Sample
- For C++ environments this is the place to start. The samples provide a basic overview of many STRIDE testing features and techniques from a C++ perspective.
Test Unit Packaging Samples
Test Unit Packaging refers to how functions or methods implementing test cases are packaged into test units. It's possible for different packaging options to coexist, but for consistency and simplicity, we recommend that you decide early on in your test creation cycle what kind of test unit package you will use for your test units and then stick with that for all of your test units. A good overview of the pros and cons for each type is presented here.
If your compiler supports standard C++, the Test Class packaging is preferred as it allows the greatest functionality and flexibility with no added complexity for the simplest use cases.[1] (Note that the Test Class packaging can be used even if the software under test is written in C.)
If you have selected the type of test unit you will be using, we recommend you review and run the corresponding sample. If you are still deciding which type of test unit packaging to use, feel free to peruse all three samples as well as the corresponding documentation.
- Test Class Sample (C++ only)
- Demonstrates features available when test units are created as C++ classes
- Test C Class Sample
- Demonstrates how to create and use test units that are C structures
- Test Function List Sample
- Demonstrates how to create and use test units that are free C functions
Note: each of the three packaging samples include examples that cover basic usage and more advanced reporting techniques (runtimeservices). We recommend for this training that you focus on the basic samples as they cover the important packaging concepts. The runtimeservices examples are relevant only if the built-in reporting techniques are not sufficient for your reporting needs.
Common Testing Features Samples
These samples demonstrate features that are frequently used in common testing scenarios. All developers creating or maintaining tests should be familiar with the techniques shown in these samples.
Pass/Fail Macros
Pass/Fail Macros simplify the task of setting a test case's status to pass or fail. They comprise a set of ASSERTs and EXPECTs that test a condition (e.g. equailty, less than, strings equal, etc.) and set the currently running test to the appropriate pass or fail status. ASSERTs cause the currently executing function to immediately return if fail status is set; EXPECTs do not return.
- Test Macros Sample
- Demonstrates the use of the Test Code Macros. This sample is implemented using Test Classes (C++ only), but these macros also work in C compilation units.
Advanced Testing Features Samples
The features demonstrated in these samples target specific testing problems.
Test Points
Test points are a unique STRIDE feature that greatly simplifies testing of multi-threaded software as well as single-threaded software that employs callbacks.
- Test Point Sample
- Demonstrates techniques and syntax for implementing Test Points. With this technique, STRIDE makes it possible to observe and verify activity occurring another thread (e.g. a state machine).
Test Doubles
Test doubles provide a means to intercept function calls so that alternate implementations can be substituted at runtime under the control of your test code. This enables sophisticated mocking, faking, and stubbing.
- Test Double Sample
- Demonstrates techniques and syntax for implementing Test Doubles. STRIDE's unique implementation makes it possible to dynamically switch in function mocks, stubs, and fakes at runtime. This sample is implemented using Test Classes (C++ only), but the techniques demonstrated work equally well in C compilation units.
File Services
The STRIDE File Services APIs provide a means to perform basic filesystem operations on the host filesystem from test code running on a device. The STRIDE file transfer APIs enable reading/writing of files on the host from the device under test and can be useful for implementing data driven test scenarios (for instance, media file playback).
- File Services Sample
- Demonstrates techniques and syntax for performing basic tasks using the File Transfer Services API.
Notes
- ↑ If your C++ compiler supports exceptions and/or namespaces, STRIDE can take advantage of the added capabilities, but these are not required