| package patch_test |
|
|
| import ( |
| "testing" |
|
|
| "github.com/stretchr/testify/require" |
|
|
| "github.com/openmeterio/openmeter/openmeter/subscription" |
| "github.com/openmeterio/openmeter/openmeter/subscription/patch" |
| "github.com/openmeterio/openmeter/openmeter/testutils" |
| "github.com/openmeterio/openmeter/pkg/clock" |
| "github.com/openmeterio/openmeter/pkg/datetime" |
| ) |
|
|
| func TestStretchPhase(t *testing.T) { |
| now := testutils.GetRFC3339Time(t, "2021-01-01T00:00:01Z") |
| clock.SetTime(now) |
|
|
| s, p := getDefaultSpec(t, now) |
|
|
| getSpec := func(_ *testing.T) subscription.SubscriptionSpec { |
| phases := make(map[string]*subscription.SubscriptionPhaseSpec) |
|
|
| for k, v := range s.Phases { |
| vCopy := *v |
| phases[k] = &vCopy |
| } |
|
|
| s2 := *s |
| s2.Phases = phases |
|
|
| return s2 |
| } |
|
|
| tests := testsuite[patch.PatchStretchPhase]{ |
| SystemTime: now, |
| TT: []testcase[patch.PatchStretchPhase]{ |
| { |
| Name: "Should extend first phase by 1 Month", |
| Patch: patch.PatchStretchPhase{ |
| PhaseKey: "test_phase_1", |
| Duration: datetime.MustParseDuration(t, "P1M"), |
| }, |
| GetSpec: func(t *testing.T) *subscription.SubscriptionSpec { |
| s := getSpec(t) |
|
|
| |
| require.GreaterOrEqual(t, len(s.Phases), 2) |
| require.Equal(t, "test_phase_1", p.Phases[0].Key) |
|
|
| _, ok := s.Phases["test_phase_1"] |
| require.True(t, ok) |
|
|
| p2, ok := s.Phases["test_phase_2"] |
| require.True(t, ok) |
|
|
| |
| require.Equal(t, p2.StartAfter, datetime.NewISODuration(0, 1, 0, 0, 0, 0, 0)) |
|
|
| return &s |
| }, |
| Ctx: subscription.ApplyContext{ |
| CurrentTime: now, |
| }, |
| GetExpectedSpec: func(t *testing.T) subscription.SubscriptionSpec { |
| s := getSpec(t) |
|
|
| for k := range s.Phases { |
| if k != "test_phase_1" { |
| nSA, err := s.Phases[k].StartAfter.Add(datetime.MustParseDuration(t, "P1M")) |
| require.NoError(t, err) |
|
|
| s.Phases[k].StartAfter = nSA |
| } |
| } |
|
|
| return s |
| }, |
| }, |
| { |
| Name: "Should shrink first phase by 2 weeks", |
| Patch: patch.PatchStretchPhase{ |
| PhaseKey: "test_phase_1", |
| Duration: datetime.MustParseDuration(t, "-P2W"), |
| }, |
| GetSpec: func(t *testing.T) *subscription.SubscriptionSpec { |
| s := getSpec(t) |
|
|
| |
| require.GreaterOrEqual(t, len(s.Phases), 2) |
| require.Equal(t, "test_phase_1", p.Phases[0].Key) |
|
|
| _, ok := s.Phases["test_phase_1"] |
| require.True(t, ok) |
|
|
| p2, ok := s.Phases["test_phase_2"] |
| require.True(t, ok) |
|
|
| |
| require.Equal(t, p2.StartAfter, datetime.NewISODuration(0, 1, 0, 0, 0, 0, 0)) |
|
|
| return &s |
| }, |
| Ctx: subscription.ApplyContext{ |
| CurrentTime: now, |
| }, |
| GetExpectedSpec: func(t *testing.T) subscription.SubscriptionSpec { |
| s := getSpec(t) |
|
|
| for k := range s.Phases { |
| if k != "test_phase_1" { |
| nSA, err := s.Phases[k].StartAfter.Subtract(datetime.MustParseDuration(t, "P2W")) |
| require.NoError(t, err) |
|
|
| s.Phases[k].StartAfter = nSA |
| } |
| } |
|
|
| return s |
| }, |
| }, |
| { |
| Name: "Should not allow stretching if there's a single phase", |
| Patch: patch.PatchStretchPhase{ |
| PhaseKey: "test_phase_1", |
| Duration: datetime.MustParseDuration(t, "P1M"), |
| }, |
| GetSpec: func(t *testing.T) *subscription.SubscriptionSpec { |
| s := getSpec(t) |
|
|
| |
| require.GreaterOrEqual(t, len(s.Phases), 2) |
| require.Equal(t, "test_phase_1", p.Phases[0].Key) |
|
|
| _, ok := s.Phases["test_phase_1"] |
| require.True(t, ok) |
|
|
| delete(s.Phases, "test_phase_2") |
| delete(s.Phases, "test_phase_3") |
|
|
| return &s |
| }, |
| Ctx: subscription.ApplyContext{ |
| CurrentTime: now, |
| }, |
| ExpectedError: &subscription.PatchConflictError{Msg: "cannot stretch a single phase"}, |
| }, |
| { |
| Name: "Should not allow stretching more than phase length", |
| Patch: patch.PatchStretchPhase{ |
| PhaseKey: "test_phase_1", |
| Duration: datetime.MustParseDuration(t, "-P1M"), |
| }, |
| GetSpec: func(t *testing.T) *subscription.SubscriptionSpec { |
| s := getSpec(t) |
|
|
| |
| require.GreaterOrEqual(t, len(s.Phases), 2) |
| require.Equal(t, "test_phase_1", p.Phases[0].Key) |
|
|
| _, ok := s.Phases["test_phase_1"] |
| require.True(t, ok) |
|
|
| return &s |
| }, |
| Ctx: subscription.ApplyContext{ |
| CurrentTime: now, |
| }, |
| ExpectedError: &subscription.PatchConflictError{Msg: "phase test_phase_1 would disappear due to stretching"}, |
| }, |
| { |
| Name: "Should work when stretching past next phase", |
| Patch: patch.PatchStretchPhase{ |
| PhaseKey: "test_phase_1", |
| Duration: datetime.MustParseDuration(t, "P5M"), |
| }, |
| GetSpec: func(t *testing.T) *subscription.SubscriptionSpec { |
| s := getSpec(t) |
|
|
| |
| require.GreaterOrEqual(t, len(s.Phases), 2) |
| require.Equal(t, "test_phase_1", p.Phases[0].Key) |
|
|
| _, ok := s.Phases["test_phase_1"] |
| require.True(t, ok) |
|
|
| return &s |
| }, |
| GetExpectedSpec: func(t *testing.T) subscription.SubscriptionSpec { |
| s := getSpec(t) |
|
|
| for k := range s.Phases { |
| if k != "test_phase_1" { |
| nSA, err := s.Phases[k].StartAfter.Add(datetime.MustParseDuration(t, "P5M")) |
| require.NoError(t, err) |
|
|
| s.Phases[k].StartAfter = nSA |
| } |
| } |
|
|
| return s |
| }, |
| Ctx: subscription.ApplyContext{ |
| CurrentTime: now, |
| }, |
| }, |
| }, |
| } |
|
|
| tests.Run(t) |
| } |
|
|
| func TestASD(t *testing.T) { |
| p1 := datetime.MustParseDuration(t, "P1M") |
| p2 := datetime.MustParseDuration(t, "P2W") |
| p3 := datetime.MustParseDuration(t, "-P2W") |
|
|
| r1, err := p1.Subtract(p2) |
| require.Nil(t, err) |
|
|
| r2, err := p1.Add(p3) |
| require.Nil(t, err) |
|
|
| require.Equal(t, r1, r2) |
| } |
|
|