Files
stack/libs/go-libs/analytics/segment_test.go
791b4bc769 feat: Switch to monorepo (#21)
* feat: first commit

* feat: import wallet, fctl sdk and some stuff

* fix: make hooks enabled only if changes in the code

* feat: refine scripts

* chore: disable pre commit hooks

* chore: update payments

* feat: make all hooks pass

this has required modifications on almost each project

* git subrepo push services/webhooks

subrepo:
  subdir:   "services/webhooks"
  merged:   "ca5d19c5"
upstream:
  origin:   "webhooks"
  branch:   "main"
  commit:   "ca5d19c5"
git-subrepo:
  version:  "0.4.5"
  origin:   "ssh://[email protected]/ingydotnet/git-subrepo"
  commit:   "dbb99be"

* chore: push backport

* chore: backports

* chore: backports

* chore: backports

* chore: backports

* chore: backports

* chore: remove test code

* chore: backports

* fix: branch

* git subrepo push --branch=chore/backports --force services/fctl

subrepo:
  subdir:   "services/fctl"
  merged:   "0d98fdaa"
upstream:
  origin:   "fctl"
  branch:   "chore/backports"
  commit:   "0d98fdaa"
git-subrepo:
  version:  "0.4.5"
  origin:   "ssh://[email protected]/ingydotnet/git-subrepo"
  commit:   "dbb99be"

* feat(fctl): fix argument

* git subrepo push --branch=chore/backports --force services/fctl

subrepo:
  subdir:   "services/fctl"
  merged:   "5a7a41f9"
upstream:
  origin:   "fctl"
  branch:   "chore/backports"
  commit:   "5a7a41f9"
git-subrepo:
  version:  "0.4.5"
  origin:   "ssh://[email protected]/ingydotnet/git-subrepo"
  commit:   "dbb99be"

* feat: remove ledger

* git subrepo clone ledger services/ledger

subrepo:
  subdir:   "services/ledger"
  merged:   "ad57138a"
upstream:
  origin:   "ledger"
  branch:   "main"
  commit:   "ad57138a"
git-subrepo:
  version:  "0.4.5"
  origin:   "ssh://[email protected]/ingydotnet/git-subrepo"
  commit:   "dbb99be"

* feat(auth): fix dependencies

* chore: backports

* feat: remove ledger

* feat: add ledger

* feat: remove auth

* feat: fetch auth main

* feat: remove search

* feat: add search

* feat: remove submodules

* feat: reomve payments

* feat: add payments from main

* feat: add 'yarn install' before generate sdk

* feat: Update CI

* feat: remove fctl

* feat: add fctl

* chore: go mod tidy

* git subrepo push services/fctl

subrepo:
  subdir:   "services/fctl"
  merged:   "5d4c919"
upstream:
  origin:   "fctl"
  branch:   "main"
  commit:   "5d4c919"
git-subrepo:
  version:  "0.4.5"
  origin:   "ssh://[email protected]/ingydotnet/git-subrepo"
  commit:   "dbb99be"

* feat: add go-project-template

* feat: update go-project-template under new go libs

* git subrepo push libs/go-project-template

subrepo:
  subdir:   "libs/go-project-template"
  merged:   "40e49f0"
upstream:
  origin:   "go-project-template"
  branch:   "main"
  commit:   "40e49f0"
git-subrepo:
  version:  "0.4.5"
  origin:   "ssh://[email protected]/ingydotnet/git-subrepo"
  commit:   "dbb99be"

* fix: sdk hook

* feat: Update CI

* feat: Update CI

* feat: Update CI

* feat: Update CI

* feat: Update

* feat: CI Update

* feat: Clear CI

* feat: CI clear

* fee

* feat: CI

* feat: Update CI

* feat: Update CI

* feat: Desactivate release mode

* feat: Update CI

* feat: Update CI

* ci: upgrade

* feat: update go-libs

* feat(orchetration): init project

* git subrepo push libs/go-project-template

subrepo:
  subdir:   "libs/go-project-template"
  merged:   "cbead19"
upstream:
  origin:   "go-project-template"
  branch:   "main"
  commit:   "cbead19"
git-subrepo:
  version:  "0.4.5"
  origin:   "ssh://[email protected]/ingydotnet/git-subrepo"
  commit:   "dbb99be"

* fix: commitlint

* feat: little clean & fix pre-commit

* fix: for pre-commit

* ci: Improvement

* ci: Improvement

* ci: Improvement

* ci: Improvement

* ci: Improvement

* chore: add machine

* ci: Improvement

* ci: Improvement

* ci: Improvement

* ci: Improvement

* feat: Add all SDK

* ci: Improvement

* feat: Update taskfile & CI

* feat: Update taskfile & CI

* feat: List foliders in find

* feat: List foliders in find

* feat: List foliders in find

* feat: List foliders in find

* feat: List foliders in find

* feat: List foliders in find

* feat: Add GoBuild

* feat: Add GoBuild

* feat: Add GoBuild

* feat: Add GoBuild

* feat: Add GoBuild

* feat: Add GoBuild

* feat: Add GoBuild

* feat: Add GoBuild

* feat: Add GoBuild

* feat: Add GoBuild

* chore: Empty-Commit

* feat: Add GoBuild

* feat: Add GoBuild

* feat: Add GoBuild

* feat: Add GoBuild

* feat: Add GoBuild

* feat: Add GoBuild

* feat: Add GoBuild

* feat: Add GoBuild

* feat: Add GoBuild

* feat: Add GoBuild

* feat: Add GoBuild

* feat: Add GoBuild

* feat: Add GoBuild

* feat: Add GoBuild

* feat: big bang

* feat: big bang

* feat: big bang

* ci: Update

* ci: Add release

* ci: Update .goreleaser.yml

* feat(orchestration): first working version

* feat(operator): simplify

* feat(operator): factorize ingress, services, auth clients...

* feat(operator): remove resources

* fix: auth configuration causing pods reboot

* feat: Update gitpod configuration

* feat(gitpod): Add Garden

* feat(gitpod): Add rsync

* feat(gitpod): Add packages

* feat(gitpod): Add packages

* feat(gitpod): Optimize configuration

* feat(gitpod): restore default config

* feat(gitpod): Add port 80 & 443 on qemu

* feat(gitpod): Ignore .garden fodler

* feat(gitpod): Upgrade qemu

* feat: add 'stack' label on created objects

* feat: add taskfile operator to root taskfile

* feat(operator): add lint to taskfile

* feat(operator): add build.Dockerfile

* fix(operator): fix build.Dockerfile

* fix(operator): restore service names

* fix(operator): ingresses

* fix(operator): fix middlewares

* fix(operator): duplicate middlewares entries

* fix(operator): control ingress path prefix

* feat(operator): disable ingress on service if not specified in configuration

* fix(fctl): membership uri

* fix(orchestration): application/json content-type

* feat: wip

* fix: orchestration run ids

* fix: catch panic on workflow executions

Co-authored-by: Ragot Geoffrey <[email protected]>
Co-authored-by: Antoine Gelloz <[email protected]>
2023-01-25 13:41:59 +01:00

167 lines
3.5 KiB
Go

package analytics
import (
"bytes"
"context"
"encoding/json"
"errors"
"io"
"net/http"
"sync"
"testing"
"time"
"github.com/segmentio/analytics-go"
"github.com/stretchr/testify/require"
"go.uber.org/fx"
)
type transport func(*http.Request) (*http.Response, error)
func (fn transport) RoundTrip(req *http.Request) (*http.Response, error) {
return fn(req)
}
type Queue[ITEM any] struct {
mu sync.Mutex
items []ITEM
}
func (s *Queue[ITEM]) Get() (ret ITEM, ok bool) {
s.mu.Lock()
defer s.mu.Unlock()
if len(s.items) == 0 {
return
}
ret = s.items[0]
ok = true
if len(s.items) == 1 {
s.items = make([]ITEM, 0)
return
}
s.items = s.items[1:]
return
}
func (s *Queue[ITEM]) Put(i ITEM) *Queue[ITEM] {
s.mu.Lock()
defer s.mu.Unlock()
s.items = append(s.items, i)
return s
}
func (s *Queue[ITEM]) Empty() bool {
s.mu.Lock()
defer s.mu.Unlock()
return len(s.items) == 0
}
func NewQueue[ITEM any]() *Queue[ITEM] {
return &Queue[ITEM]{}
}
type segmentBatch struct {
Batch []analytics.Track `json:"batch"`
}
const (
interval = 10 * time.Millisecond
version = "100.0.0"
applicationId = "foo"
writeKey = "key"
)
var (
module = fx.Options(
fx.NopLogger,
NewHeartbeatModule(version, writeKey, interval),
fx.Replace(func() AppIdProvider {
return AppIdProviderFn(func(ctx context.Context) (string, error) {
return applicationId, nil
})
}),
fx.Supply(fx.Annotate(PropertiesEnricherFn(func(ctx context.Context, p analytics.Properties) error {
p.Set("foo", "bar")
return nil
}), fx.ResultTags(FXTagPropertiesEnrichers), fx.As(new(PropertiesEnricher)))),
)
)
func EventuallyQueueNotEmpty[ITEM any](t *testing.T, queue *Queue[ITEM]) {
require.Eventually(t, func() bool {
return !queue.Empty()
}, 10*interval, interval)
}
var emptyHttpResponse = &http.Response{
Body: io.NopCloser(bytes.NewReader([]byte{})),
StatusCode: http.StatusOK,
}
func newApp(module fx.Option, t transport) *fx.App {
return fx.New(module, fx.Replace(analytics.Config{
BatchSize: 1,
Transport: t,
}))
}
func withApp(t *testing.T, app *fx.App, fn func(t *testing.T)) {
require.NoError(t, app.Start(context.Background()))
defer func() {
require.NoError(t, app.Stop(context.Background()))
}()
fn(t)
}
func TestSegment(t *testing.T) {
t.Run("Nominal case", func(t *testing.T) {
queue := NewQueue[*http.Request]()
app := newApp(module, func(request *http.Request) (*http.Response, error) {
queue.Put(request)
return emptyHttpResponse, nil
})
withApp(t, app, func(t *testing.T) {
for i := 0; i < 10; i++ {
EventuallyQueueNotEmpty(t, queue)
request, ok := queue.Get()
require.True(t, ok)
username, password, ok := request.BasicAuth()
require.True(t, ok)
require.Equal(t, writeKey, username)
require.Empty(t, password)
batch := &segmentBatch{}
require.NoError(t, json.NewDecoder(request.Body).Decode(batch))
require.Len(t, batch.Batch, 1)
track := batch.Batch[0]
require.Equal(t, ApplicationStats, track.Event)
require.Equal(t, "bar", track.Properties["foo"])
}
})
})
t.Run("With error on the backend", func(t *testing.T) {
firstCall := true
queue := NewQueue[*http.Request]()
app := newApp(module, func(request *http.Request) (*http.Response, error) {
if firstCall {
firstCall = false
return nil, errors.New("error on the first try")
}
queue.Put(request)
return emptyHttpResponse, nil
})
withApp(t, app, func(t *testing.T) {
EventuallyQueueNotEmpty(t, queue)
_, ok := queue.Get()
require.True(t, ok)
})
})
}