github.com/fawick/restic@v0.1.1-0.20171126184616-c02923fbfc79/internal/restic/snapshot_policy_test.go (about) 1 package restic_test 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io/ioutil" 7 "path/filepath" 8 "reflect" 9 "testing" 10 "time" 11 12 "github.com/restic/restic/internal/restic" 13 ) 14 15 func parseTimeUTC(s string) time.Time { 16 t, err := time.Parse("2006-01-02 15:04:05", s) 17 if err != nil { 18 panic(err) 19 } 20 21 return t.UTC() 22 } 23 24 func TestExpireSnapshotOps(t *testing.T) { 25 data := []struct { 26 expectEmpty bool 27 expectSum int 28 p *restic.ExpirePolicy 29 }{ 30 {true, 0, &restic.ExpirePolicy{}}, 31 {true, 0, &restic.ExpirePolicy{Tags: []restic.TagList{}}}, 32 {false, 22, &restic.ExpirePolicy{Daily: 7, Weekly: 2, Monthly: 3, Yearly: 10}}, 33 } 34 for i, d := range data { 35 isEmpty := d.p.Empty() 36 if isEmpty != d.expectEmpty { 37 t.Errorf("empty test %v: wrong result, want:\n %#v\ngot:\n %#v", i, d.expectEmpty, isEmpty) 38 } 39 hasSum := d.p.Sum() 40 if hasSum != d.expectSum { 41 t.Errorf("sum test %v: wrong result, want:\n %#v\ngot:\n %#v", i, d.expectSum, hasSum) 42 } 43 } 44 } 45 46 var testExpireSnapshots = restic.Snapshots{ 47 {Time: parseTimeUTC("2014-09-01 10:20:30")}, 48 {Time: parseTimeUTC("2014-09-02 10:20:30")}, 49 {Time: parseTimeUTC("2014-09-05 10:20:30")}, 50 {Time: parseTimeUTC("2014-09-06 10:20:30")}, 51 {Time: parseTimeUTC("2014-09-08 10:20:30")}, 52 {Time: parseTimeUTC("2014-09-09 10:20:30")}, 53 {Time: parseTimeUTC("2014-09-10 10:20:30")}, 54 {Time: parseTimeUTC("2014-09-11 10:20:30")}, 55 {Time: parseTimeUTC("2014-09-20 10:20:30")}, 56 {Time: parseTimeUTC("2014-09-22 10:20:30")}, 57 {Time: parseTimeUTC("2014-08-08 10:20:30")}, 58 {Time: parseTimeUTC("2014-08-10 10:20:30")}, 59 {Time: parseTimeUTC("2014-08-12 10:20:30")}, 60 {Time: parseTimeUTC("2014-08-13 10:20:30")}, 61 {Time: parseTimeUTC("2014-08-13 10:20:30.1")}, 62 {Time: parseTimeUTC("2014-08-15 10:20:30")}, 63 {Time: parseTimeUTC("2014-08-18 10:20:30")}, 64 {Time: parseTimeUTC("2014-08-20 10:20:30")}, 65 {Time: parseTimeUTC("2014-08-21 10:20:30")}, 66 {Time: parseTimeUTC("2014-08-22 10:20:30")}, 67 {Time: parseTimeUTC("2014-10-01 10:20:30"), Tags: []string{"foo"}}, 68 {Time: parseTimeUTC("2014-10-02 10:20:30"), Tags: []string{"foo"}}, 69 {Time: parseTimeUTC("2014-10-05 10:20:30"), Tags: []string{"foo"}}, 70 {Time: parseTimeUTC("2014-10-06 10:20:30"), Tags: []string{"foo"}}, 71 {Time: parseTimeUTC("2014-10-08 10:20:30"), Tags: []string{"foo"}}, 72 {Time: parseTimeUTC("2014-10-09 10:20:30"), Tags: []string{"foo"}}, 73 {Time: parseTimeUTC("2014-10-10 10:20:30"), Tags: []string{"foo"}}, 74 {Time: parseTimeUTC("2014-10-11 10:20:30"), Tags: []string{"foo"}}, 75 {Time: parseTimeUTC("2014-10-20 10:20:30"), Tags: []string{"foo"}}, 76 {Time: parseTimeUTC("2014-10-22 10:20:30"), Tags: []string{"foo"}}, 77 {Time: parseTimeUTC("2014-11-08 10:20:30"), Tags: []string{"foo"}}, 78 {Time: parseTimeUTC("2014-11-10 10:20:30"), Tags: []string{"foo"}}, 79 {Time: parseTimeUTC("2014-11-12 10:20:30"), Tags: []string{"foo"}}, 80 {Time: parseTimeUTC("2014-11-13 10:20:30"), Tags: []string{"foo"}}, 81 {Time: parseTimeUTC("2014-11-13 10:20:30.1"), Tags: []string{"bar"}}, 82 {Time: parseTimeUTC("2014-11-15 10:20:30"), Tags: []string{"foo", "bar"}}, 83 {Time: parseTimeUTC("2014-11-18 10:20:30")}, 84 {Time: parseTimeUTC("2014-11-20 10:20:30")}, 85 {Time: parseTimeUTC("2014-11-21 10:20:30")}, 86 {Time: parseTimeUTC("2014-11-22 10:20:30")}, 87 {Time: parseTimeUTC("2015-09-01 10:20:30")}, 88 {Time: parseTimeUTC("2015-09-02 10:20:30")}, 89 {Time: parseTimeUTC("2015-09-05 10:20:30")}, 90 {Time: parseTimeUTC("2015-09-06 10:20:30")}, 91 {Time: parseTimeUTC("2015-09-08 10:20:30")}, 92 {Time: parseTimeUTC("2015-09-09 10:20:30")}, 93 {Time: parseTimeUTC("2015-09-10 10:20:30")}, 94 {Time: parseTimeUTC("2015-09-11 10:20:30")}, 95 {Time: parseTimeUTC("2015-09-20 10:20:30")}, 96 {Time: parseTimeUTC("2015-09-22 10:20:30")}, 97 {Time: parseTimeUTC("2015-08-08 10:20:30")}, 98 {Time: parseTimeUTC("2015-08-10 10:20:30")}, 99 {Time: parseTimeUTC("2015-08-12 10:20:30")}, 100 {Time: parseTimeUTC("2015-08-13 10:20:30")}, 101 {Time: parseTimeUTC("2015-08-13 10:20:30.1")}, 102 {Time: parseTimeUTC("2015-08-15 10:20:30")}, 103 {Time: parseTimeUTC("2015-08-18 10:20:30")}, 104 {Time: parseTimeUTC("2015-08-20 10:20:30")}, 105 {Time: parseTimeUTC("2015-08-21 10:20:30")}, 106 {Time: parseTimeUTC("2015-08-22 10:20:30")}, 107 {Time: parseTimeUTC("2015-10-01 10:20:30")}, 108 {Time: parseTimeUTC("2015-10-02 10:20:30")}, 109 {Time: parseTimeUTC("2015-10-05 10:20:30")}, 110 {Time: parseTimeUTC("2015-10-06 10:20:30")}, 111 {Time: parseTimeUTC("2015-10-08 10:20:30")}, 112 {Time: parseTimeUTC("2015-10-09 10:20:30")}, 113 {Time: parseTimeUTC("2015-10-10 10:20:30")}, 114 {Time: parseTimeUTC("2015-10-11 10:20:30")}, 115 {Time: parseTimeUTC("2015-10-20 10:20:30")}, 116 {Time: parseTimeUTC("2015-10-22 10:20:30")}, 117 {Time: parseTimeUTC("2015-10-22 10:20:30")}, 118 {Time: parseTimeUTC("2015-10-22 10:20:30"), Tags: []string{"foo", "bar"}}, 119 {Time: parseTimeUTC("2015-10-22 10:20:30"), Tags: []string{"foo", "bar"}}, 120 {Time: parseTimeUTC("2015-10-22 10:20:30"), Tags: []string{"foo", "bar"}, Paths: []string{"path1", "path2"}}, 121 {Time: parseTimeUTC("2015-11-08 10:20:30")}, 122 {Time: parseTimeUTC("2015-11-10 10:20:30")}, 123 {Time: parseTimeUTC("2015-11-12 10:20:30")}, 124 {Time: parseTimeUTC("2015-11-13 10:20:30")}, 125 {Time: parseTimeUTC("2015-11-13 10:20:30.1")}, 126 {Time: parseTimeUTC("2015-11-15 10:20:30")}, 127 {Time: parseTimeUTC("2015-11-18 10:20:30")}, 128 {Time: parseTimeUTC("2015-11-20 10:20:30")}, 129 {Time: parseTimeUTC("2015-11-21 10:20:30")}, 130 {Time: parseTimeUTC("2015-11-22 10:20:30")}, 131 {Time: parseTimeUTC("2016-01-01 01:02:03")}, 132 {Time: parseTimeUTC("2016-01-01 01:03:03")}, 133 {Time: parseTimeUTC("2016-01-01 07:08:03")}, 134 {Time: parseTimeUTC("2016-01-03 07:02:03")}, 135 {Time: parseTimeUTC("2016-01-04 10:23:03")}, 136 {Time: parseTimeUTC("2016-01-04 11:23:03")}, 137 {Time: parseTimeUTC("2016-01-04 12:23:03")}, 138 {Time: parseTimeUTC("2016-01-04 12:24:03")}, 139 {Time: parseTimeUTC("2016-01-04 12:28:03")}, 140 {Time: parseTimeUTC("2016-01-04 12:30:03")}, 141 {Time: parseTimeUTC("2016-01-04 16:23:03")}, 142 {Time: parseTimeUTC("2016-01-05 09:02:03")}, 143 {Time: parseTimeUTC("2016-01-06 08:02:03")}, 144 {Time: parseTimeUTC("2016-01-07 10:02:03")}, 145 {Time: parseTimeUTC("2016-01-08 20:02:03")}, 146 {Time: parseTimeUTC("2016-01-09 21:02:03")}, 147 {Time: parseTimeUTC("2016-01-12 21:02:03")}, 148 {Time: parseTimeUTC("2016-01-12 21:08:03")}, 149 {Time: parseTimeUTC("2016-01-18 12:02:03")}, 150 } 151 152 var expireTests = []restic.ExpirePolicy{ 153 {}, 154 {Last: 10}, 155 {Last: 15}, 156 {Last: 99}, 157 {Last: 200}, 158 {Hourly: 20}, 159 {Daily: 3}, 160 {Daily: 10}, 161 {Daily: 30}, 162 {Last: 5, Daily: 5}, 163 {Last: 2, Daily: 10}, 164 {Weekly: 2}, 165 {Weekly: 4}, 166 {Daily: 3, Weekly: 4}, 167 {Monthly: 6}, 168 {Daily: 2, Weekly: 2, Monthly: 6}, 169 {Yearly: 10}, 170 {Daily: 7, Weekly: 2, Monthly: 3, Yearly: 10}, 171 {Tags: []restic.TagList{{"foo"}}}, 172 {Tags: []restic.TagList{{"foo", "bar"}}}, 173 {Tags: []restic.TagList{{"foo"}, {"bar"}}}, 174 } 175 176 func TestApplyPolicy(t *testing.T) { 177 for i, p := range expireTests { 178 keep, remove := restic.ApplyPolicy(testExpireSnapshots, p) 179 180 t.Logf("test %d: returned keep %v, remove %v (of %v) expired snapshots for policy %v", 181 i, len(keep), len(remove), len(testExpireSnapshots), p) 182 183 if len(keep)+len(remove) != len(testExpireSnapshots) { 184 t.Errorf("test %d: len(keep)+len(remove) = %d != len(testExpireSnapshots) = %d", 185 i, len(keep)+len(remove), len(testExpireSnapshots)) 186 } 187 188 if p.Sum() > 0 && len(keep) > p.Sum() { 189 t.Errorf("not enough snapshots removed: policy allows %v snapshots to remain, but ended up with %v", 190 p.Sum(), len(keep)) 191 } 192 193 for _, sn := range keep { 194 t.Logf("test %d: keep snapshot at %v %s\n", i, sn.Time, sn.Tags) 195 } 196 for _, sn := range remove { 197 t.Logf("test %d: forget snapshot at %v %s\n", i, sn.Time, sn.Tags) 198 } 199 200 goldenFilename := filepath.Join("testdata", fmt.Sprintf("policy_keep_snapshots_%d", i)) 201 202 if *updateGoldenFiles { 203 buf, err := json.MarshalIndent(keep, "", " ") 204 if err != nil { 205 t.Fatalf("error marshaling result: %v", err) 206 } 207 208 if err = ioutil.WriteFile(goldenFilename, buf, 0644); err != nil { 209 t.Fatalf("unable to update golden file: %v", err) 210 } 211 } 212 213 buf, err := ioutil.ReadFile(goldenFilename) 214 if err != nil { 215 t.Errorf("error loading golden file %v: %v", goldenFilename, err) 216 continue 217 } 218 219 var want restic.Snapshots 220 err = json.Unmarshal(buf, &want) 221 if err != nil { 222 t.Errorf("error unmarshalling golden file %v: %v", goldenFilename, err) 223 continue 224 } 225 226 if !reflect.DeepEqual(keep, want) { 227 t.Errorf("test %v: wrong result, want:\n %v\ngot:\n %v", i, want, keep) 228 continue 229 } 230 } 231 }