Check timeout with test
This commit is contained in:
parent
134c5508c1
commit
a1228eddc3
|
@ -9,8 +9,10 @@ import (
|
||||||
yaml "gopkg.in/yaml.v2"
|
yaml "gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var configFile = flag.String("config", "/etc/nginx-ldap-auth/config.yaml", "Configuration file")
|
var (
|
||||||
var config Config
|
configFile = flag.String("config", "/etc/nginx-ldap-auth/config.yaml", "Configuration file")
|
||||||
|
config Config
|
||||||
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
|
@ -17,7 +17,7 @@ type userpass struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
passwords map[string]userpass
|
passwords = map[string]*userpass{}
|
||||||
mutex = sync.RWMutex{}
|
mutex = sync.RWMutex{}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ func containsWrongPassword(data *userpass, password string) (int, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pos := sort.Search(size, func(i int) bool {
|
pos := sort.Search(size, func(i int) bool {
|
||||||
return data.wrong[i].password < password
|
return data.wrong[i].password >= password
|
||||||
})
|
})
|
||||||
|
|
||||||
return pos, pos < size &&
|
return pos, pos < size &&
|
||||||
|
@ -48,7 +48,7 @@ func getCache(username, password string) (bool, bool) {
|
||||||
return true, true
|
return true, true
|
||||||
}
|
}
|
||||||
|
|
||||||
_, found = containsWrongPassword(&data, password)
|
_, found = containsWrongPassword(data, password)
|
||||||
|
|
||||||
return false, found
|
return false, found
|
||||||
}
|
}
|
||||||
|
@ -59,28 +59,29 @@ func putCache(username, password string, ok bool) {
|
||||||
|
|
||||||
data, found := passwords[username]
|
data, found := passwords[username]
|
||||||
if !found {
|
if !found {
|
||||||
data = userpass{}
|
data = &userpass{}
|
||||||
passwords[username] = data
|
passwords[username] = data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
timeout := config.Timeout.Wrong
|
||||||
|
if ok {
|
||||||
|
timeout = config.Timeout.Success
|
||||||
|
}
|
||||||
|
|
||||||
|
pass := passtimer{
|
||||||
|
password: password,
|
||||||
|
timer: time.AfterFunc(timeout, func() {
|
||||||
|
removeCache(username, password, ok)
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
if ok {
|
if ok {
|
||||||
if data.correct != nil {
|
if data.correct != nil {
|
||||||
data.correct.timer.Stop()
|
data.correct.timer.Stop()
|
||||||
}
|
}
|
||||||
data.correct = &passtimer{
|
data.correct = &pass
|
||||||
password: password,
|
|
||||||
timer: time.AfterFunc(config.Timeout.Success, func() {
|
|
||||||
removeCache(username, "", true)
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
pass := passtimer{
|
pos, found := containsWrongPassword(data, password)
|
||||||
password: password,
|
|
||||||
timer: time.AfterFunc(config.Timeout.Wrong, func() {
|
|
||||||
removeCache(username, password, false)
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
pos, found := containsWrongPassword(&data, password)
|
|
||||||
if found {
|
if found {
|
||||||
data.wrong[pos].timer.Stop()
|
data.wrong[pos].timer.Stop()
|
||||||
} else {
|
} else {
|
||||||
|
@ -106,7 +107,7 @@ func removeCache(username, password string, ok bool) {
|
||||||
data.correct = nil
|
data.correct = nil
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pos, found := containsWrongPassword(&data, password)
|
pos, found := containsWrongPassword(data, password)
|
||||||
if found {
|
if found {
|
||||||
data.wrong[pos].timer.Stop()
|
data.wrong[pos].timer.Stop()
|
||||||
data.wrong = data.wrong[:pos+copy(data.wrong[pos:], data.wrong[pos+1:])]
|
data.wrong = data.wrong[:pos+copy(data.wrong[pos:], data.wrong[pos+1:])]
|
||||||
|
|
88
src/timeout_test.go
Normal file
88
src/timeout_test.go
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
username1 = "Alice"
|
||||||
|
username2 = "James"
|
||||||
|
password1 = "master"
|
||||||
|
password2 = "shadow"
|
||||||
|
password3 = "qwerty"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
config.Timeout.Success = time.Second / 2
|
||||||
|
config.Timeout.Wrong = time.Second / 5
|
||||||
|
os.Exit(m.Run())
|
||||||
|
}
|
||||||
|
|
||||||
|
func printPassMap(t *testing.T, prefix string) {
|
||||||
|
buffer := bytes.Buffer{}
|
||||||
|
first := true
|
||||||
|
for k, v := range passwords {
|
||||||
|
if first {
|
||||||
|
first = false
|
||||||
|
} else {
|
||||||
|
buffer.WriteByte(',')
|
||||||
|
}
|
||||||
|
correct := "<nil>"
|
||||||
|
if v.correct != nil {
|
||||||
|
correct = v.correct.password
|
||||||
|
}
|
||||||
|
fmt.Fprintf(&buffer, "%s:{correct:%s,wrong:%+v}", k, correct, v.wrong)
|
||||||
|
}
|
||||||
|
t.Logf("%s passwords: %s\n", prefix, buffer.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func testCache(t *testing.T, id int, username, password string, eok, efound bool) {
|
||||||
|
ok, found := getCache(username, password)
|
||||||
|
if ok != eok || found != efound {
|
||||||
|
t.Errorf("Test %d expected (%v %v) given (%v %v)\n", id, eok, efound, ok, found)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPasswordTimeout(t *testing.T) {
|
||||||
|
testCache(t, 0, username1, password1, false, false)
|
||||||
|
testCache(t, 1, username1, password2, false, false)
|
||||||
|
testCache(t, 2, username1, password3, false, false)
|
||||||
|
testCache(t, 3, username2, password1, false, false)
|
||||||
|
testCache(t, 4, username2, password2, false, false)
|
||||||
|
testCache(t, 5, username2, password3, false, false)
|
||||||
|
|
||||||
|
putCache(username1, password1, true)
|
||||||
|
putCache(username1, password3, false)
|
||||||
|
printPassMap(t, "add")
|
||||||
|
|
||||||
|
testCache(t, 6, username1, password1, true, true)
|
||||||
|
testCache(t, 7, username1, password2, false, false)
|
||||||
|
testCache(t, 8, username1, password3, false, true)
|
||||||
|
testCache(t, 9, username2, password1, false, false)
|
||||||
|
testCache(t, 10, username2, password2, false, false)
|
||||||
|
testCache(t, 11, username2, password3, false, false)
|
||||||
|
|
||||||
|
time.Sleep(config.Timeout.Wrong + config.Timeout.Wrong/2)
|
||||||
|
printPassMap(t, "timed")
|
||||||
|
|
||||||
|
testCache(t, 12, username1, password1, true, true)
|
||||||
|
testCache(t, 13, username1, password2, false, false)
|
||||||
|
testCache(t, 14, username1, password3, false, false)
|
||||||
|
testCache(t, 15, username2, password1, false, false)
|
||||||
|
testCache(t, 16, username2, password2, false, false)
|
||||||
|
testCache(t, 17, username2, password3, false, false)
|
||||||
|
|
||||||
|
time.Sleep(config.Timeout.Success - config.Timeout.Wrong)
|
||||||
|
printPassMap(t, "expired")
|
||||||
|
|
||||||
|
testCache(t, 18, username1, password1, false, false)
|
||||||
|
testCache(t, 19, username1, password2, false, false)
|
||||||
|
testCache(t, 20, username1, password3, false, false)
|
||||||
|
testCache(t, 21, username2, password1, false, false)
|
||||||
|
testCache(t, 22, username2, password2, false, false)
|
||||||
|
testCache(t, 23, username2, password3, false, false)
|
||||||
|
}
|
Reference in a new issue