Commit 8b4a553eee
Verified · cmc
Layout: unified · split
internal/config/config.go +8 −3
| @@ -7,6 +7,7 @@ import ( | ||
| 7 | 7 | "encoding/pem" |
| 8 | 8 | "errors" |
| 9 | 9 | "fmt" |
| 10 | "math" | |
| 10 | 11 | "net" |
| 11 | 12 | "os" |
| 12 | 13 | "path/filepath" |
| @@ -236,7 +237,8 @@ type Limits struct { | ||
| 236 | 237 | } |
| 237 | 238 | |
| 238 | 239 | // PackLimits resolves the pack_* settings for packlimit.New. A zero |
| 239 | // count is no bound. | |
| 240 | // max or per is no bound; an unbounded queue is math.MaxInt, since | |
| 241 | // packlimit reads a zero queue as no queue at all. | |
| 240 | 242 | func (l Limits) PackLimits() (max, per, queue int, wait time.Duration) { |
| 241 | 243 | pick := func(v, def int) int { |
| 242 | 244 | switch { |
| @@ -247,13 +249,16 @@ func (l Limits) PackLimits() (max, per, queue int, wait time.Duration) { | ||
| 247 | 249 | } |
| 248 | 250 | return v |
| 249 | 251 | } |
| 252 | queue = pick(l.PackQueue, DefaultPackQueue) | |
| 253 | if l.PackQueue < 0 { | |
| 254 | queue = math.MaxInt | |
| 255 | } | |
| 250 | 256 | wait = DefaultPackQueueWait |
| 251 | 257 | if d, err := time.ParseDuration(l.PackQueueWait); err == nil && d > 0 { |
| 252 | 258 | wait = d |
| 253 | 259 | } |
| 254 | 260 | return pick(l.PackConcurrency, DefaultPackConcurrency), |
| 255 | pick(l.PackPerPrincipal, DefaultPackPerPrincipal), | |
| 256 | pick(l.PackQueue, DefaultPackQueue), wait | |
| 261 | pick(l.PackPerPrincipal, DefaultPackPerPrincipal), queue, wait | |
| 257 | 262 | } |
| 258 | 263 | |
| 259 | 264 | type Mail struct { |
internal/config/config_test.go +16 −15
| @@ -6,6 +6,7 @@ import ( | ||
| 6 | 6 | "crypto/rand" |
| 7 | 7 | "crypto/x509" |
| 8 | 8 | "encoding/pem" |
| 9 | "math" | |
| 9 | 10 | "os" |
| 10 | 11 | "path/filepath" |
| 11 | 12 | "strings" |
| @@ -47,6 +48,21 @@ func TestLoadMinimal(t *testing.T) { | ||
| 47 | 48 | } |
| 48 | 49 | } |
| 49 | 50 | |
| 51 | func TestPackLimits(t *testing.T) { | |
| 52 | max, per, queue, wait := Limits{}.PackLimits() | |
| 53 | if max != DefaultPackConcurrency || per != DefaultPackPerPrincipal || queue != DefaultPackQueue || wait != DefaultPackQueueWait { | |
| 54 | t.Fatalf("defaults: %d %d %d %s", max, per, queue, wait) | |
| 55 | } | |
| 56 | max, per, queue, wait = Limits{PackConcurrency: -1, PackPerPrincipal: -1, PackQueue: -1, PackQueueWait: "5s"}.PackLimits() | |
| 57 | if max != 0 || per != 0 || queue != math.MaxInt || wait != 5*time.Second { | |
| 58 | t.Fatalf("off: %d %d %d %s", max, per, queue, wait) | |
| 59 | } | |
| 60 | max, per, queue, _ = Limits{PackConcurrency: 8, PackPerPrincipal: 3, PackQueue: 64}.PackLimits() | |
| 61 | if max != 8 || per != 3 || queue != 64 { | |
| 62 | t.Fatalf("set: %d %d %d", max, per, queue) | |
| 63 | } | |
| 64 | } | |
| 65 | ||
| 50 | 66 | func TestContradictions(t *testing.T) { |
| 51 | 67 | cases := []struct { |
| 52 | 68 | name string |
| @@ -395,18 +411,3 @@ func TestBackupRecipients(t *testing.T) { | ||
| 395 | 411 | t.Fatalf("default: %v, %v", cfg.Backup, err) |
| 396 | 412 | } |
| 397 | 413 | } |
| 398 | ||
| 399 | func TestPackLimits(t *testing.T) { | |
| 400 | max, per, queue, wait := Limits{}.PackLimits() | |
| 401 | if max != DefaultPackConcurrency || per != DefaultPackPerPrincipal || queue != DefaultPackQueue || wait != DefaultPackQueueWait { | |
| 402 | t.Fatalf("defaults: %d %d %d %s", max, per, queue, wait) | |
| 403 | } | |
| 404 | max, per, queue, wait = Limits{PackConcurrency: -1, PackPerPrincipal: -1, PackQueue: -1, PackQueueWait: "5s"}.PackLimits() | |
| 405 | if max != 0 || per != 0 || queue != 0 || wait != 5*time.Second { | |
| 406 | t.Fatalf("off: %d %d %d %s", max, per, queue, wait) | |
| 407 | } | |
| 408 | max, per, queue, _ = Limits{PackConcurrency: 8, PackPerPrincipal: 3, PackQueue: 64}.PackLimits() | |
| 409 | if max != 8 || per != 3 || queue != 64 { | |
| 410 | t.Fatalf("set: %d %d %d", max, per, queue) | |
| 411 | } | |
| 412 | } | |
internal/packlimit/packlimit_test.go +15
| @@ -2,6 +2,7 @@ package packlimit | ||
| 2 | 2 | |
| 3 | 3 | import ( |
| 4 | 4 | "errors" |
| 5 | "math" | |
| 5 | 6 | "testing" |
| 6 | 7 | "time" |
| 7 | 8 | ) |
| @@ -207,3 +208,17 @@ func waitQueued(t *testing.T, l *Limiter, n int) { | ||
| 207 | 208 | } |
| 208 | 209 | t.Fatalf("queue never reached %d", n) |
| 209 | 210 | } |
| 211 | ||
| 212 | // config maps pack_queue = -1 to math.MaxInt: waiters are not turned | |
| 213 | // away for want of queue room. | |
| 214 | func TestUnboundedQueue(t *testing.T) { | |
| 215 | l := New(1, 0, math.MaxInt, 5*time.Second) | |
| 216 | r1, _ := l.Acquire(nil, "a") | |
| 217 | done := make(chan struct{}) | |
| 218 | defer close(done) | |
| 219 | for i := 0; i < 64; i++ { | |
| 220 | go l.Acquire(done, "b") | |
| 221 | } | |
| 222 | waitQueued(t, l, 64) | |
| 223 | r1() | |
| 224 | } | |