blob: 4d89b39b45f68ba2c0507db56fd89c13fd557868 [file] [log] [blame] [edit]
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)
}