go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/config/impl/filesystem/fs_test.go (about) 1 // Copyright 2016 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package filesystem 16 17 import ( 18 "context" 19 "io/ioutil" 20 "net/url" 21 "os" 22 "path/filepath" 23 "testing" 24 25 . "github.com/smartystreets/goconvey/convey" 26 27 "go.chromium.org/luci/common/errors" 28 "go.chromium.org/luci/config" 29 ) 30 31 func withFolder(files map[string]string, cb func(folder string)) { 32 folder, err := ioutil.TempDir("", "fs_test_") 33 if err != nil { 34 panic(err) 35 } 36 defer os.RemoveAll(folder) 37 38 for fpath, content := range files { 39 if content == "" { 40 content = fpath 41 } 42 fpath = filepath.Join(folder, filepath.FromSlash(fpath)) 43 if err := os.MkdirAll(filepath.Dir(fpath), 0777); err != nil { 44 panic(err) 45 } 46 if err := os.WriteFile(fpath, []byte(content), 0666); err != nil { 47 panic(err) 48 } 49 } 50 51 cb(folder) 52 } 53 54 func TestFSImpl(t *testing.T) { 55 t.Parallel() 56 57 ctx := context.Background() 58 59 withFolder(map[string]string{ 60 "projects/doodly/something/file.cfg": "", 61 "projects/foobar/something/file.cfg": "", 62 "projects/foobar/another/file.cfg": "", 63 "services/foosrv/something.cfg": "", 64 "projects/foobar.json": `{ 65 "Name": "A cool project", 66 "Url": "https://something.example.com" 67 }`, 68 }, func(folder string) { 69 Convey("basic Test Filesystem config client", t, func() { 70 const expectedRev = "a1b9f654acc5008452980a98ec930cbfdeec82d6" 71 72 client, err := New(folder) 73 So(err, ShouldBeNil) 74 75 Convey("GetConfig", func() { 76 expect := &config.Config{ 77 Meta: config.Meta{ 78 ConfigSet: "projects/foobar", 79 Path: "something/file.cfg", 80 ContentHash: "v1:72b8fe0ecd5e7560762aed58063aeb3795e69bd8", 81 Revision: expectedRev, 82 ViewURL: "file://./something/file.cfg", 83 }, 84 Content: "projects/foobar/something/file.cfg", 85 } 86 87 Convey("All content", func() { 88 cfg, err := client.GetConfig(ctx, "projects/foobar", "something/file.cfg", false) 89 So(err, ShouldBeNil) 90 So(cfg, ShouldResemble, expect) 91 }) 92 93 Convey("services", func() { 94 cfg, err := client.GetConfig(ctx, "services/foosrv", "something.cfg", false) 95 So(err, ShouldBeNil) 96 So(cfg, ShouldResemble, &config.Config{ 97 Meta: config.Meta{ 98 ConfigSet: "services/foosrv", 99 Path: "something.cfg", 100 ContentHash: "v1:536a41710e0cb4f21950d5e0e32642bda58fce9a", 101 Revision: expectedRev, 102 ViewURL: "file://./something.cfg", 103 }, 104 Content: "services/foosrv/something.cfg", 105 }) 106 }) 107 108 Convey("just meta", func() { 109 cfg, err := client.GetConfig(ctx, "projects/foobar", "something/file.cfg", true) 110 So(err, ShouldBeNil) 111 So(cfg.ContentHash, ShouldEqual, "v1:72b8fe0ecd5e7560762aed58063aeb3795e69bd8") 112 So(cfg.Content, ShouldEqual, "") 113 114 Convey("make sure it doesn't poison the cache", func() { 115 cfg, err := client.GetConfig(ctx, "projects/foobar", "something/file.cfg", false) 116 So(err, ShouldBeNil) 117 So(cfg, ShouldResemble, expect) 118 }) 119 }) 120 }) 121 122 Convey("GetConfigs", func() { 123 cfg, err := client.GetConfigs(ctx, "projects/foobar", nil, false) 124 So(err, ShouldBeNil) 125 So(cfg, ShouldResemble, map[string]config.Config{ 126 "another/file.cfg": { 127 Meta: config.Meta{ 128 ConfigSet: "projects/foobar", 129 Path: "another/file.cfg", 130 ContentHash: "v1:1b136cf89ccbd1d5f42cecae874367b0258d810d", 131 Revision: expectedRev, 132 ViewURL: "file://./another/file.cfg", 133 }, 134 Content: "projects/foobar/another/file.cfg", 135 }, 136 "something/file.cfg": { 137 Meta: config.Meta{ 138 ConfigSet: "projects/foobar", 139 Path: "something/file.cfg", 140 ContentHash: "v1:72b8fe0ecd5e7560762aed58063aeb3795e69bd8", 141 Revision: expectedRev, 142 ViewURL: "file://./something/file.cfg", 143 }, 144 Content: "projects/foobar/something/file.cfg", 145 }, 146 }) 147 }) 148 149 Convey("ListFiles", func() { 150 cfg, err := client.ListFiles(ctx, "projects/foobar") 151 So(err, ShouldBeNil) 152 So(cfg, ShouldResemble, []string{ 153 "another/file.cfg", 154 "something/file.cfg", 155 }) 156 }) 157 158 Convey("GetProjectConfigs", func() { 159 cfgs, err := client.GetProjectConfigs(ctx, "something/file.cfg", false) 160 So(err, ShouldBeNil) 161 So(cfgs, ShouldResemble, []config.Config{ 162 { 163 Meta: config.Meta{ 164 ConfigSet: "projects/doodly", 165 Path: "something/file.cfg", 166 ContentHash: "v1:5a2f9983dbb615a58e1d267633396e72f6710ef2", 167 Revision: expectedRev, 168 ViewURL: "file://./something/file.cfg", 169 }, 170 Content: "projects/doodly/something/file.cfg", 171 }, 172 { 173 Meta: config.Meta{ 174 ConfigSet: "projects/foobar", 175 Path: "something/file.cfg", 176 ContentHash: "v1:72b8fe0ecd5e7560762aed58063aeb3795e69bd8", 177 Revision: expectedRev, 178 ViewURL: "file://./something/file.cfg", 179 }, 180 Content: "projects/foobar/something/file.cfg", 181 }, 182 }) 183 }) 184 185 Convey("GetProjects", func() { 186 projs, err := client.GetProjects(ctx) 187 So(err, ShouldBeNil) 188 So(projs, ShouldResemble, []config.Project{ 189 { 190 ID: "doodly", 191 Name: "doodly", 192 RepoType: "FILESYSTEM", 193 }, 194 { 195 ID: "foobar", 196 Name: "A cool project", 197 RepoType: "FILESYSTEM", 198 RepoURL: &url.URL{Scheme: "https", Host: "something.example.com"}, 199 }, 200 }) 201 }) 202 203 }) 204 }) 205 206 withFolder(map[string]string{ 207 "projects/doodly/file.cfg": "", 208 "projects/woodly/file.cfg": "", 209 }, func(folder string) { 210 Convey("rereads configs in sloppy mode", t, func() { 211 client, err := New(folder) 212 So(err, ShouldBeNil) 213 214 cfgs, err := client.GetProjectConfigs(ctx, "file.cfg", false) 215 So(err, ShouldBeNil) 216 So(cfgs, ShouldResemble, []config.Config{ 217 { 218 Meta: config.Meta{ 219 ConfigSet: "projects/doodly", 220 Path: "file.cfg", 221 ContentHash: "v1:a4f9e9ab503a00964c88e696067feed0702a81b3", 222 Revision: "42a1ca1c43387844fafbb1c958a0d12f3ea61347", 223 ViewURL: "file://./file.cfg", 224 }, 225 Content: "projects/doodly/file.cfg", 226 }, { 227 Meta: config.Meta{ 228 ConfigSet: "projects/woodly", 229 Path: "file.cfg", 230 ContentHash: "v1:722c6274d1e657691764199fa1095114a3569dee", 231 Revision: "42a1ca1c43387844fafbb1c958a0d12f3ea61347", 232 ViewURL: "file://./file.cfg", 233 }, 234 Content: "projects/woodly/file.cfg", 235 }, 236 }) 237 238 err = os.WriteFile( 239 filepath.Join(folder, filepath.FromSlash("projects/doodly/file.cfg")), 240 []byte("blarg"), 241 0666) 242 So(err, ShouldBeNil) 243 244 cfgs, err = client.GetProjectConfigs(ctx, "file.cfg", false) 245 So(err, ShouldBeNil) 246 So(cfgs, ShouldResemble, []config.Config{ 247 { 248 Meta: config.Meta{ 249 ConfigSet: "projects/doodly", 250 Path: "file.cfg", 251 ContentHash: "v1:a593942cb7ea9ffcd8ccf2f0fa23c338e23bfecd", 252 Revision: "e841b8e92756491dae3302e1e31f673e0613ad0c", 253 ViewURL: "file://./file.cfg", 254 }, 255 Content: "blarg", 256 }, { 257 Meta: config.Meta{ 258 ConfigSet: "projects/woodly", 259 Path: "file.cfg", 260 ContentHash: "v1:722c6274d1e657691764199fa1095114a3569dee", 261 Revision: "e841b8e92756491dae3302e1e31f673e0613ad0c", 262 ViewURL: "file://./file.cfg", 263 }, 264 Content: "projects/woodly/file.cfg", 265 }, 266 }) 267 }) 268 }) 269 270 versioned := map[string]string{ 271 "v1/projects/foobar/something/file.cfg": "", 272 "v2/projects/foobar/something/file.cfg": "", 273 } 274 275 withFolder(versioned, func(folder string) { 276 symlink := filepath.Join(folder, "link") 277 278 Convey("Test versioned Filesystem", t, func() { 279 So(errors.FilterFunc(os.Remove(symlink), os.IsNotExist), ShouldBeNil) 280 So(os.Symlink(filepath.Join(folder, "v1"), symlink), ShouldBeNil) 281 client, err := New(symlink) 282 So(err, ShouldBeNil) 283 284 Convey("v1", func() { 285 cfg, err := client.GetConfig(ctx, "projects/foobar", "something/file.cfg", false) 286 So(err, ShouldBeNil) 287 So(cfg.Content, ShouldEqual, "v1/projects/foobar/something/file.cfg") 288 289 Convey("v2", func() { 290 So(errors.Filter(os.Remove(symlink), os.ErrNotExist), ShouldBeNil) 291 So(os.Symlink(filepath.Join(folder, "v2"), symlink), ShouldBeNil) 292 293 cfg, err := client.GetConfig(ctx, "projects/foobar", "something/file.cfg", false) 294 So(err, ShouldBeNil) 295 So(cfg.Content, ShouldEqual, "v2/projects/foobar/something/file.cfg") 296 }) 297 }) 298 299 }) 300 }) 301 302 }