| package gerrit |
| |
| import ( |
| "testing" |
| |
| "github.com/stretchr/testify/require" |
| ) |
| |
| func makeChangeInfo() *ChangeInfo { |
| return &ChangeInfo{ |
| Labels: map[string]*LabelEntry{}, |
| } |
| } |
| |
| func testConfig(t *testing.T, cfg *Config) { |
| |
| testEmpty(t, cfg) |
| testCqInProgress(t, cfg) |
| testCqSuccess(t, cfg) |
| testCqSuccessNotMerged(t, cfg) |
| testCqSuccessWithHigherValues(t, cfg) |
| testCqFailed(t, cfg) |
| testCqFailedWithLowerValues(t, cfg) |
| testDryRunInProgress(t, cfg) |
| testDryRunSuccess(t, cfg) |
| testDryRunSuccessWithHigherValues(t, cfg) |
| testDryRunFailed(t, cfg) |
| testDryRunFailedWithLowerValues(t, cfg) |
| } |
| |
| // Initial empty change. No CQ labels at all. |
| func testEmpty(t *testing.T, cfg *Config) { |
| ci := makeChangeInfo() |
| |
| require.False(t, cfg.CqRunning(ci)) |
| require.False(t, cfg.CqSuccess(ci)) |
| require.False(t, cfg.DryRunRunning(ci)) |
| if cfg.HasCq { |
| // Have to use false here because ANGLE and Chromium configs do not use |
| // CQ success/failure labels, so we can't distinguish between "dry run |
| // finished" and "dry run never started". |
| require.False(t, cfg.DryRunSuccess(ci, false)) |
| } else { |
| // DryRunSuccess is always true with no CQ. |
| require.True(t, cfg.DryRunSuccess(ci, false)) |
| } |
| } |
| |
| // CQ in progress. |
| func testCqInProgress(t *testing.T, cfg *Config) { |
| ci := makeChangeInfo() |
| SetLabels(ci, cfg.SetCqLabels) |
| if cfg.HasCq { |
| require.True(t, cfg.CqRunning(ci)) |
| require.False(t, cfg.CqSuccess(ci)) |
| require.False(t, cfg.DryRunRunning(ci)) |
| require.False(t, cfg.DryRunSuccess(ci, true)) |
| } else { |
| // CQ and DryRun are never running with no CQ. CqSuccess is only |
| // true if the change is merged, and DryRunSuccess is always |
| // true. |
| require.False(t, cfg.CqRunning(ci)) |
| require.False(t, cfg.CqSuccess(ci)) |
| require.False(t, cfg.DryRunRunning(ci)) |
| require.True(t, cfg.DryRunSuccess(ci, true)) |
| } |
| } |
| |
| // CQ success. |
| func testCqSuccess(t *testing.T, cfg *Config) { |
| ci := makeChangeInfo() |
| if len(cfg.CqSuccessLabels) > 0 { |
| SetLabels(ci, cfg.CqSuccessLabels) |
| } |
| if cfg.CqLabelsUnsetOnCompletion { |
| UnsetLabels(ci, cfg.CqActiveLabels) |
| } |
| ci.Status = ChangeStatusMerged |
| if cfg.HasCq { |
| require.False(t, cfg.CqRunning(ci)) |
| require.True(t, cfg.CqSuccess(ci)) |
| require.False(t, cfg.DryRunRunning(ci)) |
| require.True(t, cfg.DryRunSuccess(ci, false)) |
| } else { |
| // CQ and DryRun are never running with no CQ. CqSuccess is only |
| // true if the change is merged, and DryRunSuccess is always |
| // true. |
| require.False(t, cfg.CqRunning(ci)) |
| require.True(t, cfg.CqSuccess(ci)) |
| require.False(t, cfg.DryRunRunning(ci)) |
| require.True(t, cfg.DryRunSuccess(ci, true)) |
| } |
| } |
| |
| // CQ success with higher label values than specified. |
| func testCqSuccessWithHigherValues(t *testing.T, cfg *Config) { |
| ci := makeChangeInfo() |
| labels := map[string]int{} |
| if len(cfg.CqSuccessLabels) > 0 { |
| for k, v := range cfg.CqSuccessLabels { |
| labels[k] = v + 1 |
| } |
| } |
| SetLabels(ci, labels) |
| if cfg.CqLabelsUnsetOnCompletion { |
| UnsetLabels(ci, cfg.CqActiveLabels) |
| } |
| ci.Status = ChangeStatusMerged |
| if cfg.HasCq { |
| require.False(t, cfg.CqRunning(ci)) |
| require.True(t, cfg.CqSuccess(ci)) |
| require.False(t, cfg.DryRunRunning(ci)) |
| require.True(t, cfg.DryRunSuccess(ci, false)) |
| } else { |
| // CQ and DryRun are never running with no CQ. CqSuccess is only |
| // true if the change is merged, and DryRunSuccess is always |
| // true. |
| require.False(t, cfg.CqRunning(ci)) |
| require.True(t, cfg.CqSuccess(ci)) |
| require.False(t, cfg.DryRunRunning(ci)) |
| require.True(t, cfg.DryRunSuccess(ci, true)) |
| } |
| } |
| |
| // CQ success but not merged yet (this is a race condition which occurs |
| // occasionally on the Android rollers). |
| func testCqSuccessNotMerged(t *testing.T, cfg *Config) { |
| ci := makeChangeInfo() |
| SetLabels(ci, cfg.SetCqLabels) |
| if cfg.CqLabelsUnsetOnCompletion { |
| UnsetLabels(ci, cfg.CqActiveLabels) |
| } |
| if len(cfg.CqSuccessLabels) > 0 { |
| SetLabels(ci, cfg.CqSuccessLabels) |
| } |
| ci.Status = "" |
| if cfg.HasCq { |
| // In this case, we're waiting for the CQ to land the change, so |
| // we consider it to still be running. |
| if len(cfg.CqSuccessLabels) > 0 { |
| require.True(t, cfg.CqRunning(ci)) |
| require.True(t, cfg.DryRunSuccess(ci, false)) |
| } else { |
| require.False(t, cfg.CqRunning(ci)) |
| require.False(t, cfg.DryRunSuccess(ci, false)) |
| } |
| require.False(t, cfg.CqSuccess(ci)) |
| require.False(t, cfg.DryRunRunning(ci)) |
| } else { |
| // CQ and DryRun are never running with no CQ. CqSuccess is only |
| // true if the change is merged, and DryRunSuccess is always |
| // true. |
| require.False(t, cfg.CqRunning(ci)) |
| require.False(t, cfg.CqSuccess(ci)) |
| require.False(t, cfg.DryRunRunning(ci)) |
| require.True(t, cfg.DryRunSuccess(ci, true)) |
| } |
| } |
| |
| // CQ failed. |
| func testCqFailed(t *testing.T, cfg *Config) { |
| ci := makeChangeInfo() |
| SetLabels(ci, cfg.SetCqLabels) |
| if cfg.CqLabelsUnsetOnCompletion { |
| UnsetLabels(ci, cfg.CqActiveLabels) |
| } |
| if len(cfg.CqFailureLabels) > 0 { |
| SetLabels(ci, cfg.CqFailureLabels) |
| } |
| ci.Status = "" |
| if cfg.HasCq { |
| require.False(t, cfg.CqRunning(ci)) |
| require.False(t, cfg.CqSuccess(ci)) |
| require.False(t, cfg.DryRunRunning(ci)) |
| require.False(t, cfg.DryRunSuccess(ci, false)) |
| } else { |
| // CQ and DryRun are never running with no CQ. CqSuccess is only |
| // true if the change is merged, and DryRunSuccess is always |
| // true. |
| require.False(t, cfg.CqRunning(ci)) |
| require.False(t, cfg.CqSuccess(ci)) |
| require.False(t, cfg.DryRunRunning(ci)) |
| require.True(t, cfg.DryRunSuccess(ci, true)) |
| } |
| } |
| |
| // CQ failed with lower label values than specified. |
| func testCqFailedWithLowerValues(t *testing.T, cfg *Config) { |
| ci := makeChangeInfo() |
| SetLabels(ci, cfg.SetCqLabels) |
| if cfg.CqLabelsUnsetOnCompletion { |
| UnsetLabels(ci, cfg.CqActiveLabels) |
| } |
| labels := map[string]int{} |
| if len(cfg.CqFailureLabels) > 0 { |
| for k, v := range cfg.CqFailureLabels { |
| labels[k] = v - 1 |
| } |
| } |
| SetLabels(ci, labels) |
| ci.Status = "" |
| if cfg.HasCq { |
| require.False(t, cfg.CqRunning(ci)) |
| require.False(t, cfg.CqSuccess(ci)) |
| require.False(t, cfg.DryRunRunning(ci)) |
| require.False(t, cfg.DryRunSuccess(ci, false)) |
| } else { |
| // CQ and DryRun are never running with no CQ. CqSuccess is only |
| // true if the change is merged, and DryRunSuccess is always |
| // true. |
| require.False(t, cfg.CqRunning(ci)) |
| require.False(t, cfg.CqSuccess(ci)) |
| require.False(t, cfg.DryRunRunning(ci)) |
| require.True(t, cfg.DryRunSuccess(ci, true)) |
| } |
| } |
| |
| // Dry run in progress. |
| func testDryRunInProgress(t *testing.T, cfg *Config) { |
| ci := makeChangeInfo() |
| SetLabels(ci, cfg.SetDryRunLabels) |
| if cfg.HasCq { |
| require.False(t, cfg.CqRunning(ci)) |
| require.False(t, cfg.CqSuccess(ci)) |
| require.True(t, cfg.DryRunRunning(ci)) |
| require.False(t, cfg.DryRunSuccess(ci, true)) |
| } else { |
| // CQ and DryRun are never running with no CQ. CqSuccess is only |
| // true if the change is merged, and DryRunSuccess is always |
| // true. |
| require.False(t, cfg.CqRunning(ci)) |
| require.False(t, cfg.CqSuccess(ci)) |
| require.False(t, cfg.DryRunRunning(ci)) |
| require.True(t, cfg.DryRunSuccess(ci, true)) |
| } |
| } |
| |
| // Dry run success. |
| func testDryRunSuccess(t *testing.T, cfg *Config) { |
| ci := makeChangeInfo() |
| SetLabels(ci, cfg.SetDryRunLabels) |
| if len(cfg.DryRunSuccessLabels) > 0 { |
| SetLabels(ci, cfg.DryRunSuccessLabels) |
| } |
| if cfg.CqLabelsUnsetOnCompletion { |
| UnsetLabels(ci, cfg.DryRunActiveLabels) |
| } |
| // Unfortunately, with no labels to differentiate, we can't verify that |
| // CqRunning is false here. |
| //require.False(t, cfg.CqRunning(ci)) |
| require.False(t, cfg.CqSuccess(ci)) |
| require.False(t, cfg.DryRunRunning(ci)) |
| require.True(t, cfg.DryRunSuccess(ci, true)) |
| } |
| |
| // Dry run success with higher label values than specified. |
| func testDryRunSuccessWithHigherValues(t *testing.T, cfg *Config) { |
| ci := makeChangeInfo() |
| SetLabels(ci, cfg.SetDryRunLabels) |
| labels := map[string]int{} |
| if len(cfg.DryRunSuccessLabels) > 0 { |
| for k, v := range cfg.DryRunSuccessLabels { |
| labels[k] = v + 1 |
| } |
| } |
| SetLabels(ci, labels) |
| if cfg.CqLabelsUnsetOnCompletion { |
| UnsetLabels(ci, cfg.DryRunActiveLabels) |
| } |
| // Unfortunately, with no labels to differentiate, we can't verify that |
| // CqRunning is false here. |
| //require.False(t, cfg.CqRunning(ci)) |
| require.False(t, cfg.CqSuccess(ci)) |
| require.False(t, cfg.DryRunRunning(ci)) |
| require.True(t, cfg.DryRunSuccess(ci, true)) |
| } |
| |
| // Dry run failed. |
| func testDryRunFailed(t *testing.T, cfg *Config) { |
| ci := makeChangeInfo() |
| SetLabels(ci, cfg.SetDryRunLabels) |
| if len(cfg.DryRunFailureLabels) > 0 { |
| SetLabels(ci, cfg.DryRunFailureLabels) |
| } |
| if cfg.CqLabelsUnsetOnCompletion { |
| UnsetLabels(ci, cfg.DryRunActiveLabels) |
| } |
| if cfg.HasCq { |
| require.False(t, cfg.CqRunning(ci)) |
| require.False(t, cfg.CqSuccess(ci)) |
| require.False(t, cfg.DryRunRunning(ci)) |
| require.False(t, cfg.DryRunSuccess(ci, false)) |
| } else { |
| // CQ and DryRun are never running with no CQ. CqSuccess is only |
| // true if the change is merged, and DryRunSuccess is always |
| // true. |
| require.False(t, cfg.CqRunning(ci)) |
| require.False(t, cfg.CqSuccess(ci)) |
| require.False(t, cfg.DryRunRunning(ci)) |
| require.True(t, cfg.DryRunSuccess(ci, true)) |
| } |
| } |
| |
| // Dry run failed with lower label values than specified. |
| func testDryRunFailedWithLowerValues(t *testing.T, cfg *Config) { |
| ci := makeChangeInfo() |
| SetLabels(ci, cfg.SetDryRunLabels) |
| labels := map[string]int{} |
| if len(cfg.DryRunFailureLabels) > 0 { |
| for k, v := range cfg.DryRunFailureLabels { |
| labels[k] = v - 1 |
| } |
| } |
| SetLabels(ci, labels) |
| if cfg.CqLabelsUnsetOnCompletion { |
| UnsetLabels(ci, cfg.DryRunActiveLabels) |
| } |
| if cfg.HasCq { |
| require.False(t, cfg.CqRunning(ci)) |
| require.False(t, cfg.CqSuccess(ci)) |
| require.False(t, cfg.DryRunRunning(ci)) |
| require.False(t, cfg.DryRunSuccess(ci, false)) |
| } else { |
| // CQ and DryRun are never running with no CQ. CqSuccess is only |
| // true if the change is merged, and DryRunSuccess is always |
| // true. |
| require.False(t, cfg.CqRunning(ci)) |
| require.False(t, cfg.CqSuccess(ci)) |
| require.False(t, cfg.DryRunRunning(ci)) |
| require.True(t, cfg.DryRunSuccess(ci, true)) |
| } |
| } |
| |
| // Partial CQ success; in the case of Android, this occurs when the presubmit |
| // produces warnings, which causes the Verified+1 label to be set but the |
| // Autosubmit+1 label to be removed. |
| func testPartialCqSuccess(t *testing.T, cfg *Config) { |
| ci := makeChangeInfo() |
| labels := map[string]int{} |
| for k, v := range cfg.CqSuccessLabels { |
| labels[k] = v |
| } |
| for k, v := range cfg.NoCqLabels { |
| labels[k] = v |
| } |
| SetLabels(ci, labels) |
| require.False(t, cfg.CqRunning(ci)) |
| require.False(t, cfg.CqSuccess(ci)) |
| } |
| |
| func TestConfigAndroid(t *testing.T) { |
| cfg := ConfigAndroid |
| testConfig(t, cfg) |
| testPartialCqSuccess(t, cfg) |
| } |
| |
| func TestConfigANGLE(t *testing.T) { |
| testConfig(t, ConfigANGLE) |
| } |
| |
| func TestConfigChromium(t *testing.T) { |
| testConfig(t, ConfigChromium) |
| } |
| |
| func TestConfigChromiumNoCQ(t *testing.T) { |
| testConfig(t, ConfigChromiumNoCQ) |
| } |
| |
| func TestConfigLibassistant(t *testing.T) { |
| testConfig(t, ConfigLibAssistant) |
| } |