Skip to content

Commit

Permalink
Add ingestion test
Browse files Browse the repository at this point in the history
  • Loading branch information
mna committed Sep 10, 2024
1 parent c12c198 commit fa62b4c
Show file tree
Hide file tree
Showing 2 changed files with 173 additions and 0 deletions.
5 changes: 5 additions & 0 deletions server/mdm/maintainedapps/ingest.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"net/url"
"os"
"path"
"strings"
"time"

"github.com/fleetdm/fleet/v4/pkg/fleethttp"
Expand Down Expand Up @@ -62,6 +63,10 @@ type ingester struct {
func (i ingester) ingest(ctx context.Context, apps []maintainedApp) error {
var g errgroup.Group

if !strings.HasSuffix(i.baseURL, "/") {
i.baseURL += "/"
}

client := fleethttp.NewClient(fleethttp.WithTimeout(10 * time.Second))

// run at most 3 concurrent requests to avoid overwhelming the brew API
Expand Down
168 changes: 168 additions & 0 deletions server/mdm/maintainedapps/ingest_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
package maintainedapps

import (
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"path"
"strings"
"testing"

"github.com/fleetdm/fleet/v4/server/fleet"
"github.com/fleetdm/fleet/v4/server/mock"
"github.com/go-kit/log"
"github.com/stretchr/testify/require"
)

func TestIngestValidations(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var cask brewCask

appToken := strings.TrimSuffix(path.Base(r.URL.Path), ".json")
switch appToken {
case "fail":
w.WriteHeader(http.StatusInternalServerError)
return

case "notfound":
w.WriteHeader(http.StatusNotFound)
return

case "noname":
cask = brewCask{
Token: appToken,
Name: nil,
URL: "https://example.com",
Version: "1.0",
}

case "emptyname":
cask = brewCask{
Token: appToken,
Name: []string{""},
URL: "https://example.com",
Version: "1.0",
}

case "notoken":
cask = brewCask{
Token: "",
Name: []string{appToken},
URL: "https://example.com",
Version: "1.0",
}

case "noversion":
cask = brewCask{
Token: appToken,
Name: []string{appToken},
URL: "https://example.com",
Version: "",
}

case "nourl":
cask = brewCask{
Token: appToken,
Name: []string{appToken},
URL: "",
Version: "1.0",
}

case "invalidurl":
cask = brewCask{
Token: appToken,
Name: []string{appToken},
URL: "https://\x00\x01\x02",
Version: "1.0",
}

case "ok":
cask = brewCask{
Token: appToken,
Name: []string{appToken},
URL: "https://example.com",
Version: "1.0",
}

default:
w.WriteHeader(http.StatusBadRequest)
t.Fatalf("unexpected app token %s", appToken)
}

err := json.NewEncoder(w).Encode(cask)
require.NoError(t, err)
}))
t.Cleanup(srv.Close)

ctx := context.Background()
ds := new(mock.Store)
ds.UpsertMaintainedAppFunc = func(ctx context.Context, app *fleet.MaintainedApp) error {
return nil
}

cases := []struct {
appToken string
wantErr string
upsertCalled bool
}{
{"fail", "brew API returned status 500", false},
{"notfound", "", false},
{"noname", "missing name for cask noname", false},
{"emptyname", "missing name for cask emptyname", false},
{"notoken", "missing token for cask notoken", false},
{"noversion", "missing version for cask noversion", false},
{"nourl", "missing URL for cask nourl", false},
{"invalidurl", "parse URL for cask invalidurl", false},
{"ok", "", true},
{"multi:ok", "", true},
{"multi:fail", "brew API returned status 500", true},
}
for _, c := range cases {
t.Run(c.appToken, func(t *testing.T) {
i := ingester{baseURL: srv.URL, ds: ds, logger: log.NewNopLogger()}

var apps []maintainedApp
var ignoreDSCheck bool
if strings.HasPrefix(c.appToken, "multi:") {
token := strings.TrimPrefix(c.appToken, "multi:")
if token == "fail" {
// do not check the DS call, as it may or may not have happened depending
// on the concurrent execution
ignoreDSCheck = true
// send 3 ok, one fail
apps = []maintainedApp{
{Identifier: "ok", BundleIdentifier: "abc", InstallerFormat: "pkg"},
{Identifier: "fail", BundleIdentifier: "def", InstallerFormat: "pkg"},
{Identifier: "ok", BundleIdentifier: "ghi", InstallerFormat: "pkg"},
{Identifier: "ok", BundleIdentifier: "klm", InstallerFormat: "pkg"},
}
} else {
// send 4 apps with ok
apps = []maintainedApp{
{Identifier: token, BundleIdentifier: "abc", InstallerFormat: "pkg"},
{Identifier: token, BundleIdentifier: "def", InstallerFormat: "pkg"},
{Identifier: token, BundleIdentifier: "ghi", InstallerFormat: "pkg"},
{Identifier: token, BundleIdentifier: "klm", InstallerFormat: "pkg"},
}
}
} else {
apps = []maintainedApp{
{Identifier: c.appToken, BundleIdentifier: "abc", InstallerFormat: "pkg"},
}
}

err := i.ingest(ctx, apps)
if c.wantErr == "" {
require.NoError(t, err)
} else {
require.ErrorContains(t, err, c.wantErr)
}

if !ignoreDSCheck {
require.Equal(t, c.upsertCalled, ds.UpsertMaintainedAppFuncInvoked)
}
ds.UpsertMaintainedAppFuncInvoked = false
})
}
}

0 comments on commit fa62b4c

Please sign in to comment.