Add more tests and CI
continuous-integration/woodpecker the build failed
Details
continuous-integration/woodpecker the build failed
Details
Signed-off-by: jolheiser <john.olheiser@gmail.com>main
parent
15d69e947d
commit
dffcd8a537
|
@ -0,0 +1,54 @@
|
||||||
|
clone:
|
||||||
|
git:
|
||||||
|
image: woodpeckerci/plugin-git:next
|
||||||
|
|
||||||
|
pipeline:
|
||||||
|
compliance:
|
||||||
|
image: golang:1.17
|
||||||
|
commands:
|
||||||
|
- go test -race ./...
|
||||||
|
- go vet ./...
|
||||||
|
when:
|
||||||
|
event: pull_request
|
||||||
|
|
||||||
|
build:
|
||||||
|
image: golang:1.17
|
||||||
|
commands:
|
||||||
|
- GOOS="linux" go build go.jolheiser.com/cabinet/cmd/cabinet
|
||||||
|
- GOOS="windows" go build go.jolheiser.com/cabinet/cmd/cabinet
|
||||||
|
|
||||||
|
release-main:
|
||||||
|
image: jolheiser/drone-gitea-main:latest
|
||||||
|
settings:
|
||||||
|
base_url: https://git.jojodev.com
|
||||||
|
api_key:
|
||||||
|
from_secret: gitea_token
|
||||||
|
files:
|
||||||
|
- "cabinet"
|
||||||
|
- "cabinet.exe"
|
||||||
|
when:
|
||||||
|
event: push
|
||||||
|
branch: main
|
||||||
|
|
||||||
|
release-tag:
|
||||||
|
image: plugins/gitea-release:1
|
||||||
|
settings:
|
||||||
|
base_url: https://git.jojodev.com
|
||||||
|
api_key:
|
||||||
|
from_secret: gitea_token
|
||||||
|
files:
|
||||||
|
- "cabinet"
|
||||||
|
- "cabinet.exe"
|
||||||
|
when:
|
||||||
|
event: tag
|
||||||
|
tag: v*
|
||||||
|
|
||||||
|
prune:
|
||||||
|
image: jolheiser/drone-gitea-prune
|
||||||
|
settings:
|
||||||
|
api_key:
|
||||||
|
from_secret: gitea_token
|
||||||
|
base: https://git.jojodev.com
|
||||||
|
when:
|
||||||
|
event: tag
|
||||||
|
tag: v*
|
|
@ -12,7 +12,6 @@ import (
|
||||||
workspace2 "go.jolheiser.com/cabinet/internal/workspace"
|
workspace2 "go.jolheiser.com/cabinet/internal/workspace"
|
||||||
|
|
||||||
"github.com/AlecAivazis/survey/v2"
|
"github.com/AlecAivazis/survey/v2"
|
||||||
|
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
|
@ -98,5 +98,10 @@ func (l *Limit) hasHitSizeLimit(remoteAddr string, size int64) bool {
|
||||||
l.mx.Lock()
|
l.mx.Lock()
|
||||||
defer l.mx.Unlock()
|
defer l.mx.Unlock()
|
||||||
|
|
||||||
|
if l.request[ip] == nil {
|
||||||
|
l.request[ip] = rate.NewLimiter(rate.Limit(l.rpm/60), l.rpm)
|
||||||
|
l.size[ip] = rate.NewLimiter(rate.Limit(l.spm/60), l.burst)
|
||||||
|
}
|
||||||
|
|
||||||
return !l.size[ip].AllowN(time.Now(), int(size))
|
return !l.size[ip].AllowN(time.Now(), int(size))
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
package router
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/matryer/is"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLimit(t *testing.T) {
|
||||||
|
localhost := "127.0.0.1:80"
|
||||||
|
|
||||||
|
t.Run("Requests Per Minute", func(t *testing.T) {
|
||||||
|
assert := is.New(t)
|
||||||
|
limit := NewLimit(5, 5, 10, 10)
|
||||||
|
for idx := 0; idx < 5; idx++ {
|
||||||
|
assert.Equal(limit.hasHitRequestLimit(localhost), false) // Five requests is okay
|
||||||
|
}
|
||||||
|
assert.Equal(limit.hasHitRequestLimit(localhost), true) // A sixth requests is not okay
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Size Per Minute", func(t *testing.T) {
|
||||||
|
assert := is.New(t)
|
||||||
|
limit := NewLimit(5, 5, 5, 10)
|
||||||
|
for idx := 0; idx < 5; idx++ {
|
||||||
|
assert.Equal(limit.hasHitSizeLimit(localhost, 1), false) // Five requests is okay
|
||||||
|
}
|
||||||
|
assert.Equal(limit.hasHitSizeLimit(localhost, 1), true) // A sixth requests is not okay
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Size Per Minute w/Burst", func(t *testing.T) {
|
||||||
|
assert := is.New(t)
|
||||||
|
limit := NewLimit(5, 5, 10, 10)
|
||||||
|
for idx := 0; idx < 10; idx++ {
|
||||||
|
assert.Equal(limit.hasHitSizeLimit(localhost, 1), false) // Ten requests is okay (with Burst)
|
||||||
|
}
|
||||||
|
assert.Equal(limit.hasHitSizeLimit(localhost, 1), true) // An eleventh requests is not okay (with Burst)
|
||||||
|
})
|
||||||
|
}
|
|
@ -7,13 +7,16 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/matryer/is"
|
|
||||||
"go.jolheiser.com/cabinet"
|
"go.jolheiser.com/cabinet"
|
||||||
|
"go.jolheiser.com/cabinet/internal/workspace"
|
||||||
"go.jolheiser.com/cabinet/internal/workspace/mock"
|
"go.jolheiser.com/cabinet/internal/workspace/mock"
|
||||||
|
|
||||||
|
"github.com/matryer/is"
|
||||||
|
"github.com/rs/zerolog"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRouter(t *testing.T) {
|
func TestRouter(t *testing.T) {
|
||||||
assert := is.New(t)
|
zerolog.SetGlobalLevel(zerolog.Disabled)
|
||||||
|
|
||||||
m := mock.New()
|
m := mock.New()
|
||||||
server := httptest.NewUnstartedServer(nil)
|
server := httptest.NewUnstartedServer(nil)
|
||||||
|
@ -24,20 +27,68 @@ func TestRouter(t *testing.T) {
|
||||||
|
|
||||||
c := cabinet.New(server.URL, cabinet.WithHTTPClient(server.Client()))
|
c := cabinet.New(server.URL, cabinet.WithHTTPClient(server.Client()))
|
||||||
|
|
||||||
|
testRouter(t, "No Token", true, true, c)
|
||||||
|
|
||||||
|
// All token
|
||||||
|
aToken := workspace.Token{Key: "all", Permission: workspace.TokenFile | workspace.TokenRedirect}
|
||||||
|
_ = m.AddToken(aToken)
|
||||||
|
testRouter(t, "Incorrect Token", false, false, c)
|
||||||
|
c.Token = aToken.Key
|
||||||
|
testRouter(t, "All Token", true, true, c)
|
||||||
|
|
||||||
|
// Redirect token
|
||||||
|
rToken := workspace.Token{Key: "redirect", Permission: workspace.TokenRedirect}
|
||||||
|
_ = m.AddToken(rToken)
|
||||||
|
c.Token = rToken.Key
|
||||||
|
testRouter(t, "Redirect Token", true, false, c)
|
||||||
|
|
||||||
|
// File token
|
||||||
|
fToken := workspace.Token{Key: "file", Permission: workspace.TokenFile}
|
||||||
|
_ = m.AddToken(fToken)
|
||||||
|
c.Token = fToken.Key
|
||||||
|
testRouter(t, "File Token", false, true, c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testRouter(t *testing.T, name string, rSucceed, fSucceed bool, c *cabinet.Client) {
|
||||||
// Redirect
|
// Redirect
|
||||||
|
t.Run(name+" Redirect", func(t *testing.T) {
|
||||||
|
assert := is.New(t)
|
||||||
redir := "https://duckduckgo.com"
|
redir := "https://duckduckgo.com"
|
||||||
u, _, err := c.Redirect(redir)
|
u, res, err := c.Redirect(redir)
|
||||||
|
switch {
|
||||||
|
case rSucceed:
|
||||||
assert.NoErr(err) // Creating a redirect should succeed
|
assert.NoErr(err) // Creating a redirect should succeed
|
||||||
resp, err := http.Get(u)
|
resp, err := http.Get(u)
|
||||||
assert.NoErr(err)
|
assert.NoErr(err)
|
||||||
assert.Equal(redir, resp.Request.URL.String()) // The redirect should match what was given
|
assert.Equal(redir, resp.Request.URL.String()) // The redirect should match what was given
|
||||||
|
case c.Token == "":
|
||||||
|
assert.Equal(res.StatusCode, http.StatusUnauthorized) // Creating a redirect should be unauthorized
|
||||||
|
case c.Token != "":
|
||||||
|
assert.Equal(res.StatusCode, http.StatusForbidden) // Creating a redirect should be forbidden
|
||||||
|
default:
|
||||||
|
assert.Fail() // Unknown case in test
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// File
|
||||||
|
t.Run(name+" File", func(t *testing.T) {
|
||||||
|
assert := is.New(t)
|
||||||
file := "foobar"
|
file := "foobar"
|
||||||
f, _, err := c.File("test.txt", strings.NewReader(file))
|
f, res, err := c.File("test.txt", strings.NewReader(file))
|
||||||
|
switch {
|
||||||
|
case fSucceed:
|
||||||
assert.NoErr(err) // Creating a file should succeed
|
assert.NoErr(err) // Creating a file should succeed
|
||||||
resp, err = http.Get(f)
|
resp, err := http.Get(f)
|
||||||
assert.NoErr(err)
|
assert.NoErr(err)
|
||||||
b, err := io.ReadAll(resp.Body)
|
b, err := io.ReadAll(resp.Body)
|
||||||
assert.NoErr(err)
|
assert.NoErr(err)
|
||||||
assert.Equal(file, string(b)) // The file should match what was given
|
assert.Equal(file, string(b)) // The file should match what was given
|
||||||
|
case c.Token == "":
|
||||||
|
assert.Equal(res.StatusCode, http.StatusUnauthorized) // Creating a redirect should be unauthorized
|
||||||
|
case c.Token != "":
|
||||||
|
assert.Equal(res.StatusCode, http.StatusForbidden) // Creating a redirect should be forbidden
|
||||||
|
default:
|
||||||
|
assert.Fail() // Unknown case in test
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue