<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Testing on Roberto Selbach</title><link>https://rselbach.com/tags/testing/</link><description>Recent content in Testing on Roberto Selbach</description><generator>Hugo</generator><language>en-US</language><lastBuildDate>Thu, 09 Oct 2014 13:10:00 +0000</lastBuildDate><atom:link href="https://rselbach.com/tags/testing/index.xml" rel="self" type="application/rss+xml"/><item><title>Parallel benchmarks and wandering maps</title><link>https://rselbach.com/parallel-benchmarks-and-wandering-maps/</link><pubDate>Thu, 09 Oct 2014 13:10:00 +0000</pubDate><guid>https://rselbach.com/parallel-benchmarks-and-wandering-maps/</guid><description>&lt;p&gt;I tested a locked lookup table with Go 1.3&amp;rsquo;s parallel benchmark support:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;BenchmarkLookupParallel&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;b&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;testing&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;B&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;b&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;RunParallel&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;func&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;pb&lt;/span&gt; &lt;span style="color:#f92672"&gt;*&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;testing&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;PB&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;pb&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Next&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;			&lt;span style="color:#a6e22e"&gt;_&lt;/span&gt; = &lt;span style="color:#a6e22e"&gt;table&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Lookup&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;troy&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;RunParallel&lt;/code&gt; creates goroutines and distributes benchmark iterations among them. This exposed lock contention that a serial benchmark politely concealed. It is still synthetic: all workers hammering one key may be less realistic than production, so I use representative key distributions too.&lt;/p&gt;
&lt;p&gt;The same upgrade broke a test that compared map traversal output to a fixed string. Go 1.3 randomizes iteration order for small maps, making an assumption that was always invalid fail more reliably.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;k&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;range&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;m&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;keys&lt;/span&gt; = append(&lt;span style="color:#a6e22e"&gt;keys&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;k&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;sort&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Strings&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;keys&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Sorting is correct when output order is part of the result. For equality, I compare contents instead of rendering iteration order.&lt;/p&gt;
&lt;p&gt;Random order is not cryptographic randomness, nor should a program depend on getting a different order every pass. It is an implementation defense against accidental ordering assumptions, not a shuffling API.&lt;/p&gt;
&lt;p&gt;I approve of the randomization. A runtime that accidentally rewards a bad assumption lets the assumption become an API. My test was not flaky; it was finally honest.&lt;/p&gt;</description></item><item><title>Coverage, TLS, and atomic swaps in Go 1.2</title><link>https://rselbach.com/coverage-tls-and-atomic-swaps-in-go-1-2/</link><pubDate>Thu, 09 Jan 2014 15:35:00 +0000</pubDate><guid>https://rselbach.com/coverage-tls-and-atomic-swaps-in-go-1-2/</guid><description>&lt;p&gt;Three Go 1.2 additions fixed three unrelated annoyances in one week. None is glamorous, which is usually a sign that I will use it.&lt;/p&gt;
&lt;p&gt;First, &lt;code&gt;go test&lt;/code&gt; now measures statement coverage directly:&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;cover&lt;/code&gt; tool is still distributed separately in &lt;code&gt;go.tools&lt;/code&gt;, so I installed it first:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;$&lt;/span&gt; go get code&lt;span style="color:#f92672"&gt;.&lt;/span&gt;google&lt;span style="color:#f92672"&gt;.&lt;/span&gt;com&lt;span style="color:#f92672"&gt;/&lt;/span&gt;p&lt;span style="color:#f92672"&gt;/&lt;/span&gt;go&lt;span style="color:#f92672"&gt;.&lt;/span&gt;tools&lt;span style="color:#f92672"&gt;/&lt;/span&gt;cmd&lt;span style="color:#f92672"&gt;/&lt;/span&gt;cover
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;$ go test -cover
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;PASS
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;coverage: 71.4% of statements
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ok example/parser 0.012s
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For detail I use &lt;code&gt;go test -coverprofile=cover.out&lt;/code&gt;, followed by &lt;code&gt;go tool cover -func=cover.out&lt;/code&gt; or &lt;code&gt;go tool cover -html=cover.out&lt;/code&gt;. Coverage works by rewriting source with counters. It tells me which statements ran, not whether the assertions were intelligent. I can reach 100 percent while testing almost nothing; I have demonstrated this skill repeatedly.&lt;/p&gt;
&lt;p&gt;Second, &lt;code&gt;crypto/tls&lt;/code&gt; gained better control over protocol and cipher behavior, including TLS 1.2 support. For a client that must reject obsolete protocol versions I can set the minimum explicitly:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;tr&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Transport&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	&lt;span style="color:#a6e22e"&gt;TLSClientConfig&lt;/span&gt;: &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;tls&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Config&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;		&lt;span style="color:#a6e22e"&gt;MinVersion&lt;/span&gt;: &lt;span style="color:#a6e22e"&gt;tls&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;VersionTLS11&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;	},
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;client&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;http&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Client&lt;/span&gt;{&lt;span style="color:#a6e22e"&gt;Transport&lt;/span&gt;: &lt;span style="color:#a6e22e"&gt;tr&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I still let the standard library choose cipher suites unless interoperability forces my hand. A handwritten list ages, and a secure-looking list copied from a weblog ages especially well.&lt;/p&gt;
&lt;p&gt;Finally, &lt;code&gt;sync/atomic&lt;/code&gt; now has swap operations. I used one to replace a numeric generation and retrieve the previous value as a single atomic action:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;old&lt;/span&gt; &lt;span style="color:#f92672"&gt;:=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;atomic&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;SwapUint64&lt;/span&gt;(&lt;span style="color:#f92672"&gt;&amp;amp;&lt;/span&gt;&lt;span style="color:#a6e22e"&gt;generation&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;next&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;Printf&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;generation %d -&amp;gt; %d&amp;#34;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;old&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;next&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The important phrase is &amp;ldquo;single atomic action.&amp;rdquo; Loading and then storing separately leaves a window in which another goroutine can intervene. A swap closes that window, but it does not magically protect related fields or establish a larger invariant. For that I still use a mutex.&lt;/p&gt;
&lt;p&gt;The default coverage mode counts whether statements execute. When tests exercise code concurrently, &lt;code&gt;-covermode=atomic&lt;/code&gt; makes counter updates safe, at additional cost. I do not compare benchmark timings from an instrumented coverage build with normal timings. The inserted counters are deliberately observable work.&lt;/p&gt;
&lt;p&gt;Atomics also require aligned, correctly typed storage and a design whose state really fits in one word. My generation counter does. A configuration containing a counter, pointer, and status does not become coherent because each field can be manipulated atomically. Readers could observe a combination that never represented one published configuration.&lt;/p&gt;
&lt;p&gt;I keep the atomic operation beside a comment describing that single-word invariant. Otherwise the next maintenance change tends to add a companion field and quietly invalidate the reasoning.&lt;/p&gt;
&lt;p&gt;These features share a useful property: they turn homemade approximations into explicit operations. I deleted a coverage script, avoided a custom TLS dialer, and replaced a dubious load/store pair. Upgrades are pleasant when the final diff is mostly subtraction.&lt;/p&gt;</description></item><item><title>Testing KDE 3.5 With Real Work</title><link>https://rselbach.com/testing-kde-35-with-real-work/</link><pubDate>Fri, 04 Nov 2005 19:25:00 +0000</pubDate><guid>https://rselbach.com/testing-kde-35-with-real-work/</guid><description>&lt;p&gt;I&amp;rsquo;ve been testing KDE 3.5&amp;rsquo;s KHTML changes ahead of the final release. Passing a standards test is good news, but I wanted to know whether the same engine still handled the untidy pages I use for work.&lt;/p&gt;
&lt;p&gt;I started with a small directory of local pages: nested floats, a wide preformatted block, a form inside a table, transparent PNGs, and one page with deliberately broken markup. Each isolates a behavior well enough that a rendering change isn&amp;rsquo;t just “this site looks odd.”&lt;/p&gt;
&lt;p&gt;Then I used Konqueror on documentation and project sites with style sheets enabled, disabled, and replaced by a tiny user sheet. Keyboard focus still had to move through links and form controls in a sensible order. Better CSS support isn&amp;rsquo;t much help if a search field becomes unreachable without a mouse.&lt;/p&gt;
&lt;p&gt;One layout did regress. Instead of filing the full page, I removed blocks until only a float, a cleared heading, and six lines of CSS remained. That reduction changed the report from a screenshot of somebody else&amp;rsquo;s site into a local file that showed the bug every time.&lt;/p&gt;
&lt;p&gt;I kept the exact revision and compared the reduced page with the previous build. “Konqueror acted funny” is emotionally accurate and technically ornamental; a twelve-line attachment with a before-and-after result is useful.&lt;/p&gt;
&lt;p&gt;KHTML&amp;rsquo;s shared role raises the stakes. A rendering fix reaches Konqueror and any application embedding the part, while a regression travels just as efficiently. Small local pages make that shared behavior testable without depending on a live site changing underneath the report.&lt;/p&gt;
&lt;p&gt;The standards progress in 3.5 is visible, especially on layouts that used to need browser-specific nudges. The useful release behavior isn&amp;rsquo;t the badge, though; it&amp;rsquo;s rendering those pages more correctly without breaking forms, focus, and rough old HTML.&lt;/p&gt;
&lt;p&gt;My little page collection now lives beside the build scripts. It&amp;rsquo;s less glamorous than a browser shootout, but much better at explaining the next crooked heading.&lt;/p&gt;</description></item></channel></rss>