Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

alg/ensemble: test results unchanged #101

Merged
merged 5 commits into from
May 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions alg/ensemble/ensemble_test.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,80 @@
package ensemble

import (
"encoding/json"
"io/ioutil"
"reflect"
"testing"

"github.com/mmcloughlin/addchain/alg/exec"
"github.com/mmcloughlin/addchain/internal/results"
"github.com/mmcloughlin/addchain/internal/test"
)

// TestResults confirms that chain lengths from every ensemble algorithm remain
// unchanged. This is intended to provide confidence when making risky changes
// or refactors. The results package has its own similar test, but this is
// focussed on verifying that the best recorded result is still the same.
//
// The test uses the "golden test" technique, where we dump
// known-good results into golden files and later verify that we get the same
// result.
func TestResults(t *testing.T) {
t.Parallel()
test.RequireLong(t)

as := Ensemble()
for _, c := range results.Results {
c := c // scopelint
t.Run(c.Slug, func(t *testing.T) {
t.Parallel()

// Execute.
ex := exec.NewParallel()
rs := ex.Execute(c.Target(), as)

// Summarize results in map from algorithm name to program length.
got := map[string]int{}
for _, r := range rs {
if r.Err != nil {
t.Fatalf("error with %s: %v", r.Algorithm, r.Err)
}
got[r.Algorithm.String()] = len(r.Program)
}

// If golden, write out results data file.
filename := test.GoldenName(c.Slug)

if test.Golden() {
t.Logf("writing golden file %s", filename)
b, err := json.MarshalIndent(got, "", "\t")
if err != nil {
t.Fatal(err)
}
if err := ioutil.WriteFile(filename, b, 0644); err != nil {
t.Fatalf("write golden file: %v", err)
}
}

// Load golden file.
b, err := ioutil.ReadFile(filename)
if err != nil {
t.Fatalf("read golden file: %v", err)
}

var expect map[string]int
if err := json.Unmarshal(b, &expect); err != nil {
t.Fatal(err)
}

// Verify equal.
if !reflect.DeepEqual(expect, got) {
t.Fatal("results do not match golden file")
}
})
}
}

