Add some tests (#2652)

and some cleanups
This commit is contained in:
qwerty287 2023-10-28 13:37:54 +02:00 committed by GitHub
parent 4f8732bafc
commit e74115027b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 356 additions and 94 deletions

View file

@ -1252,8 +1252,8 @@ const docTemplate = `{
}
],
"responses": {
"200": {
"description": "OK"
"204": {
"description": "No Content"
}
}
}
@ -1278,8 +1278,8 @@ const docTemplate = `{
}
],
"responses": {
"200": {
"description": "OK"
"204": {
"description": "No Content"
}
}
}
@ -1304,8 +1304,8 @@ const docTemplate = `{
}
],
"responses": {
"200": {
"description": "OK"
"204": {
"description": "No Content"
}
}
}
@ -2055,8 +2055,8 @@ const docTemplate = `{
}
],
"responses": {
"200": {
"description": "OK"
"204": {
"description": "No Content"
}
}
}

View file

@ -56,6 +56,6 @@ func TestService(t *testing.T) {
s, _ := Service("foo", "bar", "baz", []string{"1", "2", "3"})
j, err := json.Marshal(s)
assert.Nil(t, err)
assert.NoError(t, err)
assert.JSONEq(t, expected, string(j))
}

View file

@ -65,19 +65,19 @@ func TestPersistentVolumeClaim(t *testing.T) {
}`
pvc, err := PersistentVolumeClaim("someNamespace", "somename", "local-storage", "1Gi", true)
assert.Nil(t, err)
assert.NoError(t, err)
j, err := json.Marshal(pvc)
assert.Nil(t, err)
assert.NoError(t, err)
assert.JSONEq(t, expectedRwx, string(j))
pvc, err = PersistentVolumeClaim("someNamespace", "somename", "local-storage", "1Gi", false)
assert.Nil(t, err)
assert.NoError(t, err)
j, err = json.Marshal(pvc)
assert.Nil(t, err)
assert.NoError(t, err)
assert.JSONEq(t, expectedRwo, string(j))
_, err = PersistentVolumeClaim("someNamespace", "some0INVALID3name", "local-storage", "1Gi", false)
assert.NotNil(t, err)
assert.Error(t, err)
}

View file

@ -0,0 +1,33 @@
// Copyright 2023 Woodpecker Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package local
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestGenNetRC(t *testing.T) {
assert.Equal(t, `
machine machine
login user
password pass
`, genNetRC(map[string]string{
"CI_NETRC_MACHINE": "machine",
"CI_NETRC_USERNAME": "user",
"CI_NETRC_PASSWORD": "pass",
}))
}

View file

@ -35,7 +35,7 @@ func TestStringorIntYaml(t *testing.T) {
assert.Equal(t, StringOrInt(10), s.Foo)
d, err := yaml.Marshal(&s)
assert.Nil(t, err)
assert.NoError(t, err)
s2 := StructStringorInt{}
assert.NoError(t, yaml.Unmarshal(d, &s2))
@ -57,7 +57,7 @@ func TestStringOrSliceYaml(t *testing.T) {
assert.Equal(t, StringOrSlice{"bar", "baz"}, s.Foo)
d, err := yaml.Marshal(&s)
assert.Nil(t, err)
assert.NoError(t, err)
s2 := StructStringOrSlice{}
assert.NoError(t, yaml.Unmarshal(d, &s2))
@ -79,7 +79,7 @@ func TestSliceOrMapYaml(t *testing.T) {
assert.Equal(t, SliceOrMap{"bar": "baz", "far": "faz"}, s.Foos)
d, err := yaml.Marshal(&s)
assert.Nil(t, err)
assert.NoError(t, err)
s2 := StructSliceorMap{}
assert.NoError(t, yaml.Unmarshal(d, &s2))
@ -106,7 +106,7 @@ func TestStr2SliceOrMapPtrMap(t *testing.T) {
Bars: []string{},
}}
d, err := yaml.Marshal(&s)
assert.Nil(t, err)
assert.NoError(t, err)
s2 := map[string]*StructSliceorMap{}
assert.NoError(t, yaml.Unmarshal(d, &s2))

View file

@ -91,7 +91,7 @@ network2:
}
for _, network := range networks {
bytes, err := yaml.Marshal(network.networks)
assert.Nil(t, err)
assert.NoError(t, err)
assert.Equal(t, network.expected, string(bytes), "should be equal")
}
}

View file

@ -88,7 +88,7 @@ func TestMarshalVolumes(t *testing.T) {
}
for _, volume := range volumes {
bytes, err := yaml.Marshal(volume.volumes)
assert.Nil(t, err)
assert.NoError(t, err)
assert.Equal(t, volume.expected, string(bytes), "should be equal")
}
}
@ -151,7 +151,7 @@ func TestUnmarshalVolumes(t *testing.T) {
for _, volume := range volumes {
actual := &Volumes{}
err := yaml.Unmarshal([]byte(volume.yaml), actual)
assert.Nil(t, err)
assert.NoError(t, err)
assert.Equal(t, volume.expected, actual, "should be equal")
}
}

View file

@ -16,7 +16,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc v4.23.4
// protoc v4.24.3
// source: woodpecker.proto
package proto

View file

@ -16,7 +16,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.3.0
// - protoc v4.23.4
// - protoc v4.24.3
// source: woodpecker.proto
package proto

View file

@ -54,12 +54,12 @@ func GetQueueInfo(c *gin.Context) {
// @Summary Pause a pipeline queue
// @Router /queue/pause [post]
// @Produce plain
// @Success 200
// @Success 204
// @Tags Pipeline queues
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
func PauseQueue(c *gin.Context) {
server.Config.Services.Queue.Pause()
c.Status(http.StatusOK)
c.Status(http.StatusNoContent)
}
// ResumeQueue
@ -67,12 +67,12 @@ func PauseQueue(c *gin.Context) {
// @Summary Resume a pipeline queue
// @Router /queue/resume [post]
// @Produce plain
// @Success 200
// @Success 204
// @Tags Pipeline queues
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
func ResumeQueue(c *gin.Context) {
server.Config.Services.Queue.Resume()
c.Status(http.StatusOK)
c.Status(http.StatusNoContent)
}
// BlockTilQueueHasRunningItem
@ -80,7 +80,7 @@ func ResumeQueue(c *gin.Context) {
// @Summary Block til pipeline queue has a running item
// @Router /queue/norunningpipelines [get]
// @Produce plain
// @Success 200
// @Success 204
// @Tags Pipeline queues
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
func BlockTilQueueHasRunningItem(c *gin.Context) {
@ -90,7 +90,7 @@ func BlockTilQueueHasRunningItem(c *gin.Context) {
break
}
}
c.Status(http.StatusOK)
c.Status(http.StatusNoContent)
}
// PostHook

View file

@ -417,7 +417,7 @@ func RepairRepo(c *gin.Context) {
// @Summary Move a repository to a new owner
// @Router /repos/{repo_id}/move [post]
// @Produce plain
// @Success 200
// @Success 204
// @Tags Repositories
// @Param Authorization header string true "Insert your personal access token" default(Bearer <personal access token>)
// @Param repo_id path int true "the repository id"
@ -493,7 +493,7 @@ func MoveRepo(c *gin.Context) {
c.String(http.StatusInternalServerError, err.Error())
return
}
c.Status(http.StatusOK)
c.Status(http.StatusNoContent)
}
// GetAllRepos

View file

@ -0,0 +1,33 @@
// Copyright 2022 Woodpecker Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package badges
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/woodpecker-ci/woodpecker/server/model"
)
// Generate an SVG badge based on a pipeline
func TestGenerate(t *testing.T) {
assert.Equal(t, badgeNone, Generate(nil))
assert.Equal(t, badgeSuccess, Generate(&model.Pipeline{Status: model.StatusSuccess}))
assert.Equal(t, badgeFailure, Generate(&model.Pipeline{Status: model.StatusFailure}))
assert.Equal(t, badgeError, Generate(&model.Pipeline{Status: model.StatusError}))
assert.Equal(t, badgeError, Generate(&model.Pipeline{Status: model.StatusKilled}))
assert.Equal(t, badgeStarted, Generate(&model.Pipeline{Status: model.StatusPending}))
assert.Equal(t, badgeStarted, Generate(&model.Pipeline{Status: model.StatusRunning}))
}

View file

@ -96,9 +96,6 @@ func parsePushHook(hook *github.PushEvent) (*model.Repo, *model.Pipeline, error)
if len(pipeline.Author) == 0 {
pipeline.Author = hook.GetHeadCommit().GetAuthor().GetLogin()
}
// if len(pipeline.Email) == 0 {
// TODO: default to gravatar?
// }
if strings.HasPrefix(pipeline.Ref, "refs/tags/") {
// just kidding, this is actually a tag event. Why did this come as a push
// event we'll never know!

View file

@ -1,4 +1,4 @@
// Code generated by mockery v2.33.1. DO NOT EDIT.
// Code generated by mockery v2.36.0. DO NOT EDIT.
package mocks

View file

@ -0,0 +1,47 @@
// Copyright 2023 Woodpecker Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package types
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestSortByName(t *testing.T) {
fm := []*FileMeta{
{
Name: "a",
},
{
Name: "c",
},
{
Name: "b",
},
}
assert.Equal(t, []*FileMeta{
{
Name: "a",
},
{
Name: "b",
},
{
Name: "c",
},
}, SortByName(fm))
}

View file

@ -23,7 +23,6 @@ type StepStore interface {
StepList(*Pipeline) ([]*Step, error)
StepCreate([]*Step) error
StepUpdate(*Step) error
StepClear(*Pipeline) error
}
// Different ways to handle failure states

46
server/model/step_test.go Normal file
View file

@ -0,0 +1,46 @@
// Copyright 2023 Woodpecker Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package model
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestStepStatus(t *testing.T) {
step := &Step{
State: StatusPending,
}
assert.Equal(t, step.Running(), true)
step.State = StatusRunning
assert.Equal(t, step.Running(), true)
step.Failure = FailureIgnore
step.State = StatusError
assert.Equal(t, step.Failing(), false)
step.State = StatusFailure
assert.Equal(t, step.Failing(), false)
step.Failure = FailureFail
step.State = StatusError
assert.Equal(t, step.Failing(), true)
step.State = StatusFailure
assert.Equal(t, step.Failing(), true)
step.State = StatusPending
assert.Equal(t, step.Failing(), false)
step.State = StatusSuccess
assert.Equal(t, step.Failing(), false)
}

View file

@ -24,27 +24,27 @@ import (
func TestShortMessageLongKey(t *testing.T) {
aes := &aesEncryptionService{}
err := aes.loadCipher(string(random.GetRandomBytes(32)))
assert.Nil(t, err)
assert.NoError(t, err)
input := string(random.GetRandomBytes(4))
cipher, err := aes.Encrypt(input, "")
assert.Nil(t, err)
assert.NoError(t, err)
output, err := aes.Decrypt(cipher, "")
assert.Nil(t, err)
assert.NoError(t, err)
assert.Equal(t, input, output)
}
func TestLongMessageShortKey(t *testing.T) {
aes := &aesEncryptionService{}
err := aes.loadCipher(string(random.GetRandomBytes(12)))
assert.Nil(t, err)
assert.NoError(t, err)
input := string(random.GetRandomBytes(1024))
cipher, err := aes.Encrypt(input, "")
assert.Nil(t, err)
assert.NoError(t, err)
output, err := aes.Decrypt(cipher, "")
assert.Nil(t, err)
assert.NoError(t, err)
assert.Equal(t, input, output)
}

View file

@ -17,6 +17,8 @@ package datastore
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/woodpecker-ci/woodpecker/server/model"
)
@ -29,28 +31,62 @@ func TestAgentFindByToken(t *testing.T) {
Name: "test",
Token: "secret-token",
}
if err := store.AgentCreate(agent); err != nil {
t.Errorf("Unexpected error: insert agent: %s", err)
return
}
err := store.AgentCreate(agent)
assert.NoError(t, err)
_agent, err := store.AgentFindByToken(agent.Token)
if err != nil {
t.Error(err)
return
}
if got, want := _agent.ID, int64(1); got != want {
t.Errorf("Want config id %d, got %d", want, got)
}
assert.Equal(t, int64(1), _agent.ID)
_agent, err = store.AgentFindByToken("")
if err == nil || err.Error() != "Please provide a token" {
t.Errorf("Expected to get an error for an empty token, but got %s", err)
return
}
if _agent != nil {
t.Errorf("Expected to not find an agent")
return
}
assert.ErrorIs(t, err, ErrNoTokenProvided)
assert.Nil(t, _agent)
}
func TestAgentFindByID(t *testing.T) {
store, closer := newTestStore(t, new(model.Agent))
defer closer()
agent := &model.Agent{
ID: int64(1),
Name: "test",
Token: "secret-token",
}
err := store.AgentCreate(agent)
assert.NoError(t, err)
_agent, err := store.AgentFind(agent.ID)
assert.NoError(t, err)
assert.Equal(t, "secret-token", _agent.Token)
}
func TestAgentList(t *testing.T) {
store, closer := newTestStore(t, new(model.Agent))
defer closer()
agent1 := &model.Agent{
ID: int64(1),
Name: "test-1",
Token: "secret-token-1",
}
agent2 := &model.Agent{
ID: int64(2),
Name: "test-2",
Token: "secret-token-2",
}
err := store.AgentCreate(agent1)
assert.NoError(t, err)
err = store.AgentCreate(agent2)
assert.NoError(t, err)
agents, err := store.AgentList(&model.ListOptions{All: true})
assert.NoError(t, err)
assert.Equal(t, 2, len(agents))
agents, err = store.AgentList(&model.ListOptions{Page: 1, PerPage: 1})
assert.NoError(t, err)
assert.Equal(t, 1, len(agents))
}

View file

@ -0,0 +1,39 @@
// Copyright 2023 Woodpecker Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package datastore
import (
"errors"
"testing"
"github.com/stretchr/testify/assert"
"github.com/woodpecker-ci/woodpecker/server/store/types"
)
func TestWrapGet(t *testing.T) {
err := wrapGet(false, nil)
assert.ErrorIs(t, err, types.RecordNotExist)
err = wrapGet(true, errors.New("test err"))
assert.Equal(t, "TestWrapGet: test err", err.Error())
}
func TestWrapDelete(t *testing.T) {
err := wrapDelete(0, nil)
assert.ErrorIs(t, err, types.RecordNotExist)
err = wrapDelete(1, errors.New("test err"))
assert.Equal(t, "TestWrapDelete: test err", err.Error())
}

View file

@ -43,7 +43,10 @@ func (s storage) ServerConfigSet(key, value string) error {
return err
}
_, err = s.engine.Where("key = ?", config.Key).AllCols().Update(config)
// TODO change to Where() when https://gitea.com/xorm/xorm/issues/2358 is solved
_, err = s.engine.Cols("value").Update(config, &model.ServerConfig{
Key: key,
})
return err
}

View file

@ -43,4 +43,31 @@ func TestServerConfigGetSet(t *testing.T) {
t.Errorf("Want server-config value %s, got %s", serverConfig.Value, value)
return
}
serverConfig.Value = "new-wonderland"
if err := store.ServerConfigSet(serverConfig.Key, serverConfig.Value); err != nil {
t.Errorf("Unexpected error: insert secret: %s", err)
return
}
value, err = store.ServerConfigGet(serverConfig.Key)
if err != nil {
t.Errorf("Unexpected error: delete secret: %s", err)
return
}
if value != serverConfig.Value {
t.Errorf("Want server-config value %s, got %s", serverConfig.Value, value)
return
}
value, err = store.ServerConfigGet("config_not_exist")
if err == nil {
t.Errorf("Unexpected: no error on missing config: %v", err)
return
}
if value != "" {
t.Errorf("Unexpected: got value on missing config: %s", value)
return
}
}

View file

@ -83,24 +83,6 @@ func (s storage) StepUpdate(step *model.Step) error {
return err
}
func (s storage) StepClear(pipeline *model.Pipeline) error {
sess := s.engine.NewSession()
defer sess.Close()
if err := sess.Begin(); err != nil {
return err
}
if _, err := sess.Where("step_pipeline_id = ?", pipeline.ID).Delete(new(model.Step)); err != nil {
return err
}
if _, err := sess.Where("workflow_pipeline_id = ?", pipeline.ID).Delete(new(model.Workflow)); err != nil {
return err
}
return sess.Commit()
}
func deleteStep(sess *xorm.Session, stepID int64) error {
if _, err := sess.Where("step_id = ?", stepID).Delete(new(model.LogEntry)); err != nil {
return err

View file

@ -246,4 +246,39 @@ func TestStepByUUID(t *testing.T) {
assert.Empty(t, step)
}
// TODO: func TestStepCascade(t *testing.T) {}
func TestStepLoad(t *testing.T) {
store, closer := newTestStore(t, new(model.Step))
defer closer()
sess := store.engine.NewSession()
assert.NoError(t, store.stepCreate(sess, []*model.Step{
{
UUID: "4db7e5fc-5312-4d02-9e14-b51b9e3242cc",
PipelineID: 1,
PID: 1,
PPID: 1,
State: "running",
Name: "build",
},
{
UUID: "fc7c7fd6-553e-480b-8ed7-30d8563d0b79",
PipelineID: 4,
PID: 6,
PPID: 7,
Name: "build",
State: "pending",
Error: "pc load letter",
ExitCode: 255,
},
}))
_ = sess.Close()
step, err := store.StepLoad(1)
assert.NoError(t, err)
assert.NotEmpty(t, step)
assert.Equal(t, step.UUID, "4db7e5fc-5312-4d02-9e14-b51b9e3242cc")
step, err = store.StepLoad(5)
assert.ErrorIs(t, err, types.RecordNotExist)
assert.Empty(t, step)
}

View file

@ -1,4 +1,4 @@
// Code generated by mockery v2.33.1. DO NOT EDIT.
// Code generated by mockery v2.36.0. DO NOT EDIT.
package mocks
@ -1859,20 +1859,6 @@ func (_m *Store) StepChild(_a0 *model.Pipeline, _a1 int, _a2 string) (*model.Ste
return r0, r1
}
// StepClear provides a mock function with given fields: _a0
func (_m *Store) StepClear(_a0 *model.Pipeline) error {
ret := _m.Called(_a0)
var r0 error
if rf, ok := ret.Get(0).(func(*model.Pipeline) error); ok {
r0 = rf(_a0)
} else {
r0 = ret.Error(0)
}
return r0
}
// StepFind provides a mock function with given fields: _a0, _a1
func (_m *Store) StepFind(_a0 *model.Pipeline, _a1 int) (*model.Step, error) {
ret := _m.Called(_a0, _a1)

View file

@ -141,7 +141,6 @@ type Store interface {
StepChild(*model.Pipeline, int, string) (*model.Step, error)
StepList(*model.Pipeline) ([]*model.Step, error)
StepUpdate(*model.Step) error
StepClear(*model.Pipeline) error
StepListFromWorkflowFind(*model.Workflow) ([]*model.Step, error)
// Logs