diff --git a/utils/fs/fs.go b/utils/fs/fs.go new file mode 100644 index 00000000..d5999a9b --- /dev/null +++ b/utils/fs/fs.go @@ -0,0 +1,44 @@ +// 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 fs + +import ( + "io" + "os" +) + +type osFS struct{} + +func (osFS) Open(name string) (File, error) { return os.Open(name) } +func (osFS) Stat(name string) (os.FileInfo, error) { return os.Stat(name) } + +var fs FileSystem = osFS{} + +type FileSystem interface { + Open(name string) (File, error) +} + +type File interface { + io.ReadWriteCloser +} + +// Useful for tests. Not thread safe. +func ChangeFileSystem(filesystem FileSystem) { + fs = filesystem +} + +func Open(name string) (File, error) { + return fs.Open(name) +} diff --git a/utils/fs/mockfs/mockfs.go b/utils/fs/mockfs/mockfs.go new file mode 100644 index 00000000..a890d1d6 --- /dev/null +++ b/utils/fs/mockfs/mockfs.go @@ -0,0 +1,65 @@ +// 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 mockfs + +import ( + "bytes" + "fmt" + + "github.com/google/cadvisor/utils/fs" + "github.com/stretchr/testify/mock" +) + +type MockFile struct { + mock.Mock + bytes.Buffer + checkClose bool +} + +func (self *MockFile) CheckClose() *MockFile { + self.checkClose = true + return self +} + +func (self *MockFile) Close() error { + if self.checkClose { + args := self.Called() + return args.Error(0) + } + return nil +} + +type MockFileSystem struct { + mock.Mock + files map[string]*MockFile +} + +func (self *MockFileSystem) AddTextFile(name, content string) *MockFile { + if self.files == nil { + self.files = make(map[string]*MockFile, 4) + } + f := &MockFile{ + Buffer: *bytes.NewBufferString(content), + } + self.files[name] = f + return f +} + +func (self *MockFileSystem) Open(name string) (fs.File, error) { + if f, ok := self.files[name]; ok { + return f, nil + } + return nil, fmt.Errorf("cannot open file %v", name) +} diff --git a/utils/procfs/schedstats.go b/utils/procfs/schedstats.go index 89ad27bc..560b0d43 100644 --- a/utils/procfs/schedstats.go +++ b/utils/procfs/schedstats.go @@ -18,8 +18,9 @@ import ( "bufio" "fmt" "io" - "os" "strconv" + + "github.com/google/cadvisor/utils/fs" ) type ProcessSchedStat struct { @@ -66,7 +67,7 @@ func (self *ProcessSchedStat) Add(pid int) error { } path := fmt.Sprintf("/proc/%d/schedstat", pid) - f, err := os.Open(path) + f, err := fs.Open(path) if err != nil { return err } diff --git a/utils/procfs/schedstats_test.go b/utils/procfs/schedstats_test.go new file mode 100644 index 00000000..6eb24876 --- /dev/null +++ b/utils/procfs/schedstats_test.go @@ -0,0 +1,52 @@ +// 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 procfs + +import ( + "fmt" + "reflect" + "testing" + + "github.com/google/cadvisor/utils/fs" + "github.com/google/cadvisor/utils/fs/mockfs" +) + +func TestReadProcessSchedStat(t *testing.T) { + + mockfs := &mockfs.MockFileSystem{} + + pid := 10 + + stat := &ProcessSchedStat{ + NumProcesses: 1, + Running: 100, + RunWait: 120, + NumTimeSlices: 130, + } + + path := fmt.Sprintf("/proc/%v/schedstat", pid) + content := fmt.Sprintf("%v %v %v\n", stat.Running, stat.RunWait, stat.NumTimeSlices) + mockfs.AddTextFile(path, content) + fs.ChangeFileSystem(mockfs) + + receivedStat := &ProcessSchedStat{} + err := receivedStat.Add(pid) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(receivedStat, stat) { + t.Errorf("Received wrong schedstat: %+v", receivedStat) + } +}