harness-drone/operator/manager/rpc/client_test.go
2019-04-16 10:08:21 +08:00

506 lines
13 KiB
Go

// Copyright 2019 Drone.IO Inc. All rights reserved.
// Use of this source code is governed by the Drone Non-Commercial License
// that can be found in the LICENSE file.
// +build !oss
package rpc
import (
"bytes"
"testing"
"github.com/drone/drone/core"
"github.com/drone/drone/operator/manager"
"github.com/drone/drone/store/shared/db"
"github.com/google/go-cmp/cmp"
"github.com/h2non/gock"
)
func TestRequest(t *testing.T) {
defer gock.Off()
gock.New("http://drone.company.com").
Post("/rpc/v1/request").
MatchHeader("X-Drone-Token", "correct-horse-battery-staple").
BodyString(`{"Request":{"kind":"","type":"","os":"linux","arch":"amd64","variant":"","kernel":""}}`).
Reply(200).
Type("application/json").
BodyString(`{"id":1,"build_id":2,"number":3,"name":"build","status":"pending","errignore":false,"exit_code":0,"machine":"localhost","os":"linux","arch":"amd64","started":0,"stopped":0,"created":0,"updated":0,"version":1,"on_success":false,"on_failure":false}`)
want := &core.Stage{
ID: 1,
BuildID: 2,
Number: 3,
Name: "build",
Machine: "localhost",
OS: "linux",
Arch: "amd64",
Status: core.StatusPending,
ExitCode: 0,
Version: 1,
}
client := NewClient("http://drone.company.com", "correct-horse-battery-staple")
gock.InterceptClient(client.client.HTTPClient)
got, err := client.Request(noContext, &manager.Request{OS: "linux", Arch: "amd64"})
if err != nil {
t.Error(err)
}
if diff := cmp.Diff(want, got); diff != "" {
t.Errorf(diff)
}
if gock.IsPending() {
t.Errorf("Unfinished requests")
}
}
func TestAccept(t *testing.T) {
defer gock.Off()
gock.New("http://drone.company.com").
Post("/rpc/v1/accept").
MatchHeader("X-Drone-Token", "correct-horse-battery-staple").
BodyString(`{"Stage":1,"Machine":"localhost"}`).
Reply(204)
client := NewClient("http://drone.company.com", "correct-horse-battery-staple")
gock.InterceptClient(client.client.HTTPClient)
err := client.Accept(noContext, 1, "localhost")
if err != nil {
t.Error(err)
}
if gock.IsPending() {
t.Errorf("Unfinished requests")
}
}
func TestNetrc(t *testing.T) {
defer gock.Off()
gock.New("http://drone.company.com").
Post("/rpc/v1/netrc").
MatchHeader("X-Drone-Token", "correct-horse-battery-staple").
BodyString(`{"Repo":1}`).
Reply(200).
Type("application/json").
BodyString(`{"machine":"github.com","login":"octocat","password":"12345"}`)
client := NewClient("http://drone.company.com", "correct-horse-battery-staple")
gock.InterceptClient(client.client.HTTPClient)
got, err := client.Netrc(noContext, 1)
if err != nil {
t.Error(err)
}
want := &core.Netrc{
Password: "12345",
Login: "octocat",
Machine: "github.com",
}
if diff := cmp.Diff(got, want); diff != "" {
t.Errorf(diff)
}
if gock.IsPending() {
t.Errorf("Unfinished requests")
}
}
func TestDetails(t *testing.T) {
defer gock.Off()
gock.New("http://drone.company.com").
Post("/rpc/v1/details").
MatchHeader("X-Drone-Token", "correct-horse-battery-staple").
BodyString(`{"Stage":1}`).
Reply(200).
Type("application/json").
BodyString(`{"Secret":"passphrase", "Context":{"repository":{}}}`)
// TODO(bradrydzewski) return a mock core.BuildContext
// and validate the unmarshaled results.
client := NewClient("http://drone.company.com", "correct-horse-battery-staple")
gock.InterceptClient(client.client.HTTPClient)
out, err := client.Details(noContext, 1)
if err != nil {
t.Error(err)
return
}
if out.Repo.Secret != "passphrase" {
t.Errorf("Expect repository passphrase encoded in json response")
}
if gock.IsPending() {
t.Errorf("Unfinished requests")
}
}
func TestBefore(t *testing.T) {
defer gock.Off()
gock.New("http://drone.company.com").
Post("/rpc/v1/before").
MatchHeader("X-Drone-Token", "correct-horse-battery-staple").
BodyString(`{"id":1,"step_id":2,"number":3,"name":"build","status":"pending","exit_code":0,"version":1}`).
Reply(200).
Type("application/json").
BodyString(`{"id":1,"step_id":2,"number":3,"name":"build","status":"pending","exit_code":0,"version":2}`)
before := &core.Step{
ID: 1,
StageID: 2,
Number: 3,
Name: "build",
Status: core.StatusPending,
ExitCode: 0,
Version: 1,
}
client := NewClient("http://drone.company.com", "correct-horse-battery-staple")
gock.InterceptClient(client.client.HTTPClient)
err := client.Before(noContext, before)
if err != nil {
t.Error(err)
}
after := &core.Step{
ID: 1,
StageID: 2,
Number: 3,
Name: "build",
Status: core.StatusPending,
ExitCode: 0,
Version: 2,
}
if diff := cmp.Diff(before, after); diff != "" {
t.Errorf(diff)
}
if gock.IsPending() {
t.Errorf("Unfinished requests")
}
}
func TestAfter(t *testing.T) {
defer gock.Off()
gock.New("http://drone.company.com").
Post("/rpc/v1/after").
MatchHeader("X-Drone-Token", "correct-horse-battery-staple").
BodyString(`{"id":1,"step_id":2,"number":3,"name":"build","status":"failure","exit_code":1,"version":2}`).
Reply(200).
Type("application/json").
BodyString(`{"id":1,"step_id":2,"number":3,"name":"build","status":"failure","exit_code":1,"version":3}`)
before := &core.Step{
ID: 1,
StageID: 2,
Number: 3,
Name: "build",
Status: core.StatusFailing,
ExitCode: 1,
Version: 2,
}
client := NewClient("http://drone.company.com", "correct-horse-battery-staple")
gock.InterceptClient(client.client.HTTPClient)
err := client.After(noContext, before)
if err != nil {
t.Error(err)
}
after := &core.Step{
ID: 1,
StageID: 2,
Number: 3,
Name: "build",
Status: core.StatusFailing,
ExitCode: 1,
Version: 3,
}
if diff := cmp.Diff(before, after); diff != "" {
t.Errorf(diff)
}
if gock.IsPending() {
t.Errorf("Unfinished requests")
}
}
func TestBeforeAll(t *testing.T) {
defer gock.Off()
gock.New("http://drone.company.com").
Post("/rpc/v1/beforeAll").
MatchHeader("X-Drone-Token", "correct-horse-battery-staple").
BodyString(`{"id":1,"repo_id":0,"build_id":2,"number":3,"name":"build","status":"pending","errignore":false,"exit_code":0,"machine":"localhost","os":"linux","arch":"amd64","started":0,"stopped":0,"created":0,"updated":0,"version":1,"on_success":false,"on_failure":false}`).
Reply(200).
Type("application/json").
BodyString(`{"id":1,"repo_id":0,"build_id":2,"number":3,"name":"build","status":"pending","errignore":false,"exit_code":0,"machine":"localhost","os":"linux","arch":"amd64","started":0,"stopped":0,"created":0,"updated":0,"version":2,"on_success":false,"on_failure":false}`)
before := &core.Stage{
ID: 1,
BuildID: 2,
Number: 3,
Name: "build",
Machine: "localhost",
OS: "linux",
Arch: "amd64",
Status: core.StatusPending,
ExitCode: 0,
Version: 1,
}
client := NewClient("http://drone.company.com", "correct-horse-battery-staple")
gock.InterceptClient(client.client.HTTPClient)
err := client.BeforeAll(noContext, before)
if err != nil {
t.Error(err)
}
after := &core.Stage{
ID: 1,
BuildID: 2,
Number: 3,
Name: "build",
Machine: "localhost",
OS: "linux",
Arch: "amd64",
Status: core.StatusPending,
ExitCode: 0,
Version: 2,
}
if diff := cmp.Diff(before, after); diff != "" {
t.Errorf(diff)
}
if gock.IsPending() {
t.Errorf("Unfinished requests")
}
}
func TestAfterAll(t *testing.T) {
defer gock.Off()
gock.New("http://drone.company.com").
Post("/rpc/v1/afterAll").
MatchHeader("X-Drone-Token", "correct-horse-battery-staple").
BodyString(`{"id":1,"repo_id":0,"build_id":2,"number":3,"name":"build","status":"pending","errignore":false,"exit_code":0,"machine":"localhost","os":"linux","arch":"amd64","started":0,"stopped":0,"created":0,"updated":0,"version":1,"on_success":false,"on_failure":false}`).
Reply(200).
Type("application/json").
BodyString(`{"id":1,"repo_id":0,"build_id":2,"number":3,"name":"build","status":"pending","errignore":false,"exit_code":0,"machine":"localhost","os":"linux","arch":"amd64","started":0,"stopped":0,"created":0,"updated":0,"version":2,"on_success":false,"on_failure":false}`)
before := &core.Stage{
ID: 1,
BuildID: 2,
Number: 3,
Name: "build",
Machine: "localhost",
OS: "linux",
Arch: "amd64",
Status: core.StatusPending,
ExitCode: 0,
Version: 1,
}
client := NewClient("http://drone.company.com", "correct-horse-battery-staple")
gock.InterceptClient(client.client.HTTPClient)
err := client.AfterAll(noContext, before)
if err != nil {
t.Error(err)
}
after := &core.Stage{
ID: 1,
BuildID: 2,
Number: 3,
Name: "build",
Machine: "localhost",
OS: "linux",
Arch: "amd64",
Status: core.StatusPending,
ExitCode: 0,
Version: 2,
}
if diff := cmp.Diff(before, after); diff != "" {
t.Errorf(diff)
}
if gock.IsPending() {
t.Errorf("Unfinished requests")
}
}
func TestBefore_OptimisticLock(t *testing.T) {
defer gock.Off()
gock.New("http://drone.company.com").
Post("/rpc/v1/before").
Reply(409)
client := NewClient("http://drone.company.com", "correct-horse-battery-staple")
gock.InterceptClient(client.client.HTTPClient)
err := client.Before(noContext, new(core.Step))
if err != db.ErrOptimisticLock {
t.Errorf("Want optimistic lock error")
}
if gock.IsPending() {
t.Errorf("Unfinished requests")
}
}
func TestAfter_OptimisticLock(t *testing.T) {
defer gock.Off()
gock.New("http://drone.company.com").
Post("/rpc/v1/after").
Reply(409)
client := NewClient("http://drone.company.com", "correct-horse-battery-staple")
gock.InterceptClient(client.client.HTTPClient)
err := client.After(noContext, new(core.Step))
if err != db.ErrOptimisticLock {
t.Errorf("Want optimistic lock error")
}
if gock.IsPending() {
t.Errorf("Unfinished requests")
}
}
func TestBeforeAll_OptimisticLock(t *testing.T) {
defer gock.Off()
gock.New("http://drone.company.com").
Post("/rpc/v1/beforeAll").
Reply(409)
client := NewClient("http://drone.company.com", "correct-horse-battery-staple")
gock.InterceptClient(client.client.HTTPClient)
err := client.BeforeAll(noContext, new(core.Stage))
if err != db.ErrOptimisticLock {
t.Errorf("Want optimistic lock error")
}
if gock.IsPending() {
t.Errorf("Unfinished requests")
}
}
func TestAfterAll_OptimisticLock(t *testing.T) {
defer gock.Off()
gock.New("http://drone.company.com").
Post("/rpc/v1/afterAll").
Reply(409)
client := NewClient("http://drone.company.com", "correct-horse-battery-staple")
gock.InterceptClient(client.client.HTTPClient)
err := client.AfterAll(noContext, new(core.Stage))
if err != db.ErrOptimisticLock {
t.Errorf("Want optimistic lock error")
}
if gock.IsPending() {
t.Errorf("Unfinished requests")
}
}
func TestWatch(t *testing.T) {
defer gock.Off()
gock.New("http://drone.company.com").
Post("/rpc/v1/watch").
MatchHeader("X-Drone-Token", "correct-horse-battery-staple").
BodyString(`{"Build":1}`).
Reply(200).
Type("application/json").
BodyString(`{"Done":true}`)
client := NewClient("http://drone.company.com", "correct-horse-battery-staple")
gock.InterceptClient(client.client.HTTPClient)
done, err := client.Watch(noContext, 1)
if err != nil {
t.Error(err)
}
if !done {
t.Errorf("Want done=true, got false")
}
if gock.IsPending() {
t.Errorf("Unfinished requests")
}
}
func TestWrite(t *testing.T) {
defer gock.Off()
gock.New("http://drone.company.com").
Post("/rpc/v1/write").
MatchHeader("X-Drone-Token", "correct-horse-battery-staple").
BodyString(`{"pos":1,"out":"whoami","time":0}`).
Reply(204)
client := NewClient("http://drone.company.com", "correct-horse-battery-staple")
gock.InterceptClient(client.client.HTTPClient)
err := client.Write(noContext, 1, &core.Line{Number: 1, Message: "whoami", Timestamp: 0})
if err != nil {
t.Error(err)
}
if gock.IsPending() {
t.Errorf("Unfinished requests")
}
}
func TestUpload(t *testing.T) {
defer gock.Off()
buf := bytes.NewBufferString(`[{"pos":1,"out":"whoami","time":0}]`)
gock.New("http://drone.company.com").
Post("/rpc/v1/upload").
MatchParam("id", "1").
MatchHeader("X-Drone-Token", "correct-horse-battery-staple").
BodyString(`[{"pos":1,"out":"whoami","time":0}]`).
Reply(200)
client := NewClient("http://drone.company.com", "correct-horse-battery-staple")
gock.InterceptClient(client.client.HTTPClient)
err := client.Upload(noContext, 1, buf)
if err != nil {
t.Error(err)
}
if gock.IsPending() {
t.Errorf("Unfinished requests")
}
}
// func xTestRetrySend(t *testing.T) {
// defer gock.Off()
// gock.New("http://drone.company.com").
// Post("/rpc/v1/write").
// Times(5).
// Reply(http.StatusBadGateway)
// client := NewClient("http://drone.company.com", "correct-horse-battery-staple").(*Client)
// err := client.retrySend("http://drone.company.com/rpc/v1/write", nil, nil)
// if serr, ok := err.(*serverError); !ok || serr.Status != http.StatusBadGateway {
// t.Errorf("Want bad gateway error, got %d", serr.Status)
// }
// if gock.IsPending() {
// t.Errorf("Unfinished requests")
// }
// }