internal/repository/rollout_activation_test.go
Rama main · réplica de lectura del repositorio original.
// 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")
}