From a010934299efa90867f2897f674f3b732e04f335 Mon Sep 17 00:00:00 2001 From: Nan Deng Date: Tue, 17 Jun 2014 14:33:32 -0700 Subject: [PATCH 1/3] Close() error --- storage/memory/memory.go | 7 +++++++ storage/storage.go | 2 ++ 2 files changed, 9 insertions(+) diff --git a/storage/memory/memory.go b/storage/memory/memory.go index 1fb5887e..6155448a 100644 --- a/storage/memory/memory.go +++ b/storage/memory/memory.go @@ -204,6 +204,13 @@ func (self *InMemoryStorage) Percentiles(name string, cpuPercentiles, memPercent return cstore.Percentiles(cpuPercentiles, memPercentiles) } +func (self *InMemoryStorage) Close() error { + self.lock.Lock() + self.containerStorageMap = make(map[string]*containerStorage, 32) + self.lock.Unlock() + return nil +} + func New(maxNumSamples, maxNumStats int) storage.StorageDriver { ret := &InMemoryStorage{ containerStorageMap: make(map[string]*containerStorage, 32), diff --git a/storage/storage.go b/storage/storage.go index 84de7b57..7d521eb0 100644 --- a/storage/storage.go +++ b/storage/storage.go @@ -32,4 +32,6 @@ type StorageDriver interface { // the number of returned samples is implementation defined. Otherwise, the driver // should return at most numSamples samples. Samples(containername string, numSamples int) ([]*info.ContainerStatsSample, error) + + Close() error } From 7dd1f031a6e2383cbc5ac925386a2605af2429b5 Mon Sep 17 00:00:00 2001 From: Nan Deng Date: Tue, 17 Jun 2014 14:40:11 -0700 Subject: [PATCH 2/3] unit tests for storage driver implementations --- storage/test/storagetests.go | 171 +++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 storage/test/storagetests.go diff --git a/storage/test/storagetests.go b/storage/test/storagetests.go new file mode 100644 index 00000000..ed460705 --- /dev/null +++ b/storage/test/storagetests.go @@ -0,0 +1,171 @@ +// Copyright 2014 Google Inc. All Rights Reserved. +// +// 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 test + +import ( + "math/rand" + "testing" + "time" + + "github.com/google/cadvisor/info" + "github.com/google/cadvisor/storage" +) + +func buildTrace(cpu, mem []uint64, duration time.Duration) []*info.ContainerStats { + if len(cpu) != len(mem) { + panic("len(cpu) != len(mem)") + } + + ret := make([]*info.ContainerStats, len(cpu)) + currentTime := time.Now() + + var cpuTotalUsage uint64 = 0 + for i, cpuUsage := range cpu { + cpuTotalUsage += cpuUsage + stats := new(info.ContainerStats) + stats.Cpu = new(info.CpuStats) + stats.Memory = new(info.MemoryStats) + stats.Timestamp = currentTime + currentTime = currentTime.Add(duration) + + stats.Cpu.Usage.Total = cpuTotalUsage + stats.Cpu.Usage.User = stats.Cpu.Usage.Total + stats.Cpu.Usage.System = 0 + + stats.Memory.Usage = mem[i] + + ret[i] = stats + } + return ret +} + +func StorageDriverTestSampleCpuUsage(driver storage.StorageDriver, t *testing.T) { + defer driver.Close() + N := 10 + cpuTrace := make([]uint64, 0, N) + memTrace := make([]uint64, 0, N) + + // We need N+1 observations to get N samples + for i := 0; i < N+1; i++ { + cpuusage := uint64(rand.Intn(1000)) + memusage := uint64(rand.Intn(1000)) + cpuTrace = append(cpuTrace, cpuusage) + memTrace = append(memTrace, memusage) + } + + samplePeriod := 1 * time.Second + + ref := info.ContainerReference{ + Name: "container", + } + + trace := buildTrace(cpuTrace, memTrace, samplePeriod) + + for _, stats := range trace { + driver.AddStats(ref, stats) + } + + samples, err := driver.Samples(ref.Name, N) + if err != nil { + t.Errorf("unable to sample stats: %v", err) + } + for _, sample := range samples { + if sample.Duration != samplePeriod { + t.Errorf("sample duration is %v, not %v", sample.Duration, samplePeriod) + } + cpuUsage := sample.Cpu.Usage + found := false + for _, u := range cpuTrace { + if u == cpuUsage { + found = true + } + } + if !found { + t.Errorf("unable to find cpu usage %v", cpuUsage) + } + } +} + +func StorageDriverTestMaxMemoryUsage(driver storage.StorageDriver, t *testing.T) { + defer driver.Close() + N := 100 + memTrace := make([]uint64, N) + cpuTrace := make([]uint64, N) + for i := 0; i < N; i++ { + memTrace[i] = uint64(i + 1) + cpuTrace[i] = uint64(1) + } + + ref := info.ContainerReference{ + Name: "container", + } + + trace := buildTrace(cpuTrace, memTrace, 1*time.Second) + + for _, stats := range trace { + driver.AddStats(ref, stats) + } + + percentiles, err := driver.Percentiles(ref.Name, []int{50}, []int{50}) + if err != nil { + t.Errorf("unable to call Percentiles(): %v", err) + } + maxUsage := uint64(N) + if percentiles.MaxMemoryUsage != maxUsage { + t.Fatalf("Max memory usage should be %v; received %v", maxUsage, percentiles.MaxMemoryUsage) + } +} + +func StorageDriverTestSamplesWithoutSample(driver storage.StorageDriver, t *testing.T) { + defer driver.Close() + trace := buildTrace( + []uint64{10}, + []uint64{10}, + 1*time.Second) + ref := info.ContainerReference{ + Name: "container", + } + driver.AddStats(ref, trace[0]) + samples, err := driver.Samples(ref.Name, -1) + if err != nil { + t.Fatal(err) + } + if len(samples) != 0 { + t.Errorf("There should be no sample") + } +} + +func StorageDriverTestPercentilesWithoutSample(driver storage.StorageDriver, t *testing.T) { + defer driver.Close() + trace := buildTrace( + []uint64{10}, + []uint64{10}, + 1*time.Second) + ref := info.ContainerReference{ + Name: "container", + } + driver.AddStats(ref, trace[0]) + percentiles, err := driver.Percentiles( + ref.Name, + []int{50}, + []int{50}, + ) + if err != nil { + t.Fatal(err) + } + if percentiles != nil { + t.Errorf("There should be no percentiles") + } +} From ca65e11486613608279e73e559394d9894031159 Mon Sep 17 00:00:00 2001 From: Nan Deng Date: Tue, 17 Jun 2014 15:12:35 -0700 Subject: [PATCH 3/3] storage unit tests --- storage/storage.go | 3 +++ storage/test/storagetests.go | 6 ++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/storage/storage.go b/storage/storage.go index 7d521eb0..51f0b9c0 100644 --- a/storage/storage.go +++ b/storage/storage.go @@ -33,5 +33,8 @@ type StorageDriver interface { // should return at most numSamples samples. Samples(containername string, numSamples int) ([]*info.ContainerStatsSample, error) + // Close will clear the state of the storage driver. The elements + // stored in the underlying storage may or may not be deleted depending + // on the implementation of the storage driver. Close() error } diff --git a/storage/test/storagetests.go b/storage/test/storagetests.go index ed460705..ec9f5934 100644 --- a/storage/test/storagetests.go +++ b/storage/test/storagetests.go @@ -59,10 +59,8 @@ func StorageDriverTestSampleCpuUsage(driver storage.StorageDriver, t *testing.T) // We need N+1 observations to get N samples for i := 0; i < N+1; i++ { - cpuusage := uint64(rand.Intn(1000)) - memusage := uint64(rand.Intn(1000)) - cpuTrace = append(cpuTrace, cpuusage) - memTrace = append(memTrace, memusage) + cpuTrace = append(cpuTrace, uint64(rand.Intn(1000))) + memTrace = append(memTrace, uint64(rand.Intn(1000))) } samplePeriod := 1 * time.Second