1// +build linux
2
3/*
4** Zabbix
5** Copyright (C) 2001-2021 Zabbix SIA
6**
7** This program is free software; you can redistribute it and/or modify
8** it under the terms of the GNU General Public License as published by
9** the Free Software Foundation; either version 2 of the License, or
10** (at your option) any later version.
11**
12** This program is distributed in the hope that it will be useful,
13** but WITHOUT ANY WARRANTY; without even the implied warranty of
14** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15** GNU General Public License for more details.
16**
17** You should have received a copy of the GNU General Public License
18** along with this program; if not, write to the Free Software
19** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20**/
21
22// package std is used to create wrappers for standard Go functions to support
23// mocking in tests where necessary
24package std
25
26import (
27	"bytes"
28	"errors"
29	"os"
30	"syscall"
31	"time"
32
33	"golang.org/x/sys/unix"
34)
35
36// mocked os functionality
37
38type MockOs interface {
39	MockFile(path string, data []byte)
40}
41
42type fileTime struct {
43	ModTime time.Time
44}
45
46type mockOs struct {
47	files  map[string][]byte
48	ftimes map[string]fileTime
49}
50
51type mockFile struct {
52	buffer *bytes.Buffer
53}
54
55type fileStat struct {
56	name    string
57	size    int64
58	mode    FileMode
59	modTime time.Time
60	sys     syscall.Stat_t
61}
62
63func (o *mockOs) Open(name string) (File, error) {
64	if data, ok := o.files[name]; !ok {
65		return nil, errors.New("file does not exist")
66	} else {
67		return &mockFile{bytes.NewBuffer(data)}, nil
68	}
69}
70
71func (o *fileStat) IsDir() bool {
72	return false
73}
74
75func (o *fileStat) Mode() os.FileMode {
76	return os.FileMode(o.mode)
77}
78
79func (o *fileStat) ModTime() time.Time {
80	return o.modTime
81}
82
83func (o *fileStat) Name() string {
84	return o.name
85}
86
87func (o *fileStat) Size() int64 {
88	return o.size
89}
90
91func (o *fileStat) Sys() interface{} {
92	return &o.sys
93}
94
95func (o *mockOs) Stat(name string) (os.FileInfo, error) {
96	if data, ok := o.files[name]; !ok {
97		return nil, os.ErrNotExist
98	} else {
99		var fs fileStat
100
101		fs.mode = 436
102		fs.modTime = o.ftimes[name].ModTime
103		fs.name = name
104		fs.size = int64(len(data))
105		a, err := unix.TimeToTimespec(o.ftimes[name].ModTime)
106		if err != nil {
107			return nil, err
108		}
109		fs.sys.Atim.Sec = a.Sec
110		fs.sys.Ctim.Sec = a.Sec
111
112		return &fs, nil
113	}
114}
115
116func (o *mockOs) IsExist(err error) bool {
117
118	if err == nil {
119		return false
120	}
121	if err.Error() == "exists" {
122		return true
123	}
124	return false
125}
126
127func (f *mockFile) Close() error {
128	return nil
129}
130
131func (f *mockFile) Read(p []byte) (n int, err error) {
132	return f.buffer.Read(p)
133}
134
135// MockFile creates new mock file with the specified path and contents.
136func (o *mockOs) MockFile(path string, data []byte) {
137	o.files[path] = data
138	var ft fileTime
139	ft.ModTime = time.Now()
140	o.ftimes[path] = ft
141}
142
143// NewMockOs returns Os interface that replaces supported os package functionality with mock functions.
144func NewMockOs() Os {
145	return &mockOs{
146		files:  make(map[string][]byte),
147		ftimes: make(map[string]fileTime),
148	}
149}
150