blob: f0fc34eee7047923a9e992b57825dcc6567b5445 [file] [log] [blame]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Write a Test Suite for a Package &mdash; Apache Mynewt latest documentation</title>
<link rel="shortcut icon" href="../../_static/mynewt-logo-only-newt32x32.png"/>
<link rel="stylesheet" href="../../_static/css/theme.css" type="text/css" />
<link rel="stylesheet" href="../../_static/css/sphinx_theme.css" type="text/css" />
<link rel="stylesheet" href="../../_static/css/bootstrap-3.0.3.min.css" type="text/css" />
<link rel="stylesheet" href="../../_static/css/v2.css" type="text/css" />
<link rel="stylesheet" href="../../_static/css/custom.css" type="text/css" />
<link rel="stylesheet" href="../../_static/css/restructuredtext.css" type="text/css" />
<link rel="stylesheet" href="../../_static/css/overrides.css" type="text/css" />
<link rel="index" title="Index"
href="../../genindex.html"/>
<link rel="search" title="Search" href="../../search.html"/>
<link rel="top" title="Apache Mynewt latest documentation" href="../../index.html"/>
<link rel="up" title="Other" href="other.html"/>
<link rel="next" title="Enable Wi-Fi on Arduino MKR1000" href="wi-fi_on_arduino.html"/>
<link rel="prev" title="How to Reduce Application Code Size" href="codesize.html"/>
<script src="../../_static/js/modernizr.min.js"></script>
<script>
(function(i, s, o, g, r, a, m) {
i["GoogleAnalyticsObject"] = r;
(i[r] =
i[r] ||
function() {
(i[r].q = i[r].q || []).push(arguments);
}),
(i[r].l = 1 * new Date());
(a = s.createElement(o)), (m = s.getElementsByTagName(o)[0]);
a.async = 1;
a.src = g;
m.parentNode.insertBefore(a, m);
})(window, document, "script", "//www.google-analytics.com/analytics.js", "ga");
ga("create", "UA-72162311-1", "auto");
ga("send", "pageview");
</script>
</head>
<body class="not-front page-documentation" role="document" >
<div id="wrapper">
<div class="container">
<div id="banner" class="row v2-main-banner">
<a class="logo-cell" href="/">
<img class="logo" src="../../_static/img/logo.png">
</a>
<div class="tagline-cell">
<h4 class="tagline">An OS to build, deploy and securely manage billions of devices</h4>
</div>
<div class="news-cell">
<div class="well">
<h4>Latest News:</h4> <a href="/download">Apache Mynewt 1.11.0, Apache NimBLE 1.6.0 </a> released September 7, 2023)
</div>
</div>
</div>
</div>
<header>
<nav id="navbar" class="navbar navbar-inverse" role="navigation">
<div class="container">
<!-- Collapsed navigation -->
<div class="navbar-header">
<!-- Expander button -->
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<!-- Expanded navigation -->
<div class="navbar-collapse collapse">
<!-- Main navigation -->
<ul class="nav navbar-nav navbar-right">
<li>
<a href="/"><i class="fa fa-home" style="font-size: larger;"></i></a>
</li>
<li class="important">
<a href="/quick-start/">Quick Start</a>
</li>
<li>
<a href="/about/">About</a>
</li>
<li>
<a href="/talks/">Talks</a>
</li>
<li class="active">
<a href="/documentation/">Documentation</a>
</li>
<li>
<a href="/download/">Download</a>
</li>
<li>
<a href="/community/">Community</a>
</li>
<li>
<a href="/events/">Events</a>
</li>
</ul>
<!-- Search, Navigation and Repo links -->
<ul class="nav navbar-nav navbar-right">
</ul>
</div>
</div>
</nav>
</header>
<!-- STARTS MAIN CONTENT -->
<div id="main-content">
<div id="breadcrumb">
<div class="container">
<a href="/documentation/">Docs</a> /
<a href="../tutorials.html">Tutorials</a> /
<a href="other.html">Other</a> /
Write a Test Suite for a Package
<div class="sourcelink">
<a href="https://github.com/apache/mynewt-documentation/edit/master/docs/tutorials/other/unit_test.rst" class="icon icon-github"
rel="nofollow"> Edit on GitHub</a>
</div>
</div>
</div>
<!-- STARTS CONTAINER -->
<div class="container">
<!-- STARTS .content -->
<div id="content" class="row">
<!-- STARTS .container-sidebar -->
<div class="container-sidebar col-xs-12 col-sm-3">
<div id="docSidebar" class="sticky-container">
<div role="search" class="sphinx-search">
<form id="rtd-search-form" class="wy-form" action="../../search.html" method="get">
<input type="text" name="q" placeholder="Search documentation" class="search-documentation" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
<!-- Note: only works when deployed -->
<select class="form-control" onchange="if (this.value) window.location.href=this.value">
<option value="/latest" selected>
Version: latest
</option>
<option value="/v1_11_0" >
Version: 1.11.0
</option>
<option value="/v1_10_0" >
Version: 1.10.0
</option>
<option value="/v1_9_0" >
Version: 1.9.0
</option>
<option value="/v1_8_0" >
Version: 1.8.0
</option>
<option value="/v1_7_0" >
Version: 1.7.0
</option>
<option value="/v1_6_0" >
Version: 1.6.0
</option>
<option value="/v1_5_0" selected="selected" >
Version: 1.5.0
</option>
<option value="/v1_4_0" >
Version: 1.4.0
</option>
<option value="/v1_3_0/os/introduction" >
Version: 1.3.0
</option>
<option value="/v1_2_0/os/introduction" >
Version: 1.2.0
</option>
<option value="/v1_1_0/os/introduction" >
Version: 1.1.0
</option>
<option value="/v1_0_0/os/introduction" >
Version: 1.0.0
</option>
<option value="/v0_9_0/os/introduction" >
Version: 0.9.0
</option>
</select>
<div class="region region-sidebar">
<div class="docs-menu">
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../../index.html">Introduction</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../get_started/index.html">Setup &amp; Get Started</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../concepts.html">Concepts</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="../tutorials.html">Tutorials</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="../blinky/blinky.html">Project Blinky</a></li>
<li class="toctree-l2"><a class="reference internal" href="../repo/add_repos.html">Working with repositories</a></li>
<li class="toctree-l2"><a class="reference internal" href="../slinky/project-slinky.html">Project Slinky for Remote Comms</a></li>
<li class="toctree-l2"><a class="reference internal" href="../ble/ble.html">Bluetooth Low Energy</a></li>
<li class="toctree-l2"><a class="reference internal" href="../lora/lorawanapp.html">LoRa</a></li>
<li class="toctree-l2"><a class="reference internal" href="../os_fundamentals/os_fundamentals.html">OS Fundamentals</a></li>
<li class="toctree-l2"><a class="reference internal" href="../devmgmt/devmgmt.html">Remote Device Management</a></li>
<li class="toctree-l2"><a class="reference internal" href="../sensors/sensors.html">Sensors</a></li>
<li class="toctree-l2"><a class="reference internal" href="../tooling/tooling.html">Tooling</a></li>
<li class="toctree-l2 current"><a class="reference internal" href="other.html">Other</a><ul class="current">
<li class="toctree-l3"><a class="reference internal" href="codesize.html">How to reduce Application Code Size</a></li>
<li class="toctree-l3 current"><a class="current reference internal" href="#">Write a Test Suite for a Package</a></li>
<li class="toctree-l3"><a class="reference internal" href="wi-fi_on_arduino.html">Enable Wi-Fi on Arduino MKR1000</a></li>
<li class="toctree-l3"><a class="reference internal" href="chg_ctrl_on_pinetime.html">Charge control on PineTime</a></li>
<li class="toctree-l3"><a class="reference internal" href="rust.html">Rust Blinky application</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../../external_links.html">Third-party Resources</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../os/os_user_guide.html">OS User Guide</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../network/index.html">BLE User Guide</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../newt/index.html">Newt Tool Guide</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../newtmgr/index.html">Newt Manager Guide</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../mynewt_faq/index.html">Mynewt FAQ</a></li>
<li class="toctree-l1"><a class="reference internal" href="../../misc/index.html">Appendix</a></li>
</ul>
</div>
</div>
</div>
<!-- ENDS STICKY CONTAINER -->
</div>
<!-- ENDS .container-sidebar -->
<div class="col-xs-12 col-sm-9">
<div class="alert alert-warning">
<p>
Version 1.5.0 is not the most recent version of the
Apache Mynewt documentation. Click <a href="/latest">here</a> to
read the latest version.
</p>
</div>
<div class="">
<div class="rst-content">
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<div class="section" id="write-a-test-suite-for-a-package">
<h1>Write a Test Suite for a Package<a class="headerlink" href="#write-a-test-suite-for-a-package" title="Permalink to this headline"></a></h1>
<p>This document guides the reader through creating a test suite for a
Mynewt package.</p>
<div class="section" id="introduction">
<h2>Introduction<a class="headerlink" href="#introduction" title="Permalink to this headline"></a></h2>
<p>Writing a test suite involves using the
<span class="xref std std-doc">test/testutil</span> package. The
testutil library provides the functionality needed to define test suites
and test cases.</p>
</div>
<div class="section" id="choose-your-package-under-test">
<h2>Choose Your Package Under Test<a class="headerlink" href="#choose-your-package-under-test" title="Permalink to this headline"></a></h2>
<p>Choose the package you want to write a test suite for. In this tutorial,
we will use the <code class="docutils literal notranslate"><span class="pre">time/datetime</span></code> in the apache-mynewt-core repo.
Throughout this tutorial, we will be inside the apache-mynewt-core repo
directory, unlike most tutorials which operate from the top-level
project directory.</p>
</div>
<div class="section" id="create-a-test-package">
<h2>Create A Test Package<a class="headerlink" href="#create-a-test-package" title="Permalink to this headline"></a></h2>
<p>Typically, a library has only one test package. The convention is name
the test package by appending <code class="docutils literal notranslate"><span class="pre">/test</span></code> to the host library name. For
example, the test package for <code class="docutils literal notranslate"><span class="pre">encoding/json</span></code> is
<code class="docutils literal notranslate"><span class="pre">encoding/json/test</span></code>. The directory structure of the json package is
shown below:</p>
<div class="highlight-console notranslate"><div class="highlight"><pre><span></span><span class="go">encoding/json</span>
<span class="go">├── include</span>
<span class="go">│   └── json</span>
<span class="go">│   └── json.h</span>
<span class="go">├── pkg.yml</span>
<span class="go">├── src</span>
<span class="go">│   ├── json_decode.c</span>
<span class="go">│   └── json_encode.c</span>
<span class="go">└── test</span>
<span class="go"> ├── pkg.yml</span>
<span class="go"> └── src</span>
<span class="go"> ├── test_json.c</span>
<span class="go"> ├── test_json.h</span>
<span class="go"> ├── test_json_utils.c</span>
<span class="go"> └── testcases</span>
<span class="go"> ├── json_simple_decode.c</span>
<span class="go"> └── json_simple_encode.c</span>
</pre></div>
</div>
<p>The top-level <code class="docutils literal notranslate"><span class="pre">test</span></code> directory contains the json test package. To
create a test package for the datetime package, we need to create a
similar package called <code class="docutils literal notranslate"><span class="pre">time/datetime/test</span></code>.</p>
<div class="highlight-console notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>newt<span class="w"> </span>pkg<span class="w"> </span>new<span class="w"> </span>time/datetime/test<span class="w"> </span>-t<span class="w"> </span>unittest
<span class="go">Download package template for package type pkg.</span>
<span class="go">Package successfuly installed into /home/me/mynewt-core/time/datetime/test.</span>
</pre></div>
</div>
<p>We now have a test package inside <code class="docutils literal notranslate"><span class="pre">time/datetime</span></code>:</p>
<div class="highlight-console notranslate"><div class="highlight"><pre><span></span><span class="go">time/datetime</span>
<span class="go">├── include</span>
<span class="go">│   └── datetime</span>
<span class="go">│   └── datetime.h</span>
<span class="go">├── pkg.yml</span>
<span class="go">├── src</span>
<span class="go">│   └── datetime.c</span>
<span class="go">└── test</span>
<span class="go"> ├── README.md</span>
<span class="go"> ├── pkg.yml</span>
<span class="go"> ├── src</span>
<span class="go"> │   └── main.c</span>
<span class="go"> └── syscfg.yml</span>
</pre></div>
</div>
<p>There is one modification we need to make to the new package before we
can start writing unit test code. A test package needs access to the
code it will be testing, so we need to add a dependency on
<code class="docutils literal notranslate"><span class="pre">&#64;apache-mynewt-core/time/datetime</span></code> to our <code class="docutils literal notranslate"><span class="pre">pkg.yml</span></code> file:</p>
<div class="highlight-console notranslate"><div class="highlight"><pre><span></span><span class="go"> pkg.name: &quot;time/datetime/test&quot;</span>
<span class="go"> pkg.type: unittest</span>
<span class="go"> pkg.description: &quot;Description of your package&quot;</span>
<span class="go"> pkg.author: &quot;You &lt;you@you.org&gt;&quot;</span>
<span class="go"> pkg.homepage: &quot;http://your-url.org/&quot;</span>
<span class="go"> pkg.keywords:</span>
<span class="go"> pkg.deps:</span>
<span class="go"> - &#39;@apache-mynewt-core/test/testutil&#39;</span>
<span class="hll"><span class="go"> - &#39;@apache-mynewt-core/time/datetime&#39;</span>
</span>
<span class="go"> pkg.deps.SELFTEST:</span>
<span class="go"> - &#39;@apache-mynewt-core/sys/console/stub&#39;</span>
</pre></div>
</div>
<p>While we have the <code class="docutils literal notranslate"><span class="pre">pkg.yml</span></code> file open, let’s take a look at what newt
filled in automatically:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">pkg.type:</span> <span class="pre">unittest</span></code> designates this as a test package. A <em>test
package</em> is special in that it can be built and executed using the
<code class="docutils literal notranslate"><span class="pre">newt</span> <span class="pre">test</span></code> command.</p></li>
<li><p>A test package always depends on
<code class="docutils literal notranslate"><span class="pre">&#64;apache-mynewt-core/test/testutil</span></code>. The testutil library provides
the tools necessary for verifying package behavior,</p></li>
<li><p>The <code class="docutils literal notranslate"><span class="pre">SELFTEST</span></code> suffix indicates that a setting should only be
applied when the <code class="docutils literal notranslate"><span class="pre">newt</span> <span class="pre">test</span></code> command is used.</p></li>
</ul>
<p>Regarding the conditional dependency on <code class="docutils literal notranslate"><span class="pre">sys/console/stub</span></code>, the
datetime package requires some form of console to function. In a regular
application, the console dependency would be supplied by a higher order
package. Because <code class="docutils literal notranslate"><span class="pre">newt</span> <span class="pre">test</span></code> runs the test package without an
application present, the test package needs to supply all unresolved
dependencies itself when run in self-test mode.</p>
</div>
<div class="section" id="create-your-test-suite-code">
<h2>Create Your Test Suite Code<a class="headerlink" href="#create-your-test-suite-code" title="Permalink to this headline"></a></h2>
<p>We will be adding a <em>test suite</em> to the <code class="docutils literal notranslate"><span class="pre">main.c</span></code> file. The test suite
will be empty for now. We also need to invoke the test suite from
<code class="docutils literal notranslate"><span class="pre">main()</span></code>.</p>
<p>Our <code class="docutils literal notranslate"><span class="pre">main.c</span></code> file now looks like this:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cp">#include</span><span class="w"> </span><span class="cpf">&quot;sysinit/sysinit.h&quot;</span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf">&quot;testutil/testutil.h&quot;</span>
<span class="n">TEST_SUITE</span><span class="p">(</span><span class="n">test_datetime_suite</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="cm">/* Empty for now; add test cases later. */</span>
<span class="p">}</span>
<span class="cp">#if MYNEWT_VAL(SELFTEST)</span>
<span class="kt">int</span>
<span class="n">main</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">argc</span><span class="p">,</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">**</span><span class="n">argv</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="cm">/* Initialize all packages. */</span>
<span class="w"> </span><span class="n">sysinit</span><span class="p">();</span>
<span class="w"> </span><span class="n">test_datetime_suite</span><span class="p">();</span>
<span class="w"> </span><span class="cm">/* Indicate whether all test cases passed. */</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">tu_any_failed</span><span class="p">;</span>
<span class="p">}</span>
<span class="cp">#endif</span>
</pre></div>
</div>
</div>
<div class="section" id="try-it-out">
<h2>Try It Out<a class="headerlink" href="#try-it-out" title="Permalink to this headline"></a></h2>
<p>We now have a working test suite with no tests. Let’s make sure we get a
passing result when we run <code class="docutils literal notranslate"><span class="pre">newt</span> <span class="pre">test</span></code>:</p>
<div class="highlight-console notranslate"><div class="highlight"><pre><span></span><span class="gp">$ </span>newt<span class="w"> </span><span class="nb">test</span><span class="w"> </span>time/datetime
<span class="go">&lt;build output&gt;</span>
<span class="go">Executing test: /home/me/mynewt-core/bin/targets/unittest/time_datetime_test/app/time/datetime/test/time_datetime_test.elf</span>
<span class="go">Passed tests: [time/datetime/test]</span>
<span class="go">All tests passed</span>
</pre></div>
</div>
</div>
<div class="section" id="create-a-test">
<h2>Create a Test<a class="headerlink" href="#create-a-test" title="Permalink to this headline"></a></h2>
<p>To create a test within your test suite, there are two things to do.</p>
<ol class="arabic simple">
<li><p>Implement the test case function using the <code class="docutils literal notranslate"><span class="pre">testutil</span></code> macros.</p></li>
<li><p>Call the test case function from within the test suite.</p></li>
</ol>
<p>For this tutorial we will create a test case to verify the
<code class="docutils literal notranslate"><span class="pre">datetime_parse()</span></code> function. The <code class="docutils literal notranslate"><span class="pre">datetime_parse()</span></code> function is
declared as follows:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cm">/**</span>
<span class="cm"> * Parses an RFC 3339 datetime string. Some examples of valid datetime strings</span>
<span class="cm"> * are:</span>
<span class="cm"> * 2016-03-02T22:44:00 UTC time (implicit)</span>
<span class="cm"> * 2016-03-02T22:44:00Z UTC time (explicit)</span>
<span class="cm"> * 2016-03-02T22:44:00-08:00 PST timezone</span>
<span class="cm"> * 2016-03-02T22:44:00.1 fractional seconds</span>
<span class="cm"> * 2016-03-02T22:44:00.101+05:30 fractional seconds with timezone</span>
<span class="cm"> *</span>
<span class="cm"> * On success, the two output parameters are filled in (tv and tz).</span>
<span class="cm"> *</span>
<span class="cm"> * @return 0 on success;</span>
<span class="cm"> * nonzero on parse error.</span>
<span class="cm"> */</span>
<span class="kt">int</span>
<span class="n">datetime_parse</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">input</span><span class="p">,</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">os_timeval</span><span class="w"> </span><span class="o">*</span><span class="n">tv</span><span class="p">,</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">os_timezone</span><span class="w"> </span><span class="o">*</span><span class="n">tz</span><span class="p">)</span>
</pre></div>
</div>
<p>Our test case should make sure this function rejects invalid input, and
that it parses valid input correctly. The updated <code class="docutils literal notranslate"><span class="pre">main.c</span></code> file looks
like this:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="cp">#include</span><span class="w"> </span><span class="cpf">&quot;sysinit/sysinit.h&quot;</span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf">&quot;testutil/testutil.h&quot;</span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf">&quot;os/os_time.h&quot;</span>
<span class="cp">#include</span><span class="w"> </span><span class="cpf">&quot;datetime/datetime.h&quot;</span>
<span class="n">TEST_SUITE</span><span class="p">(</span><span class="n">test_datetime_suite</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="n">test_datetime_parse_simple</span><span class="p">();</span>
<span class="p">}</span>
<span class="n">TEST_CASE</span><span class="p">(</span><span class="n">test_datetime_parse_simple</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">os_timezone</span><span class="w"> </span><span class="n">tz</span><span class="p">;</span>
<span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">os_timeval</span><span class="w"> </span><span class="n">tv</span><span class="p">;</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">rc</span><span class="p">;</span>
<span class="w"> </span><span class="cm">/*** Valid input. */</span>
<span class="w"> </span><span class="cm">/* No timezone; UTC implied. */</span>
<span class="w"> </span><span class="n">rc</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">datetime_parse</span><span class="p">(</span><span class="s">&quot;2017-06-28T22:37:59&quot;</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">tv</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">tz</span><span class="p">);</span>
<span class="w"> </span><span class="n">TEST_ASSERT_FATAL</span><span class="p">(</span><span class="n">rc</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
<span class="w"> </span><span class="n">TEST_ASSERT</span><span class="p">(</span><span class="n">tv</span><span class="p">.</span><span class="n">tv_sec</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">1498689479</span><span class="p">);</span>
<span class="w"> </span><span class="n">TEST_ASSERT</span><span class="p">(</span><span class="n">tv</span><span class="p">.</span><span class="n">tv_usec</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
<span class="w"> </span><span class="n">TEST_ASSERT</span><span class="p">(</span><span class="n">tz</span><span class="p">.</span><span class="n">tz_minuteswest</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
<span class="w"> </span><span class="n">TEST_ASSERT</span><span class="p">(</span><span class="n">tz</span><span class="p">.</span><span class="n">tz_dsttime</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
<span class="w"> </span><span class="cm">/* PDT timezone. */</span>
<span class="w"> </span><span class="n">rc</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">datetime_parse</span><span class="p">(</span><span class="s">&quot;2013-12-05T02:43:07-07:00&quot;</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">tv</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">tz</span><span class="p">);</span>
<span class="w"> </span><span class="n">TEST_ASSERT_FATAL</span><span class="p">(</span><span class="n">rc</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
<span class="w"> </span><span class="n">TEST_ASSERT</span><span class="p">(</span><span class="n">tv</span><span class="p">.</span><span class="n">tv_sec</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">1386236587</span><span class="p">);</span>
<span class="w"> </span><span class="n">TEST_ASSERT</span><span class="p">(</span><span class="n">tv</span><span class="p">.</span><span class="n">tv_usec</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
<span class="w"> </span><span class="n">TEST_ASSERT</span><span class="p">(</span><span class="n">tz</span><span class="p">.</span><span class="n">tz_minuteswest</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">420</span><span class="p">);</span>
<span class="w"> </span><span class="n">TEST_ASSERT</span><span class="p">(</span><span class="n">tz</span><span class="p">.</span><span class="n">tz_dsttime</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
<span class="w"> </span><span class="cm">/*** Invalid input. */</span>
<span class="w"> </span><span class="cm">/* Nonsense. */</span>
<span class="w"> </span><span class="n">rc</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">datetime_parse</span><span class="p">(</span><span class="s">&quot;abc&quot;</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">tv</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">tz</span><span class="p">);</span>
<span class="w"> </span><span class="n">TEST_ASSERT</span><span class="p">(</span><span class="n">rc</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
<span class="w"> </span><span class="cm">/* Date-only. */</span>
<span class="w"> </span><span class="n">rc</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">datetime_parse</span><span class="p">(</span><span class="s">&quot;2017-01-02&quot;</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">tv</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">tz</span><span class="p">);</span>
<span class="w"> </span><span class="n">TEST_ASSERT</span><span class="p">(</span><span class="n">rc</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
<span class="w"> </span><span class="cm">/* Zero month. */</span>
<span class="w"> </span><span class="n">rc</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">datetime_parse</span><span class="p">(</span><span class="s">&quot;2017-00-28T22:37:59&quot;</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">tv</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">tz</span><span class="p">);</span>
<span class="w"> </span><span class="n">TEST_ASSERT</span><span class="p">(</span><span class="n">rc</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
<span class="w"> </span><span class="cm">/* 13 month. */</span>
<span class="w"> </span><span class="n">rc</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">datetime_parse</span><span class="p">(</span><span class="s">&quot;2017-13-28T22:37:59&quot;</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">tv</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">tz</span><span class="p">);</span>
<span class="w"> </span><span class="n">TEST_ASSERT</span><span class="p">(</span><span class="n">rc</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
<span class="cp">#if MYNEWT_VAL(SELFTEST)</span>
<span class="kt">int</span>
<span class="n">main</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">argc</span><span class="p">,</span><span class="w"> </span><span class="kt">char</span><span class="w"> </span><span class="o">**</span><span class="n">argv</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="cm">/* Initialize all packages. */</span>
<span class="w"> </span><span class="n">sysinit</span><span class="p">();</span>
<span class="w"> </span><span class="n">test_datetime_suite</span><span class="p">();</span>
<span class="w"> </span><span class="cm">/* Indicate whether all test cases passed. */</span>
<span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">tu_any_failed</span><span class="p">;</span>
<span class="p">}</span>
<span class="cp">#endif</span>
</pre></div>
</div>
<p>Take a few minutes to review the above code. Then keep reading for some
specifics.</p>
<div class="section" id="asserting">
<h3>Asserting<a class="headerlink" href="#asserting" title="Permalink to this headline"></a></h3>
<p>The <code class="docutils literal notranslate"><span class="pre">test/testutil</span></code> package provides two tools for verifying the
correctness of a package:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">TEST_ASSERT</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">TEST_ASSERT_FATAL</span></code></p></li>
</ul>
<p>Both of these macros check if the supplied condition is true. They
differ in how they behave when the condition is not true. On failure,
<code class="docutils literal notranslate"><span class="pre">TEST_ASSERT</span></code> reports the error and proceeds with the remainder of the
test case. <code class="docutils literal notranslate"><span class="pre">TEST_ASSERT_FATAL</span></code>, on the other hand, aborts the test
case on failure.</p>
<p>The general rule is to only use <code class="docutils literal notranslate"><span class="pre">TEST_ASSERT_FATAL</span></code> when subsequent
assertions depend on the condition being checked. For example, when
<code class="docutils literal notranslate"><span class="pre">datetime_parse()</span></code> is expected to succeed, the return code is checked
with <code class="docutils literal notranslate"><span class="pre">TEST_ASSERT_FATAL</span></code>. If <code class="docutils literal notranslate"><span class="pre">datetime_parse()</span></code> unexpectedly failed,
the contents of the <code class="docutils literal notranslate"><span class="pre">tv</span></code> and <code class="docutils literal notranslate"><span class="pre">tz</span></code> objects would be indeterminate, so
it is desirable to abort the test instead of checking them and reporting
spurious failures.</p>
</div>
<div class="section" id="scaling-up">
<h3>Scaling Up<a class="headerlink" href="#scaling-up" title="Permalink to this headline"></a></h3>
<p>The above example is small and self contained, so it is reasonable to
put everything in a single C file. A typical package will need a lot
more test code, and it helps to follow some conventions to maintain
organization. Let’s take a look at a more realistic example. Here is the
directory structure of the <code class="docutils literal notranslate"><span class="pre">fs/nffs/test</span></code> package:</p>
<div class="highlight-console notranslate"><div class="highlight"><pre><span></span><span class="go">fs/nffs/test</span>
<span class="go">├── pkg.yml</span>
<span class="go">└── src</span>
<span class="go"> ├── nffs_test.c</span>
<span class="go"> ├── nffs_test.h</span>
<span class="go"> ├── nffs_test_debug.c</span>
<span class="go"> ├── nffs_test_priv.h</span>
<span class="go"> ├── nffs_test_system_01.c</span>
<span class="go"> ├── nffs_test_utils.c</span>
<span class="go"> ├── nffs_test_utils.h</span>
<span class="go"> └── testcases</span>
<span class="go"> ├── append_test.c</span>
<span class="go"> ├── cache_large_file_test.c</span>
<span class="go"> ├── corrupt_block_test.c</span>
<span class="go"> ├── corrupt_scratch_test.c</span>
<span class="go"> ├── gc_on_oom_test.c</span>
<span class="go"> ├── gc_test.c</span>
<span class="go"> ├── incomplete_block_test.c</span>
<span class="go"> ├── large_system_test.c</span>
<span class="go"> ├── large_unlink_test.c</span>
<span class="go"> ├── large_write_test.c</span>
<span class="go"> ├── long_filename_test.c</span>
<span class="go"> ├── lost_found_test.c</span>
<span class="go"> ├── many_children_test.c</span>
<span class="go"> ├── mkdir_test.c</span>
<span class="go"> ├── open_test.c</span>
<span class="go"> ├── overwrite_many_test.c</span>
<span class="go"> ├── overwrite_one_test.c</span>
<span class="go"> ├── overwrite_three_test.c</span>
<span class="go"> ├── overwrite_two_test.c</span>
<span class="go"> ├── read_test.c</span>
<span class="go"> ├── readdir_test.c</span>
<span class="go"> ├── rename_test.c</span>
<span class="go"> ├── split_file_test.c</span>
<span class="go"> ├── truncate_test.c</span>
<span class="go"> ├── unlink_test.c</span>
<span class="go"> └── wear_level_test.c</span>
</pre></div>
</div>
<p>The <code class="docutils literal notranslate"><span class="pre">fs/nffs/test</span></code> package follows these conventions:</p>
<ol class="arabic simple">
<li><p>A maximum of one test case per C file.</p></li>
<li><p>Each test case file goes in the <code class="docutils literal notranslate"><span class="pre">testcases</span></code> subdirectory.</p></li>
<li><p>Test suites and utility functions go directly in the <code class="docutils literal notranslate"><span class="pre">src</span></code>
directory.</p></li>
</ol>
<p>Test packages contributed to the Mynewt project should follow these
conventions.</p>
</div>
</div>
<div class="section" id="congratulations">
<h2>Congratulations<a class="headerlink" href="#congratulations" title="Permalink to this headline"></a></h2>
<p>Now you can begin the work of validating your packages.</p>
</div>
</div>
</div>
</div>
<div class="rst-footer-buttons row" role="navigation" aria-label="footer navigation">
<a href="wi-fi_on_arduino.html" class="btn btn-neutral float-right" title="Enable Wi-Fi on Arduino MKR1000" accesskey="n">Next: Enable Wi-Fi on Arduino MKR1000 <span class="fa fa-arrow-circle-right"></span></a>
<a href="codesize.html" class="btn btn-neutral" title="How to Reduce Application Code Size" accesskey="p"><span class="fa fa-arrow-circle-left"></span> Previous: How to Reduce Application Code Size</a>
</div>
</div>
</div>
</div>
<!-- ENDS CONTENT SECTION -->
</div>
<!-- ENDS .content -->
</div>
</div>
<footer>
<div class="container">
<div class="row">
<div class="col-xs-12">
<p class="copyright">Apache Mynewt is available under Apache License, version 2.0.</p>
</div>
<div class="col-xs-12">
<div class="logos">
<img src="../../_static/img/asf_logo_wide_small.png" alt="Apache" title="Apache">
<small class="footnote">
Apache Mynewt, Mynewt, Apache, the Apache feather logo, and the Apache Mynewt project logo are either
registered trademarks or trademarks of the Apache Software Foundation in the United States and other countries.
</small>
<a href="">
<img src="../../_static/img/add_to_slack.png" alt="Slack Icon" title="Join our Slack Community" />
</a>
</div>
</div>
</div>
</div>
</footer>
</div>
<!-- ENDS #wrapper -->
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT:'../../',
VERSION:'latest',
COLLAPSE_INDEX:false,
FILE_SUFFIX:'.html',
HAS_SOURCE: true,
SOURCELINK_SUFFIX: '.txt',
LINK_SUFFIX: '.html'
};
</script>
<script type="text/javascript" src="../../_static/jquery.js"></script>
<script type="text/javascript" src="../../_static/underscore.js"></script>
<script type="text/javascript" src="../../_static/doctools.js"></script>
<script type="text/javascript" src="../../_static/js/bootstrap-3.0.3.min.js"></script>
<script type="text/javascript" src="../../_static/js/affix.js"></script>
<script type="text/javascript" src="../../_static/js/main.js"></script>
</body>
</html>