...
1 package gmeasure
2
3 import (
4 "crypto/md5"
5 "encoding/json"
6 "fmt"
7 "os"
8 "path/filepath"
9
10 "github.com/onsi/gomega/internal/gutil"
11 )
12
13 const CACHE_EXT = ".gmeasure-cache"
14
15
18 type ExperimentCache struct {
19 Path string
20 }
21
22
27 func NewExperimentCache(path string) (ExperimentCache, error) {
28 stat, err := os.Stat(path)
29 if os.IsNotExist(err) {
30 err := os.MkdirAll(path, 0777)
31 if err != nil {
32 return ExperimentCache{}, err
33 }
34 } else if !stat.IsDir() {
35 return ExperimentCache{}, fmt.Errorf("%s is not a directory", path)
36 }
37
38 return ExperimentCache{
39 Path: path,
40 }, nil
41 }
42
43
46 type CachedExperimentHeader struct {
47 Name string
48 Version int
49 }
50
51 func (cache ExperimentCache) hashOf(name string) string {
52 return fmt.Sprintf("%x", md5.Sum([]byte(name)))
53 }
54
55 func (cache ExperimentCache) readHeader(filename string) (CachedExperimentHeader, error) {
56 out := CachedExperimentHeader{}
57 f, err := os.Open(filepath.Join(cache.Path, filename))
58 if err != nil {
59 return out, err
60 }
61 defer f.Close()
62 err = json.NewDecoder(f).Decode(&out)
63 return out, err
64 }
65
66
69 func (cache ExperimentCache) List() ([]CachedExperimentHeader, error) {
70 var out []CachedExperimentHeader
71 names, err := gutil.ReadDir(cache.Path)
72 if err != nil {
73 return out, err
74 }
75 for _, name := range names {
76 if filepath.Ext(name) != CACHE_EXT {
77 continue
78 }
79 header, err := cache.readHeader(name)
80 if err != nil {
81 return out, err
82 }
83 out = append(out, header)
84 }
85 return out, nil
86 }
87
88
91 func (cache ExperimentCache) Clear() error {
92 names, err := gutil.ReadDir(cache.Path)
93 if err != nil {
94 return err
95 }
96 for _, name := range names {
97 if filepath.Ext(name) != CACHE_EXT {
98 continue
99 }
100 err := os.Remove(filepath.Join(cache.Path, name))
101 if err != nil {
102 return err
103 }
104 }
105 return nil
106 }
107
108
154 func (cache ExperimentCache) Load(name string, version int) *Experiment {
155 path := filepath.Join(cache.Path, cache.hashOf(name)+CACHE_EXT)
156 f, err := os.Open(path)
157 if err != nil {
158 return nil
159 }
160 defer f.Close()
161 dec := json.NewDecoder(f)
162 header := CachedExperimentHeader{}
163 dec.Decode(&header)
164 if header.Version < version {
165 return nil
166 }
167 out := NewExperiment("")
168 err = dec.Decode(out)
169 if err != nil {
170 return nil
171 }
172 return out
173 }
174
175
178 func (cache ExperimentCache) Save(name string, version int, experiment *Experiment) error {
179 path := filepath.Join(cache.Path, cache.hashOf(name)+CACHE_EXT)
180 f, err := os.Create(path)
181 if err != nil {
182 return err
183 }
184 defer f.Close()
185 enc := json.NewEncoder(f)
186 err = enc.Encode(CachedExperimentHeader{
187 Name: name,
188 Version: version,
189 })
190 if err != nil {
191 return err
192 }
193 return enc.Encode(experiment)
194 }
195
196
199 func (cache ExperimentCache) Delete(name string) error {
200 path := filepath.Join(cache.Path, cache.hashOf(name)+CACHE_EXT)
201 return os.Remove(path)
202 }
203
View as plain text