mirror of
https://github.com/mjl-/mox.git
synced 2025-07-10 07:54:40 +03:00
mox!
This commit is contained in:
152
updates/updates_test.go
Normal file
152
updates/updates_test.go
Normal file
@ -0,0 +1,152 @@
|
||||
package updates
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ed25519"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/mjl-/mox/dns"
|
||||
)
|
||||
|
||||
func TestUpdates(t *testing.T) {
|
||||
resolver := dns.MockResolver{
|
||||
TXT: map[string][]string{
|
||||
"_updates.mox.example.": {"v=UPDATES0; l=v0.0.1"},
|
||||
"_updates.one.example.": {"other", "v=UPDATES0; l=v0.0.1-rc1"},
|
||||
"_updates.dup.example.": {"v=UPDATES0; l=v0.0.1", "v=UPDATES0; l=v0.0.1"},
|
||||
"_updates.other.example.": {"other"},
|
||||
"_updates.malformed.example.": {"v=UPDATES0; l=bogus"},
|
||||
"_updates.malformed2.example.": {"v=UPDATES0; bogus"},
|
||||
"_updates.malformed3.example.": {"v=UPDATES0; l=v0.0.1; l=v0.0.1"},
|
||||
"_updates.temperror.example.": {"v=UPDATES0; l=v0.0.1"},
|
||||
"_updates.unknown.example.": {"v=UPDATES0; l=v0.0.1; unknown=ok"},
|
||||
},
|
||||
Fail: map[dns.Mockreq]struct{}{
|
||||
{Type: "txt", Name: "_updates.temperror.example."}: {},
|
||||
},
|
||||
}
|
||||
|
||||
lookup := func(dom string, expVersion string, expRecord *Record, expErr error) {
|
||||
t.Helper()
|
||||
|
||||
d, _ := dns.ParseDomain(dom)
|
||||
expv, _ := ParseVersion(expVersion)
|
||||
|
||||
version, record, err := Lookup(context.Background(), resolver, d)
|
||||
if (err == nil) != (expErr == nil) || err != nil && !errors.Is(err, expErr) {
|
||||
t.Fatalf("lookup: got err %v, expected %v", err, expErr)
|
||||
}
|
||||
if version != expv || !reflect.DeepEqual(record, expRecord) {
|
||||
t.Fatalf("lookup: got version %v, record %#v, expected %v %#v", version, record, expv, expRecord)
|
||||
}
|
||||
}
|
||||
|
||||
lookup("mox.example", "v0.0.1", &Record{Version: "UPDATES0", Latest: Version{0, 0, 1}}, nil)
|
||||
lookup("one.example", "v0.0.1", &Record{Version: "UPDATES0", Latest: Version{0, 0, 1}}, nil)
|
||||
lookup("absent.example", "", nil, ErrNoRecord)
|
||||
lookup("dup.example", "", nil, ErrMultipleRecords)
|
||||
lookup("other.example", "", nil, ErrNoRecord)
|
||||
lookup("malformed.example", "", nil, ErrRecordSyntax)
|
||||
lookup("malformed2.example", "", nil, ErrRecordSyntax)
|
||||
lookup("malformed3.example", "", nil, ErrRecordSyntax)
|
||||
lookup("temperror.example", "", nil, ErrDNS)
|
||||
lookup("unknown.example", "v0.0.1", &Record{Version: "UPDATES0", Latest: Version{0, 0, 1}}, nil)
|
||||
|
||||
seed := make([]byte, ed25519.SeedSize)
|
||||
priv := ed25519.NewKeyFromSeed(seed)
|
||||
pub := []byte(priv.Public().(ed25519.PublicKey))
|
||||
changelog := Changelog{
|
||||
Changes: []Change{
|
||||
{
|
||||
PubKey: pub,
|
||||
Sig: ed25519.Sign(priv, []byte("test")),
|
||||
Text: "test",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
fetch := func(baseURL string, version Version, status int, pubKey []byte, expChangelog *Changelog, expErr error) {
|
||||
t.Helper()
|
||||
|
||||
mux := &http.ServeMux{}
|
||||
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
if status == 0 {
|
||||
panic("bad serve")
|
||||
}
|
||||
w.WriteHeader(status)
|
||||
err := json.NewEncoder(w).Encode(changelog)
|
||||
if err != nil {
|
||||
t.Fatalf("encode changelog: %v", err)
|
||||
}
|
||||
})
|
||||
s := httptest.NewUnstartedServer(mux)
|
||||
s.Config.ErrorLog = log.New(io.Discard, "", 0)
|
||||
s.Start()
|
||||
defer s.Close()
|
||||
if baseURL == "" {
|
||||
baseURL = s.URL
|
||||
}
|
||||
|
||||
changelog, err := FetchChangelog(context.Background(), baseURL, version, pubKey)
|
||||
if (err == nil) != (expErr == nil) || err != nil && !errors.Is(err, expErr) {
|
||||
t.Fatalf("fetch changelog: got err %v, expected %v", err, expErr)
|
||||
}
|
||||
if !reflect.DeepEqual(changelog, expChangelog) {
|
||||
t.Fatalf("fetch changelog: got changelog %v, expected %v", changelog, expChangelog)
|
||||
}
|
||||
}
|
||||
|
||||
fetch("", Version{}, 200, pub, &changelog, nil)
|
||||
fetch("", Version{1, 1, 1}, 200, pub, &changelog, nil)
|
||||
fetch("", Version{}, 200, make([]byte, ed25519.PublicKeySize), nil, ErrChangelogFetch) // Invalid public key.
|
||||
changelog.Changes[0].Text = "bad"
|
||||
fetch("", Version{}, 200, pub, nil, ErrChangelogFetch) // Invalid signature.
|
||||
changelog.Changes[0].Text = "test"
|
||||
fetch("", Version{}, 404, pub, nil, ErrChangelogFetch)
|
||||
fetch("", Version{}, 503, pub, nil, ErrChangelogFetch)
|
||||
fetch("", Version{}, 0, pub, nil, ErrChangelogFetch)
|
||||
fetch("bogusurl", Version{}, 200, pub, nil, ErrChangelogFetch)
|
||||
|
||||
check := func(dom string, base Version, baseURL string, status int, pubKey []byte, expVersion Version, expRecord *Record, expChangelog *Changelog, expErr error) {
|
||||
t.Helper()
|
||||
|
||||
mux := &http.ServeMux{}
|
||||
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
if status == 0 {
|
||||
panic("bad serve")
|
||||
}
|
||||
w.WriteHeader(status)
|
||||
err := json.NewEncoder(w).Encode(changelog)
|
||||
if err != nil {
|
||||
t.Fatalf("encode changelog: %v", err)
|
||||
}
|
||||
})
|
||||
s := httptest.NewUnstartedServer(mux)
|
||||
s.Config.ErrorLog = log.New(io.Discard, "", 0)
|
||||
s.Start()
|
||||
defer s.Close()
|
||||
if baseURL == "" {
|
||||
baseURL = s.URL
|
||||
}
|
||||
|
||||
version, record, changelog, err := Check(context.Background(), resolver, dns.Domain{ASCII: dom}, base, baseURL, pubKey)
|
||||
if (err == nil) != (expErr == nil) || err != nil && !errors.Is(err, expErr) {
|
||||
t.Fatalf("check: got err %v, expected %v", err, expErr)
|
||||
}
|
||||
if version != expVersion || !reflect.DeepEqual(record, expRecord) || !reflect.DeepEqual(changelog, expChangelog) {
|
||||
t.Fatalf("check: got version %v, record %#v, changelog %v, expected %v %#v %v", version, record, changelog, expVersion, expRecord, expChangelog)
|
||||
}
|
||||
}
|
||||
|
||||
check("mox.example", Version{0, 0, 1}, "", 0, pub, Version{0, 0, 1}, &Record{Version: "UPDATES0", Latest: Version{0, 0, 1}}, nil, nil)
|
||||
check("mox.example", Version{0, 0, 0}, "", 200, pub, Version{0, 0, 1}, &Record{Version: "UPDATES0", Latest: Version{0, 0, 1}}, &changelog, nil)
|
||||
check("mox.example", Version{0, 0, 0}, "", 0, pub, Version{0, 0, 1}, &Record{Version: "UPDATES0", Latest: Version{0, 0, 1}}, nil, ErrChangelogFetch)
|
||||
check("absent.example", Version{0, 0, 1}, "", 200, pub, Version{}, nil, nil, ErrNoRecord)
|
||||
}
|
Reference in New Issue
Block a user