mirror of
https://github.com/caddyserver/caddy.git
synced 2025-02-02 13:15:04 +08:00
diagnostics: Add a few tests
This commit is contained in:
parent
388ff6bc0a
commit
6c17e4d4c8
|
@ -32,7 +32,8 @@ func Init(instanceID uuid.UUID) {
|
||||||
if enabled {
|
if enabled {
|
||||||
panic("already initialized")
|
panic("already initialized")
|
||||||
}
|
}
|
||||||
if instanceID.String() == "" {
|
if str := instanceID.String(); str == "" ||
|
||||||
|
instanceID.String() == "00000000-0000-0000-0000-000000000000" {
|
||||||
panic("empty UUID")
|
panic("empty UUID")
|
||||||
}
|
}
|
||||||
instanceUUID = instanceID
|
instanceUUID = instanceID
|
||||||
|
|
109
diagnostics/collection_test.go
Normal file
109
diagnostics/collection_test.go
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
// Copyright 2015 Light Code Labs, LLC
|
||||||
|
//
|
||||||
|
// 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 diagnostics
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestInit(t *testing.T) {
|
||||||
|
reset()
|
||||||
|
|
||||||
|
id := doInit(t) // should not panic
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r == nil {
|
||||||
|
t.Errorf("Second call to Init should have panicked")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
Init(id) // should panic
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInitEmptyUUID(t *testing.T) {
|
||||||
|
reset()
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r == nil {
|
||||||
|
t.Errorf("Call to Init with empty UUID should have panicked")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
Init(uuid.UUID([16]byte{}))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSet(t *testing.T) {
|
||||||
|
reset()
|
||||||
|
|
||||||
|
// should be no-op since we haven't called Init() yet
|
||||||
|
Set("test1", "foobar")
|
||||||
|
if _, ok := buffer["test"]; ok {
|
||||||
|
t.Errorf("Should not have inserted item when not initialized")
|
||||||
|
}
|
||||||
|
|
||||||
|
// should work after we've initialized
|
||||||
|
doInit(t)
|
||||||
|
Set("test1", "foobar")
|
||||||
|
val, ok := buffer["test1"]
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("Expected value to be in buffer, but it wasn't")
|
||||||
|
} else if val.(string) != "foobar" {
|
||||||
|
t.Errorf("Expected 'foobar', got '%v'", val)
|
||||||
|
}
|
||||||
|
|
||||||
|
// should not overfill buffer
|
||||||
|
maxBufferItemsTmp := maxBufferItems
|
||||||
|
maxBufferItems = 10
|
||||||
|
for i := 0; i < maxBufferItems+1; i++ {
|
||||||
|
Set(fmt.Sprintf("overfill_%d", i), "foobar")
|
||||||
|
}
|
||||||
|
if len(buffer) > maxBufferItems {
|
||||||
|
t.Errorf("Should not exceed max buffer size (%d); has %d items",
|
||||||
|
maxBufferItems, len(buffer))
|
||||||
|
}
|
||||||
|
maxBufferItems = maxBufferItemsTmp
|
||||||
|
|
||||||
|
// Should overwrite values
|
||||||
|
Set("test1", "foobar2")
|
||||||
|
val, ok = buffer["test1"]
|
||||||
|
if !ok {
|
||||||
|
t.Errorf("Expected value to be in buffer, but it wasn't")
|
||||||
|
} else if val.(string) != "foobar2" {
|
||||||
|
t.Errorf("Expected 'foobar2', got '%v'", val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// doInit calls Init() with a valid UUID
|
||||||
|
// and returns it.
|
||||||
|
func doInit(t *testing.T) uuid.UUID {
|
||||||
|
id, err := uuid.Parse(testUUID)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Could not make UUID: %v", err)
|
||||||
|
}
|
||||||
|
Init(id)
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset resets all the lovely package-level state;
|
||||||
|
// can be used as a set up function in tests.
|
||||||
|
func reset() {
|
||||||
|
instanceUUID = uuid.UUID{}
|
||||||
|
buffer = make(map[string]interface{})
|
||||||
|
bufferItemCount = 0
|
||||||
|
updating = false
|
||||||
|
enabled = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const testUUID = "0b6cfa22-0d4c-11e8-b11b-7a0058e13201"
|
|
@ -216,32 +216,39 @@ type Payload struct {
|
||||||
Data map[string]interface{} `json:"data,omitempty"`
|
Data map[string]interface{} `json:"data,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// httpClient should be used for HTTP requests. It
|
var (
|
||||||
// is configured with a timeout for reliability.
|
// httpClient should be used for HTTP requests. It
|
||||||
var httpClient = http.Client{Timeout: 1 * time.Minute}
|
// is configured with a timeout for reliability.
|
||||||
|
httpClient = http.Client{Timeout: 1 * time.Minute}
|
||||||
|
|
||||||
// buffer holds the data that we are building up to send.
|
// buffer holds the data that we are building up to send.
|
||||||
var buffer = make(map[string]interface{})
|
buffer = make(map[string]interface{})
|
||||||
var bufferItemCount = 0
|
bufferItemCount = 0
|
||||||
var bufferMu sync.RWMutex // protects both the buffer and its count
|
bufferMu sync.RWMutex // protects both the buffer and its count
|
||||||
|
|
||||||
// updating is used to ensure only one
|
// updating is used to ensure only one
|
||||||
// update happens at a time.
|
// update happens at a time.
|
||||||
var updating bool
|
updating bool
|
||||||
var updateMu sync.Mutex
|
updateMu sync.Mutex
|
||||||
|
|
||||||
// updateTimer fires off the next update.
|
// updateTimer fires off the next update.
|
||||||
// If no update is scheduled, this is nil.
|
// If no update is scheduled, this is nil.
|
||||||
var updateTimer *time.Timer
|
updateTimer *time.Timer
|
||||||
var updateTimerMu sync.Mutex
|
updateTimerMu sync.Mutex
|
||||||
|
|
||||||
// instanceUUID is the ID of the current instance.
|
// instanceUUID is the ID of the current instance.
|
||||||
// This MUST be set to emit diagnostics.
|
// This MUST be set to emit diagnostics.
|
||||||
var instanceUUID uuid.UUID
|
instanceUUID uuid.UUID
|
||||||
|
|
||||||
// enabled indicates whether the package has
|
// enabled indicates whether the package has
|
||||||
// been initialized and can be actively used.
|
// been initialized and can be actively used.
|
||||||
var enabled bool
|
enabled bool
|
||||||
|
|
||||||
|
// maxBufferItems is the maximum number of items we'll allow
|
||||||
|
// in the buffer before we start dropping new ones, in a
|
||||||
|
// rough (simple) attempt to keep memory use under control.
|
||||||
|
maxBufferItems = 100000
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// endpoint is the base URL to remote diagnostics server;
|
// endpoint is the base URL to remote diagnostics server;
|
||||||
|
@ -255,9 +262,4 @@ const (
|
||||||
// this value should be a long duration to help alleviate
|
// this value should be a long duration to help alleviate
|
||||||
// extra load on the server.
|
// extra load on the server.
|
||||||
defaultUpdateInterval = 1 * time.Hour
|
defaultUpdateInterval = 1 * time.Hour
|
||||||
|
|
||||||
// maxBufferItems is the maximum number of items we'll allow
|
|
||||||
// in the buffer before we start dropping new ones, in a
|
|
||||||
// rough (simple) attempt to keep memory use under control.
|
|
||||||
maxBufferItems = 100000
|
|
||||||
)
|
)
|
||||||
|
|
59
diagnostics/diagnostics_test.go
Normal file
59
diagnostics/diagnostics_test.go
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
// Copyright 2015 Light Code Labs, LLC
|
||||||
|
//
|
||||||
|
// 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 diagnostics
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMakePayloadAndResetBuffer(t *testing.T) {
|
||||||
|
reset()
|
||||||
|
id := doInit(t)
|
||||||
|
|
||||||
|
buffer = map[string]interface{}{
|
||||||
|
"foo1": "bar1",
|
||||||
|
"foo2": "bar2",
|
||||||
|
}
|
||||||
|
bufferItemCount = 2
|
||||||
|
|
||||||
|
payloadBytes, err := makePayloadAndResetBuffer()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error making payload bytes: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(buffer) != 0 {
|
||||||
|
t.Errorf("Expected buffer len to be 0, got %d", len(buffer))
|
||||||
|
}
|
||||||
|
if bufferItemCount != 0 {
|
||||||
|
t.Errorf("Expected buffer item count to be 0, got %d", bufferItemCount)
|
||||||
|
}
|
||||||
|
|
||||||
|
var payload Payload
|
||||||
|
err = json.Unmarshal(payloadBytes, &payload)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error deserializing payload: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if payload.InstanceID != id.String() {
|
||||||
|
t.Errorf("Expected instance ID to be set to '%s' but got '%s'", testUUID, payload.InstanceID)
|
||||||
|
}
|
||||||
|
if payload.Data == nil {
|
||||||
|
t.Errorf("Expected data to be set, but was nil")
|
||||||
|
}
|
||||||
|
if payload.Timestamp.IsZero() {
|
||||||
|
t.Errorf("Expected timestamp to be set, but was zero value")
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user