You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gosuv/vendor/github.com/equinox-io/equinox/sdk_test.go

184 lines
4.2 KiB

package equinox
import (
"bytes"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/http/httptest"
"os"
"testing"
"time"
"github.com/equinox-io/equinox/proto"
)
const fakeAppID = "fake_app_id"
var (
fakeBinary = []byte{0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1}
newFakeBinary = []byte{0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2}
ts *httptest.Server
key *ecdsa.PrivateKey
sha string
newSHA string
signature string
)
func init() {
shaBytes := sha256.Sum256(fakeBinary)
sha = hex.EncodeToString(shaBytes[:])
newSHABytes := sha256.Sum256(newFakeBinary)
newSHA = hex.EncodeToString(newSHABytes[:])
var err error
key, err = ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
if err != nil {
panic(fmt.Sprintf("Failed to generate ecdsa key: %v", err))
}
sig, err := key.Sign(rand.Reader, newSHABytes[:], nil)
if err != nil {
panic(fmt.Sprintf("Failed to sign new binary: %v", err))
}
signature = hex.EncodeToString(sig)
}
func TestNotAvailable(t *testing.T) {
opts := setup(t, "TestNotAvailable", proto.Response{
Available: false,
})
defer cleanup(opts)
_, err := Check(fakeAppID, opts)
if err != NotAvailableErr {
t.Fatalf("Expected not available error, got: %v", err)
}
}
func TestEndToEnd(t *testing.T) {
opts := setup(t, "TestEndtoEnd", proto.Response{
Available: true,
Release: proto.Release{
Version: "0.1.2.3",
Title: "Release Title",
Description: "Release Description",
CreateDate: time.Now(),
},
Checksum: newSHA,
Signature: signature,
})
defer cleanup(opts)
resp, err := Check(fakeAppID, opts)
if err != nil {
t.Fatalf("Failed check: %v", err)
}
err = resp.Apply()
if err != nil {
t.Fatalf("Failed apply: %v", err)
}
buf, err := ioutil.ReadFile(opts.TargetPath)
if err != nil {
t.Fatalf("Failed to read file: %v", err)
}
if !bytes.Equal(buf, newFakeBinary) {
t.Fatalf("Binary did not update to new expected value. Got %v, expected %v", buf, newFakeBinary)
}
}
func TestInvalidPatch(t *testing.T) {
opts := setup(t, "TestInavlidPatch", proto.Response{
Available: true,
Release: proto.Release{
Version: "0.1.2.3",
Title: "Release Title",
Description: "Release Description",
CreateDate: time.Now(),
},
DownloadURL: "bad-request",
Checksum: newSHA,
Signature: signature,
Patch: proto.PatchBSDiff,
})
defer cleanup(opts)
resp, err := Check(fakeAppID, opts)
if err != nil {
t.Fatalf("Failed check: %v", err)
}
err = resp.Apply()
if err == nil {
t.Fatalf("Apply succeeded")
}
if err.Error() != "error downloading patch: bad-request" {
t.Fatalf("Expected a different error message: %s", err)
}
}
func setup(t *testing.T, name string, resp proto.Response) Options {
checkUserAgent := func(req *http.Request) {
if req.Header.Get("User-Agent") != userAgent {
t.Errorf("Expected user agent to be %s, not %s", userAgent, req.Header.Get("User-Agent"))
}
}
mux := http.NewServeMux()
mux.HandleFunc("/check", func(w http.ResponseWriter, r *http.Request) {
checkUserAgent(r)
var req proto.Request
err := json.NewDecoder(r.Body).Decode(&req)
if err != nil {
t.Fatalf("Failed to decode proto request: %v", err)
}
if resp.Available {
if req.AppID != fakeAppID {
t.Fatalf("Unexpected app ID. Got %v, expected %v", err)
}
if req.CurrentSHA256 != sha {
t.Fatalf("Unexpected request SHA: %v", sha)
}
}
json.NewEncoder(w).Encode(resp)
})
// Keying off the download URL may not be the best idea...
if resp.DownloadURL == "bad-request" {
mux.HandleFunc("/bin", func(w http.ResponseWriter, r *http.Request) {
checkUserAgent(r)
http.Error(w, "bad-request", http.StatusBadRequest)
})
} else {
mux.HandleFunc("/bin", func(w http.ResponseWriter, r *http.Request) {
checkUserAgent(r)
w.Write(newFakeBinary)
})
}
ts = httptest.NewServer(mux)
resp.DownloadURL = ts.URL + "/bin"
var opts Options
opts.CheckURL = ts.URL + "/check"
opts.PublicKey = key.Public()
if name != "" {
opts.TargetPath = name
ioutil.WriteFile(name, fakeBinary, 0644)
}
return opts
}
func cleanup(opts Options) {
if opts.TargetPath != "" {
os.Remove(opts.TargetPath)
}
ts.Close()
}