Ctrl K
ComunidadGuías…

internal/repository/rollout_activation_test.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
// Activation-time invariants of per-update rollouts: a rollout's control_update_id is
// captured at insert time but only goes live at MarkUpdateAsChecked, one bundle upload later.
// Needs a real Postgres and skips without TEST_DATABASE_URL:
//
//	docker run -d --name eoo-pg -e POSTGRES_PASSWORD=test -p 55432:5432 postgres:16-alpine
//	TEST_DATABASE_URL="postgres://postgres:test@localhost:55432/postgres?sslmode=disable" go test ./internal/store/
package repository_test

import (
	"context"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

// TestRolloutActivationRejectsStaleControl verifies a rollout must not activate with
// the control it captured at insert time if a plain update completed in between.
func TestRolloutActivationRejectsStaleControl(t *testing.T) {
	fixture := newRolloutFixture(t)
	ctx := context.Background()

	// The update everyone is running before either publish starts.
	fixture.createUpdate(t, rolloutTestDefaultBranch, 4000, "ios", true)

	// A plain publish's row exists, unchecked, while its bundle uploads.
	plainUpdate := fixture.createUpdate(t, rolloutTestDefaultBranch, 4100, "ios", false)

	// A rollout publish starts while that upload is still running; its control is
	// resolved against a branch where 4100 is not yet visible.
	rolloutUpdate := fixture.createRolloutUpdate(t, rolloutTestDefaultBranch, 4200, "ios", 10)

	// The plain upload finishes first and is accepted: no rollout is active yet.
	require.NoError(t, fixture.updates.MarkUpdateAsChecked(ctx, plainUpdate))

	// Two outcomes are acceptable here: refused activation, or activation with a control
	// resolved at activation time. What must never happen is the control captured at insert time.
	rolloutErr := fixture.updates.MarkUpdateAsChecked(ctx, rolloutUpdate)

	envelope, err := fixture.updates.GetLatestUpdateWithRollout(ctx, fixture.appId, rolloutTestDefaultBranch, rolloutTestRuntime, "ios")
	require.NoError(t, err)
	require.NotNil(t, envelope)

	if rolloutErr != nil {
		assert.Equal(t, "4100", envelope.UpdateId, "the plain publish stays live when the rollout is refused")
		assert.Nil(t, envelope.RolloutPercentage, "no rollout may be active after a refused activation")
		return
	}

	require.Equal(t, "4200", envelope.UpdateId, "the rollout update is the one being served")
	require.NotNil(t, envelope.RolloutPercentage)
	require.Equal(t, 10, *envelope.RolloutPercentage)

	// The out-of-bucket cohort must receive the update that was live when the rollout activated (4100).
	require.NotNil(t, envelope.Control, "out-of-bucket devices must have a control update")
	assert.Equal(t, "4100", envelope.Control.UpdateId,
		"control must reflect the branch at activation time; 4000 here means publish 4100 succeeded but is served to nobody")
}