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/fakefile.go b/utils/fs/mockfs/fakefile.go new file mode 100644 index 00000000..77a3f487 --- /dev/null +++ b/utils/fs/mockfs/fakefile.go @@ -0,0 +1,35 @@ +// 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" + +type FakeFile struct { + bytes.Buffer + Name string +} + +func (self *FakeFile) Close() error { + return nil +} + +func AddTextFile(mockfs *MockFileSystem, name, content string) *FakeFile { + f := &FakeFile{ + Name: name, + Buffer: *bytes.NewBufferString(content), + } + mockfs.EXPECT().Open(name).Return(f, nil).AnyTimes() + return f +} diff --git a/utils/fs/mockfs/mockfs.go b/utils/fs/mockfs/mockfs.go new file mode 100644 index 00000000..93f08a68 --- /dev/null +++ b/utils/fs/mockfs/mockfs.go @@ -0,0 +1,55 @@ +// 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. + +// Automatically generated by MockGen. DO NOT EDIT! +// Source: github.com/google/cadvisor/utils/fs (interfaces: FileSystem) + +package mockfs + +import ( + gomock "code.google.com/p/gomock/gomock" + fs "github.com/google/cadvisor/utils/fs" +) + +// Mock of FileSystem interface +type MockFileSystem struct { + ctrl *gomock.Controller + recorder *_MockFileSystemRecorder +} + +// Recorder for MockFileSystem (not exported) +type _MockFileSystemRecorder struct { + mock *MockFileSystem +} + +func NewMockFileSystem(ctrl *gomock.Controller) *MockFileSystem { + mock := &MockFileSystem{ctrl: ctrl} + mock.recorder = &_MockFileSystemRecorder{mock} + return mock +} + +func (_m *MockFileSystem) EXPECT() *_MockFileSystemRecorder { + return _m.recorder +} + +func (_m *MockFileSystem) Open(_param0 string) (fs.File, error) { + ret := _m.ctrl.Call(_m, "Open", _param0) + ret0, _ := ret[0].(fs.File) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +func (_mr *_MockFileSystemRecorder) Open(arg0 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCall(_mr.mock, "Open", arg0) +} 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..eae182ef --- /dev/null +++ b/utils/procfs/schedstats_test.go @@ -0,0 +1,57 @@ +// 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" + + "code.google.com/p/gomock/gomock" + + "github.com/google/cadvisor/utils/fs" + "github.com/google/cadvisor/utils/fs/mockfs" +) + +func TestReadProcessSchedStat(t *testing.T) { + + mockCtrl := gomock.NewController(t) + defer mockCtrl.Finish() + + mfs := mockfs.NewMockFileSystem(mockCtrl) + + 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(mfs, path, content) + fs.ChangeFileSystem(mfs) + + receivedStat := &ProcessSchedStat{} + err := receivedStat.Add(pid) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(receivedStat, stat) { + t.Errorf("Received wrong schedstat: %+v", receivedStat) + } +}