|  | # Porting to Other Implementations | 
|  |  | 
|  | ## Introduction | 
|  |  | 
|  | This document provides an overview of the test runner and how to | 
|  | integrate it with other stacks.  So far we have it working with | 
|  | BoringSSL and some incomplete integrations with NSS and OpenSSL. | 
|  |  | 
|  | Note that supporting non-BoringSSL implementations is a work in | 
|  | progress and interfaces may change in the future. Consumers should pin | 
|  | to a particular revision rather than using BoringSSL’s master branch | 
|  | directly. As we gain experience with other implementations, we hope to | 
|  | make further improvements to portability, so please contact | 
|  | davidben@google.com and ekr@rtfm.com if implementing a new shim. | 
|  |  | 
|  |  | 
|  | ## Integration Architecture | 
|  |  | 
|  | The test runner integrates with the TLS stack under test through a | 
|  | “shim”: a command line program which encapsulates the stack. By | 
|  | default, the shim points to the BoringSSL shim in the same source | 
|  | tree, but any program can be supplied via the `-shim-path` flag. The | 
|  | runner opens up a server socket and provides the shim with a `-port` | 
|  | argument that points to that socket. The shim always connects to the | 
|  | runner as a TCP client even when acting as a TLS server. For DTLS, | 
|  | there is a small framing layer that gives packet boundaries over | 
|  | TCP. The shim can also pass a variety of command line arguments which | 
|  | are used to configure the stack under test. These can be found at | 
|  | `test_config.cc`. | 
|  |  | 
|  |  | 
|  | The shim reports success by exiting with a `0` error code and failure by | 
|  | reporting a non-zero error code and generally sending a textual error | 
|  | value to stderr. Many of the tests expect specific error string (such | 
|  | as `NO_SHARED_CIPHER`) that indicates what went wrong. | 
|  |  | 
|  |  | 
|  | ## Compatibility Issues | 
|  |  | 
|  | There are a number of situations in which the runner might succeed | 
|  | with some tests and not others: | 
|  |  | 
|  | * Defects in the stack under test | 
|  | * Features which haven’t yet been implemented | 
|  | * Failure to implement one or more of the command line flags the runner uses with the shim | 
|  | * Disagreement about the right behavior/interpretation of the spec | 
|  |  | 
|  |  | 
|  | We have implemented several features which allow implementations to ease these compatibility issues. | 
|  |  | 
|  | ### Configuration File | 
|  |  | 
|  | The runner can be supplied with a JSON configuration file which is | 
|  | intended to allow for a per-stack mapping. This file currently takes | 
|  | two directives: | 
|  |  | 
|  |  | 
|  | * `DisabledTests`: A JSON map consisting of the pattern matching the | 
|  | tests to be disabled as the key and some sort of reason why it was | 
|  | disabled as the value. The key is used as a match against the test | 
|  | name. The value is ignored and is just used for documentation | 
|  | purposes so you can remember why you disabled a | 
|  | test. `-include-disabled` overrides this filter. | 
|  |  | 
|  | * `ErrorMap`: A JSON map from the internal errors the runner expects to | 
|  | the error strings that your implementation spits out. Generally | 
|  | you’ll need to map every error, but if you also provide the | 
|  | ` -loose-errors` flag, then every un-mapped error just gets mapped to | 
|  | the empty string and treated as if it matched every error the runner | 
|  | expects. | 
|  |  | 
|  |  | 
|  | The `-shim-config` flag is used to provide the config file. | 
|  |  | 
|  |  | 
|  | ### Unimplemented Features | 
|  | If the shim encounters some request from the runner that it knows it | 
|  | can’t fulfill (e.g., a command line flag that it doesn’t recognize), | 
|  | then it can exit with the special code `89`. Shims are recommended to | 
|  | use this exit code on unknown command-line arguments. | 
|  |  | 
|  | The test runner interprets this as “unimplemented” and skips the | 
|  | test. If run normally, this will cause the test runner to report that | 
|  | the entire test suite failed. The `-allow-unimplemented` flag suppresses | 
|  | this behavior and causes the test runner to ignore these tests for the | 
|  | purpose of evaluating the success or failure of the test suite. | 
|  |  | 
|  |  | 
|  | ### Malloc Tests | 
|  |  | 
|  | The test runner can also be used to stress malloc failure | 
|  | codepaths. If passed `-malloc-test=0`, the runner will run each test | 
|  | repeatedly with an incrementing `MALLOC_NUMBER_TO_FAIL` environment | 
|  | variable. The shim should then replace the malloc implementation with | 
|  | one which fails at the specified number of calls. If there are not | 
|  | enough calls to reach the number, the shim should fail with exit code | 
|  | `88`. This signals to the runner that the test has completed. | 
|  |  | 
|  | See `crypto/test/malloc.cc` for an example malloc implementation. | 
|  |  | 
|  | Note these tests are slow and will hit Go's test timeout. Pass `-timeout 72h` to | 
|  | avoid crashing after 10 minutes. | 
|  |  | 
|  |  | 
|  | ## Example: Running Against NSS | 
|  |  | 
|  | ``` | 
|  | DYLD_LIBRARY_PATH=~/dev/nss-dev/nss-sandbox/dist/Darwin15.6.0_64_DBG.OBJ/lib go test -shim-path ~/dev/nss-dev/nss-sandbox/dist/Darwin15.6.0_64_DBG.OBJ/bin/nss_bogo_shim -loose-errors -allow-unimplemented -shim-config ~/dev/nss-dev/nss-sandbox/nss/external_tests/nss_bogo_shim/config.json | 
|  | ``` |