mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-17 15:55:26 +01:00
9bcbe2907b
Signed-off-by: Steven Zou <szou@vmware.com>
203 lines
5.5 KiB
Go
203 lines
5.5 KiB
Go
// Copyright Project Harbor 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 hook
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"sync/atomic"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/goharbor/harbor/src/jobservice/common/rds"
|
|
"github.com/goharbor/harbor/src/jobservice/env"
|
|
"github.com/goharbor/harbor/src/jobservice/job"
|
|
"github.com/goharbor/harbor/src/jobservice/lcm"
|
|
"github.com/goharbor/harbor/src/jobservice/tests"
|
|
"github.com/gomodule/redigo/redis"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"github.com/stretchr/testify/suite"
|
|
"sync"
|
|
)
|
|
|
|
// HookAgentTestSuite tests functions of hook agent
|
|
type HookAgentTestSuite struct {
|
|
suite.Suite
|
|
|
|
pool *redis.Pool
|
|
namespace string
|
|
lcmCtl lcm.Controller
|
|
|
|
envContext *env.Context
|
|
cancel context.CancelFunc
|
|
}
|
|
|
|
// TestHookAgentTestSuite is entry of go test
|
|
func TestHookAgentTestSuite(t *testing.T) {
|
|
suite.Run(t, new(HookAgentTestSuite))
|
|
}
|
|
|
|
// SetupSuite prepares test suites
|
|
func (suite *HookAgentTestSuite) SetupSuite() {
|
|
suite.pool = tests.GiveMeRedisPool()
|
|
suite.namespace = tests.GiveMeTestNamespace()
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
suite.envContext = &env.Context{
|
|
SystemContext: ctx,
|
|
WG: new(sync.WaitGroup),
|
|
}
|
|
suite.cancel = cancel
|
|
|
|
suite.lcmCtl = lcm.NewController(suite.envContext, suite.namespace, suite.pool, func(hookURL string, change *job.StatusChange) error { return nil })
|
|
}
|
|
|
|
// TearDownSuite prepares test suites
|
|
func (suite *HookAgentTestSuite) TearDownSuite() {
|
|
conn := suite.pool.Get()
|
|
defer func() {
|
|
_ = conn.Close()
|
|
}()
|
|
|
|
_ = tests.ClearAll(suite.namespace, conn)
|
|
}
|
|
|
|
// TestEventSending ...
|
|
func (suite *HookAgentTestSuite) TestEventSending() {
|
|
done := make(chan bool, 1)
|
|
|
|
expected := uint32(1300) // >1024 max
|
|
count := uint32(0)
|
|
counter := &count
|
|
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
defer func() {
|
|
c := atomic.AddUint32(counter, 1)
|
|
if c == expected {
|
|
done <- true
|
|
}
|
|
}()
|
|
_, _ = fmt.Fprintln(w, "ok")
|
|
}))
|
|
defer ts.Close()
|
|
|
|
// in case test failed and avoid dead lock
|
|
go func() {
|
|
<-time.After(time.Duration(10) * time.Second)
|
|
done <- true // time out
|
|
}()
|
|
|
|
agent := NewAgent(suite.envContext, suite.namespace, suite.pool)
|
|
agent.Attach(suite.lcmCtl)
|
|
err := agent.Serve()
|
|
require.NoError(suite.T(), err, "agent serve: nil error expected but got %s", err)
|
|
|
|
go func() {
|
|
defer func() {
|
|
suite.cancel()
|
|
}()
|
|
|
|
for i := uint32(0); i < expected; i++ {
|
|
changeData := &job.StatusChange{
|
|
JobID: fmt.Sprintf("job-%d", i),
|
|
Status: "running",
|
|
}
|
|
|
|
evt := &Event{
|
|
URL: ts.URL,
|
|
Message: fmt.Sprintf("status of job %s change to %s", changeData.JobID, changeData.Status),
|
|
Data: changeData,
|
|
Timestamp: time.Now().Unix(),
|
|
}
|
|
|
|
err := agent.Trigger(evt)
|
|
require.Nil(suite.T(), err, "agent trigger: nil error expected but got %s", err)
|
|
}
|
|
|
|
// Check results
|
|
<-done
|
|
require.Equal(suite.T(), expected, count, "expected %d hook events but only got %d", expected, count)
|
|
}()
|
|
|
|
// Wait
|
|
suite.envContext.WG.Wait()
|
|
}
|
|
|
|
// TestRetryAndPopMin ...
|
|
func (suite *HookAgentTestSuite) TestRetryAndPopMin() {
|
|
ctx := context.Background()
|
|
|
|
tks := make(chan bool, maxHandlers)
|
|
// Put tokens
|
|
for i := 0; i < maxHandlers; i++ {
|
|
tks <- true
|
|
}
|
|
|
|
agent := &basicAgent{
|
|
context: ctx,
|
|
namespace: suite.namespace,
|
|
client: NewClient(ctx),
|
|
events: make(chan *Event, maxEventChanBuffer),
|
|
tokens: tks,
|
|
redisPool: suite.pool,
|
|
}
|
|
agent.Attach(suite.lcmCtl)
|
|
|
|
changeData := &job.StatusChange{
|
|
JobID: "fake_job_ID",
|
|
Status: job.RunningStatus.String(),
|
|
}
|
|
|
|
evt := &Event{
|
|
URL: "https://fake.js.com",
|
|
Message: fmt.Sprintf("status of job %s change to %s", changeData.JobID, changeData.Status),
|
|
Data: changeData,
|
|
Timestamp: time.Now().Unix(),
|
|
}
|
|
|
|
// Mock job stats
|
|
conn := suite.pool.Get()
|
|
defer func() {
|
|
_ = conn.Close()
|
|
}()
|
|
|
|
key := rds.KeyJobStats(suite.namespace, "fake_job_ID")
|
|
_, err := conn.Do("HSET", key, "status", job.SuccessStatus.String())
|
|
require.Nil(suite.T(), err, "prepare job stats: nil error returned but got %s", err)
|
|
|
|
err = agent.pushForRetry(evt)
|
|
require.Nil(suite.T(), err, "push for retry: nil error expected but got %s", err)
|
|
|
|
err = agent.reSend()
|
|
require.Error(suite.T(), err, "resend: non nil error expected but got nil")
|
|
assert.Equal(suite.T(), 0, len(agent.events), "the hook event should be discard but actually not")
|
|
|
|
// Change status
|
|
_, err = conn.Do("HSET", key, "status", job.PendingStatus.String())
|
|
require.Nil(suite.T(), err, "prepare job stats: nil error returned but got %s", err)
|
|
|
|
err = agent.pushForRetry(evt)
|
|
require.Nil(suite.T(), err, "push for retry: nil error expected but got %s", err)
|
|
err = agent.reSend()
|
|
require.Nil(suite.T(), err, "resend: nil error should be returned but got %s", err)
|
|
|
|
<-time.After(time.Duration(1) * time.Second)
|
|
|
|
assert.Equal(suite.T(), 1, len(agent.events), "the hook event should be requeued but actually not: %d", len(agent.events))
|
|
}
|