func BenchmarkResults(b *testing.B) {
as := Ensemble()
for _, c := range results.Results {
Expand Down
202 changes: 202 additions & 0 deletions alg/ensemble/testdata/curve25519_field.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
{
"opt(dictionary(hybrid(2,0),continued_fractions(binary)))": 381,
"opt(dictionary(hybrid(2,0),continued_fractions(co_binary)))": 381,
"opt(dictionary(hybrid(2,0),continued_fractions(dichotomic)))": 268,
"opt(dictionary(hybrid(2,0),heuristic(use_first(halving,approximation))))": 381,
"opt(dictionary(hybrid(2,0),heuristic(use_first(halving,delta_largest))))": 502,
"opt(dictionary(hybrid(2,16),continued_fractions(binary)))": 276,
"opt(dictionary(hybrid(2,16),continued_fractions(co_binary)))": 276,
"opt(dictionary(hybrid(2,16),continued_fractions(dichotomic)))": 276,
"opt(dictionary(hybrid(2,16),heuristic(use_first(halving,approximation))))": 276,
"opt(dictionary(hybrid(2,16),heuristic(use_first(halving,delta_largest))))": 276,
"opt(dictionary(hybrid(2,32),continued_fractions(binary)))": 271,
"opt(dictionary(hybrid(2,32),continued_fractions(co_binary)))": 271,
"opt(dictionary(hybrid(2,32),continued_fractions(dichotomic)))": 270,
"opt(dictionary(hybrid(2,32),heuristic(use_first(halving,approximation))))": 271,
"opt(dictionary(hybrid(2,32),heuristic(use_first(halving,delta_largest))))": 281,
"opt(dictionary(hybrid(2,64),continued_fractions(binary)))": 272,
"opt(dictionary(hybrid(2,64),continued_fractions(co_binary)))": 272,
"opt(dictionary(hybrid(2,64),continued_fractions(dichotomic)))": 268,
"opt(dictionary(hybrid(2,64),heuristic(use_first(halving,approximation))))": 272,
"opt(dictionary(hybrid(2,64),heuristic(use_first(halving,delta_largest))))": 310,
"opt(dictionary(hybrid(3,0),continued_fractions(binary)))": 381,
"opt(dictionary(hybrid(3,0),continued_fractions(co_binary)))": 381,
"opt(dictionary(hybrid(3,0),continued_fractions(dichotomic)))": 268,
"opt(dictionary(hybrid(3,0),heuristic(use_first(halving,approximation))))": 341,
"opt(dictionary(hybrid(3,0),heuristic(use_first(halving,delta_largest))))": 503,
"opt(dictionary(hybrid(3,16),continued_fractions(binary)))": 276,
"opt(dictionary(hybrid(3,16),continued_fractions(co_binary)))": 276,
"opt(dictionary(hybrid(3,16),continued_fractions(dichotomic)))": 276,
"opt(dictionary(hybrid(3,16),heuristic(use_first(halving,approximation))))": 277,
"opt(dictionary(hybrid(3,16),heuristic(use_first(halving,delta_largest))))": 277,
"opt(dictionary(hybrid(3,32),continued_fractions(binary)))": 271,
"opt(dictionary(hybrid(3,32),continued_fractions(co_binary)))": 271,
"opt(dictionary(hybrid(3,32),continued_fractions(dichotomic)))": 270,
"opt(dictionary(hybrid(3,32),heuristic(use_first(halving,approximation))))": 271,
"opt(dictionary(hybrid(3,32),heuristic(use_first(halving,delta_largest))))": 284,
"opt(dictionary(hybrid(3,64),continued_fractions(binary)))": 272,
"opt(dictionary(hybrid(3,64),continued_fractions(co_binary)))": 272,
"opt(dictionary(hybrid(3,64),continued_fractions(dichotomic)))": 268,
"opt(dictionary(hybrid(3,64),heuristic(use_first(halving,approximation))))": 273,
"opt(dictionary(hybrid(3,64),heuristic(use_first(halving,delta_largest))))": 311,
"opt(dictionary(hybrid(4,0),continued_fractions(binary)))": 381,
"opt(dictionary(hybrid(4,0),continued_fractions(co_binary)))": 381,
"opt(dictionary(hybrid(4,0),continued_fractions(dichotomic)))": 277,
"opt(dictionary(hybrid(4,0),heuristic(use_first(halving,approximation))))": 320,
"opt(dictionary(hybrid(4,0),heuristic(use_first(halving,delta_largest))))": 502,
"opt(dictionary(hybrid(4,16),continued_fractions(binary)))": 276,
"opt(dictionary(hybrid(4,16),continued_fractions(co_binary)))": 276,
"opt(dictionary(hybrid(4,16),continued_fractions(dichotomic)))": 276,
"opt(dictionary(hybrid(4,16),heuristic(use_first(halving,approximation))))": 276,
"opt(dictionary(hybrid(4,16),heuristic(use_first(halving,delta_largest))))": 276,
"opt(dictionary(hybrid(4,32),continued_fractions(binary)))": 271,
"opt(dictionary(hybrid(4,32),continued_fractions(co_binary)))": 271,
"opt(dictionary(hybrid(4,32),continued_fractions(dichotomic)))": 270,
"opt(dictionary(hybrid(4,32),heuristic(use_first(halving,approximation))))": 271,
"opt(dictionary(hybrid(4,32),heuristic(use_first(halving,delta_largest))))": 282,
"opt(dictionary(hybrid(4,64),continued_fractions(binary)))": 272,
"opt(dictionary(hybrid(4,64),continued_fractions(co_binary)))": 272,
"opt(dictionary(hybrid(4,64),continued_fractions(dichotomic)))": 268,
"opt(dictionary(hybrid(4,64),heuristic(use_first(halving,approximation))))": 272,
"opt(dictionary(hybrid(4,64),heuristic(use_first(halving,delta_largest))))": 310,
"opt(dictionary(hybrid(5,0),continued_fractions(binary)))": 381,
"opt(dictionary(hybrid(5,0),continued_fractions(co_binary)))": 381,
"opt(dictionary(hybrid(5,0),continued_fractions(dichotomic)))": 277,
"opt(dictionary(hybrid(5,0),heuristic(use_first(halving,approximation))))": 320,
"opt(dictionary(hybrid(5,0),heuristic(use_first(halving,delta_largest))))": 502,
"opt(dictionary(hybrid(5,16),continued_fractions(binary)))": 276,
"opt(dictionary(hybrid(5,16),continued_fractions(co_binary)))": 276,
"opt(dictionary(hybrid(5,16),continued_fractions(dichotomic)))": 276,
"opt(dictionary(hybrid(5,16),heuristic(use_first(halving,approximation))))": 276,
"opt(dictionary(hybrid(5,16),heuristic(use_first(halving,delta_largest))))": 276,
"opt(dictionary(hybrid(5,32),continued_fractions(binary)))": 271,
"opt(dictionary(hybrid(5,32),continued_fractions(co_binary)))": 271,
"opt(dictionary(hybrid(5,32),continued_fractions(dichotomic)))": 270,
"opt(dictionary(hybrid(5,32),heuristic(use_first(halving,approximation))))": 271,
"opt(dictionary(hybrid(5,32),heuristic(use_first(halving,delta_largest))))": 282,
"opt(dictionary(hybrid(5,64),continued_fractions(binary)))": 272,
"opt(dictionary(hybrid(5,64),continued_fractions(co_binary)))": 272,
"opt(dictionary(hybrid(5,64),continued_fractions(dichotomic)))": 268,
"opt(dictionary(hybrid(5,64),heuristic(use_first(halving,approximation))))": 272,
"opt(dictionary(hybrid(5,64),heuristic(use_first(halving,delta_largest))))": 310,
"opt(dictionary(hybrid(6,0),continued_fractions(binary)))": 381,
"opt(dictionary(hybrid(6,0),continued_fractions(co_binary)))": 381,
"opt(dictionary(hybrid(6,0),continued_fractions(dichotomic)))": 277,
"opt(dictionary(hybrid(6,0),heuristic(use_first(halving,approximation))))": 320,
"opt(dictionary(hybrid(6,0),heuristic(use_first(halving,delta_largest))))": 502,
"opt(dictionary(hybrid(6,16),continued_fractions(binary)))": 276,
"opt(dictionary(hybrid(6,16),continued_fractions(co_binary)))": 276,
"opt(dictionary(hybrid(6,16),continued_fractions(dichotomic)))": 276,
"opt(dictionary(hybrid(6,16),heuristic(use_first(halving,approximation))))": 276,
"opt(dictionary(hybrid(6,16),heuristic(use_first(halving,delta_largest))))": 276,
"opt(dictionary(hybrid(6,32),continued_fractions(binary)))": 271,
"opt(dictionary(hybrid(6,32),continued_fractions(co_binary)))": 271,
"opt(dictionary(hybrid(6,32),continued_fractions(dichotomic)))": 270,
"opt(dictionary(hybrid(6,32),heuristic(use_first(halving,approximation))))": 271,
"opt(dictionary(hybrid(6,32),heuristic(use_first(halving,delta_largest))))": 282,
"opt(dictionary(hybrid(6,64),continued_fractions(binary)))": 272,
"opt(dictionary(hybrid(6,64),continued_fractions(co_binary)))": 272,
"opt(dictionary(hybrid(6,64),continued_fractions(dichotomic)))": 268,
"opt(dictionary(hybrid(6,64),heuristic(use_first(halving,approximation))))": 272,
"opt(dictionary(hybrid(6,64),heuristic(use_first(halving,delta_largest))))": 310,
"opt(dictionary(hybrid(7,0),continued_fractions(binary)))": 381,
"opt(dictionary(hybrid(7,0),continued_fractions(co_binary)))": 381,
"opt(dictionary(hybrid(7,0),continued_fractions(dichotomic)))": 277,
"opt(dictionary(hybrid(7,0),heuristic(use_first(halving,approximation))))": 320,
"opt(dictionary(hybrid(7,0),heuristic(use_first(halving,delta_largest))))": 502,
"opt(dictionary(hybrid(7,16),continued_fractions(binary)))": 276,
"opt(dictionary(hybrid(7,16),continued_fractions(co_binary)))": 276,
"opt(dictionary(hybrid(7,16),continued_fractions(dichotomic)))": 276,
"opt(dictionary(hybrid(7,16),heuristic(use_first(halving,approximation))))": 276,
"opt(dictionary(hybrid(7,16),heuristic(use_first(halving,delta_largest))))": 276,
"opt(dictionary(hybrid(7,32),continued_fractions(binary)))": 271,
"opt(dictionary(hybrid(7,32),continued_fractions(co_binary)))": 271,
"opt(dictionary(hybrid(7,32),continued_fractions(dichotomic)))": 270,
"opt(dictionary(hybrid(7,32),heuristic(use_first(halving,approximation))))": 271,
"opt(dictionary(hybrid(7,32),heuristic(use_first(halving,delta_largest))))": 282,
"opt(dictionary(hybrid(7,64),continued_fractions(binary)))": 272,
"opt(dictionary(hybrid(7,64),continued_fractions(co_binary)))": 272,
"opt(dictionary(hybrid(7,64),continued_fractions(dichotomic)))": 268,
"opt(dictionary(hybrid(7,64),heuristic(use_first(halving,approximation))))": 272,
"opt(dictionary(hybrid(7,64),heuristic(use_first(halving,delta_largest))))": 310,
"opt(dictionary(hybrid(8,0),continued_fractions(binary)))": 381,
"opt(dictionary(hybrid(8,0),continued_fractions(co_binary)))": 381,
"opt(dictionary(hybrid(8,0),continued_fractions(dichotomic)))": 277,
"opt(dictionary(hybrid(8,0),heuristic(use_first(halving,approximation))))": 320,
"opt(dictionary(hybrid(8,0),heuristic(use_first(halving,delta_largest))))": 502,
"opt(dictionary(hybrid(8,16),continued_fractions(binary)))": 276,
"opt(dictionary(hybrid(8,16),continued_fractions(co_binary)))": 276,
"opt(dictionary(hybrid(8,16),continued_fractions(dichotomic)))": 276,
"opt(dictionary(hybrid(8,16),heuristic(use_first(halving,approximation))))": 276,
"opt(dictionary(hybrid(8,16),heuristic(use_first(halving,delta_largest))))": 276,
"opt(dictionary(hybrid(8,32),continued_fractions(binary)))": 271,
"opt(dictionary(hybrid(8,32),continued_fractions(co_binary)))": 271,
"opt(dictionary(hybrid(8,32),continued_fractions(dichotomic)))": 270,
"opt(dictionary(hybrid(8,32),heuristic(use_first(halving,approximation))))": 271,
"opt(dictionary(hybrid(8,32),heuristic(use_first(halving,delta_largest))))": 282,
"opt(dictionary(hybrid(8,64),continued_fractions(binary)))": 272,
"opt(dictionary(hybrid(8,64),continued_fractions(co_binary)))": 272,
"opt(dictionary(hybrid(8,64),continued_fractions(dichotomic)))": 268,
"opt(dictionary(hybrid(8,64),heuristic(use_first(halving,approximation))))": 272,
"opt(dictionary(hybrid(8,64),heuristic(use_first(halving,delta_largest))))": 310,
"opt(dictionary(run_length(0),continued_fractions(binary)))": 381,
"opt(dictionary(run_length(0),continued_fractions(co_binary)))": 381,
"opt(dictionary(run_length(0),continued_fractions(dichotomic)))": 268,
"opt(dictionary(run_length(0),heuristic(use_first(halving,approximation))))": 381,
"opt(dictionary(run_length(0),heuristic(use_first(halving,delta_largest))))": 502,
"opt(dictionary(run_length(128),continued_fractions(binary)))": 281,
"opt(dictionary(run_length(128),continued_fractions(co_binary)))": 281,
"opt(dictionary(run_length(128),continued_fractions(dichotomic)))": 267,
"opt(dictionary(run_length(128),heuristic(use_first(halving,approximation))))": 281,
"opt(dictionary(run_length(128),heuristic(use_first(halving,delta_largest))))": 371,
"opt(dictionary(run_length(16),continued_fractions(binary)))": 276,
"opt(dictionary(run_length(16),continued_fractions(co_binary)))": 276,
"opt(dictionary(run_length(16),continued_fractions(dichotomic)))": 276,
"opt(dictionary(run_length(16),heuristic(use_first(halving,approximation))))": 276,
"opt(dictionary(run_length(16),heuristic(use_first(halving,delta_largest))))": 276,
"opt(dictionary(run_length(32),continued_fractions(binary)))": 271,
"opt(dictionary(run_length(32),continued_fractions(co_binary)))": 271,
"opt(dictionary(run_length(32),continued_fractions(dichotomic)))": 270,
"opt(dictionary(run_length(32),heuristic(use_first(halving,approximation))))": 271,
"opt(dictionary(run_length(32),heuristic(use_first(halving,delta_largest))))": 281,
"opt(dictionary(run_length(64),continued_fractions(binary)))": 272,
"opt(dictionary(run_length(64),continued_fractions(co_binary)))": 272,
"opt(dictionary(run_length(64),continued_fractions(dichotomic)))": 268,
"opt(dictionary(run_length(64),heuristic(use_first(halving,approximation))))": 272,
"opt(dictionary(run_length(64),heuristic(use_first(halving,delta_largest))))": 310,
"opt(dictionary(sliding_window(128),continued_fractions(binary)))": 320,
"opt(dictionary(sliding_window(128),continued_fractions(co_binary)))": 320,
"opt(dictionary(sliding_window(128),continued_fractions(dichotomic)))": 279,
"opt(dictionary(sliding_window(128),heuristic(use_first(halving,approximation))))": 287,
"opt(dictionary(sliding_window(128),heuristic(use_first(halving,delta_largest))))": 380,
"opt(dictionary(sliding_window(16),continued_fractions(binary)))": 279,
"opt(dictionary(sliding_window(16),continued_fractions(co_binary)))": 279,
"opt(dictionary(sliding_window(16),continued_fractions(dichotomic)))": 277,
"opt(dictionary(sliding_window(16),heuristic(use_first(halving,approximation))))": 276,
"opt(dictionary(sliding_window(16),heuristic(use_first(halving,delta_largest))))": 280,
"opt(dictionary(sliding_window(32),continued_fractions(binary)))": 278,
"opt(dictionary(sliding_window(32),continued_fractions(co_binary)))": 278,
"opt(dictionary(sliding_window(32),continued_fractions(dichotomic)))": 276,
"opt(dictionary(sliding_window(32),heuristic(use_first(halving,approximation))))": 273,
"opt(dictionary(sliding_window(32),heuristic(use_first(halving,delta_largest))))": 290,
"opt(dictionary(sliding_window(4),continued_fractions(binary)))": 320,
"opt(dictionary(sliding_window(4),continued_fractions(co_binary)))": 320,
"opt(dictionary(sliding_window(4),continued_fractions(dichotomic)))": 320,
"opt(dictionary(sliding_window(4),heuristic(use_first(halving,approximation))))": 320,
"opt(dictionary(sliding_window(4),heuristic(use_first(halving,delta_largest))))": 320,
"opt(dictionary(sliding_window(64),continued_fractions(binary)))": 293,
"opt(dictionary(sliding_window(64),continued_fractions(co_binary)))": 293,
"opt(dictionary(sliding_window(64),continued_fractions(dichotomic)))": 276,
"opt(dictionary(sliding_window(64),heuristic(use_first(halving,approximation))))": 277,
"opt(dictionary(sliding_window(64),heuristic(use_first(halving,delta_largest))))": 318,
"opt(dictionary(sliding_window(8),continued_fractions(binary)))": 290,
"opt(dictionary(sliding_window(8),continued_fractions(co_binary)))": 290,
"opt(dictionary(sliding_window(8),continued_fractions(dichotomic)))": 290,
"opt(dictionary(sliding_window(8),heuristic(use_first(halving,approximation))))": 291,
"opt(dictionary(sliding_window(8),heuristic(use_first(halving,delta_largest))))": 291,
"opt(runs(continued_fractions(binary)))": 268,
"opt(runs(continued_fractions(co_binary)))": 268,
"opt(runs(continued_fractions(dichotomic)))": 266,
"opt(runs(heuristic(use_first(halving,approximation))))": 268,
"opt(runs(heuristic(use_first(halving,delta_largest))))": 270
}
Loading