github.com/yoheimuta/protolint@v0.49.8-0.20240515023657-4ecaebb7575d/internal/linter/config/externalConfigProvider_test.go (about) 1 package config_test 2 3 import ( 4 "os" 5 "reflect" 6 "testing" 7 8 "github.com/yoheimuta/protolint/internal/setting_test" 9 10 "github.com/yoheimuta/protolint/internal/linter/config" 11 ) 12 13 func TestGetExternalConfig(t *testing.T) { 14 for _, test := range []struct { 15 name string 16 inputFilePath string 17 inputDirPath string 18 cwdPath string 19 wantExternalConfig *config.ExternalConfig 20 wantExistErr bool 21 }{ 22 { 23 name: "invalid config file", 24 inputDirPath: setting_test.TestDataPath("invalidconfig"), 25 wantExistErr: true, 26 }, 27 { 28 name: "not found a config file", 29 }, 30 { 31 name: "valid config file", 32 inputDirPath: setting_test.TestDataPath("validconfig"), 33 wantExternalConfig: &config.ExternalConfig{ 34 SourcePath: setting_test.TestDataPath("validconfig", "protolint.yaml"), 35 Lint: config.Lint{ 36 Ignores: []config.Ignore{ 37 { 38 ID: "ENUM_FIELD_NAMES_UPPER_SNAKE_CASE", 39 Files: []string{ 40 "path/to/foo.proto", 41 "path/to/bar.proto", 42 }, 43 }, 44 { 45 ID: "ENUM_NAMES_UPPER_CAMEL_CASE", 46 Files: []string{ 47 "path/to/foo.proto", 48 }, 49 }, 50 }, 51 Rules: struct { 52 NoDefault bool `yaml:"no_default" json:"no_default" toml:"no_default"` 53 AllDefault bool `yaml:"all_default" json:"all_default" toml:"all_default"` 54 Add []string `yaml:"add" json:"add" toml:"add"` 55 Remove []string `yaml:"remove" json:"remove" toml:"remove"` 56 }{ 57 NoDefault: true, 58 Add: []string{ 59 "FIELD_NAMES_LOWER_SNAKE_CASE", 60 "MESSAGE_NAMES_UPPER_CAMEL_CASE", 61 }, 62 Remove: []string{ 63 "RPC_NAMES_UPPER_CAMEL_CASE", 64 }, 65 }, 66 RulesOption: config.RulesOption{ 67 MaxLineLength: config.MaxLineLengthOption{ 68 MaxChars: 80, 69 TabChars: 2, 70 }, 71 Indent: config.IndentOption{ 72 Style: "\t", 73 Newline: "\n", 74 }, 75 }, 76 }, 77 }, 78 }, 79 { 80 name: "load .protolint.yaml", 81 inputDirPath: setting_test.TestDataPath("validconfig", "hidden"), 82 wantExternalConfig: &config.ExternalConfig{ 83 SourcePath: setting_test.TestDataPath("validconfig", "hidden", ".protolint.yaml"), 84 Lint: config.Lint{ 85 RulesOption: config.RulesOption{ 86 Indent: config.IndentOption{ 87 Style: "\t", 88 Newline: "\n", 89 }, 90 }, 91 }, 92 }, 93 }, 94 { 95 name: "load my_protolint.yaml", 96 inputFilePath: setting_test.TestDataPath("validconfig", "particular_name", "my_protolint.yaml"), 97 wantExternalConfig: &config.ExternalConfig{ 98 SourcePath: setting_test.TestDataPath("validconfig", "particular_name", "my_protolint.yaml"), 99 Lint: config.Lint{ 100 RulesOption: config.RulesOption{ 101 Indent: config.IndentOption{ 102 Style: "\t", 103 Newline: "\n", 104 }, 105 }, 106 }, 107 }, 108 }, 109 { 110 name: "load protolint.yml", 111 inputDirPath: setting_test.TestDataPath("validconfig", "yml"), 112 wantExternalConfig: &config.ExternalConfig{ 113 SourcePath: setting_test.TestDataPath("validconfig", "yml", "protolint.yml"), 114 Lint: config.Lint{ 115 RulesOption: config.RulesOption{ 116 Indent: config.IndentOption{ 117 Style: "\t", 118 Newline: "\n", 119 }, 120 }, 121 }, 122 }, 123 }, 124 { 125 name: "load .protolint.yml", 126 inputDirPath: setting_test.TestDataPath("validconfig", "yml_hidden"), 127 wantExternalConfig: &config.ExternalConfig{ 128 SourcePath: setting_test.TestDataPath("validconfig", "yml_hidden", ".protolint.yml"), 129 Lint: config.Lint{ 130 RulesOption: config.RulesOption{ 131 Indent: config.IndentOption{ 132 Style: "\t", 133 Newline: "\n", 134 }, 135 }, 136 }, 137 }, 138 }, 139 { 140 name: "load .protolint.yml at cwd automatically", 141 cwdPath: setting_test.TestDataPath("validconfig", "default"), 142 wantExternalConfig: &config.ExternalConfig{ 143 SourcePath: ".protolint.yml", 144 Lint: config.Lint{ 145 RulesOption: config.RulesOption{ 146 Indent: config.IndentOption{ 147 Style: "\t", 148 Newline: "\n", 149 }, 150 }, 151 }, 152 }, 153 }, 154 { 155 name: "prefer .protolint.yml at cwd to one at its parent dir", 156 cwdPath: setting_test.TestDataPath("validconfig", "default", "child"), 157 wantExternalConfig: &config.ExternalConfig{ 158 SourcePath: ".protolint.yaml", 159 Lint: config.Lint{ 160 RulesOption: config.RulesOption{ 161 Indent: config.IndentOption{ 162 Style: "\t", 163 Newline: "\n", 164 }, 165 }, 166 }, 167 }, 168 }, 169 { 170 name: "locate .protolint.yml at the parent when not found at cwd", 171 cwdPath: setting_test.TestDataPath("validconfig", "default", "empty_child"), 172 wantExternalConfig: &config.ExternalConfig{ 173 SourcePath: setting_test.TestDataPath("validconfig", "default", ".protolint.yml"), 174 Lint: config.Lint{ 175 RulesOption: config.RulesOption{ 176 Indent: config.IndentOption{ 177 Style: "\t", 178 Newline: "\n", 179 }, 180 }, 181 }, 182 }, 183 }, 184 { 185 name: "locate .protolint.yml at the grand parent when not found at cwd", 186 cwdPath: setting_test.TestDataPath("validconfig", "default", "empty_child", "empty_grand_child"), 187 wantExternalConfig: &config.ExternalConfig{ 188 SourcePath: setting_test.TestDataPath("validconfig", "default", ".protolint.yml"), 189 Lint: config.Lint{ 190 RulesOption: config.RulesOption{ 191 Indent: config.IndentOption{ 192 Style: "\t", 193 Newline: "\n", 194 }, 195 }, 196 }, 197 }, 198 }, 199 { 200 name: "not found a config file even so inputDirPath is set", 201 inputDirPath: setting_test.TestDataPath("validconfig", "particular_name"), 202 wantExistErr: true, 203 }, 204 { 205 name: "not found a config file even so inputFilePath is set", 206 inputFilePath: setting_test.TestDataPath("validconfig", "particular_name", "not_found.yaml"), 207 wantExistErr: true, 208 }, 209 { 210 name: "found a package.json with 'protolint' in it", 211 cwdPath: setting_test.TestDataPath("js_config", "package"), 212 wantExternalConfig: &config.ExternalConfig{ 213 SourcePath: "package.json", 214 Lint: config.Lint{ 215 RulesOption: config.RulesOption{ 216 Indent: config.IndentOption{ 217 Style: "\t", 218 Newline: "\n", 219 }, 220 }, 221 }, 222 }, 223 }, 224 { 225 name: "found a package.json without 'protolint' in it", 226 cwdPath: setting_test.TestDataPath("js_config", "package_no_protolint"), 227 wantExternalConfig: nil, 228 }, 229 { 230 name: "found a pyproject.toml without 'tools.protolint' in it", 231 cwdPath: setting_test.TestDataPath("py_project", "pyproject_no_protolint"), 232 wantExternalConfig: nil, 233 }, 234 { 235 name: "found a pyproject.toml without 'tools' in it", 236 cwdPath: setting_test.TestDataPath("py_project", "pyproject_no_tools"), 237 wantExternalConfig: nil, 238 }, 239 { 240 name: "found a package.json with 'protolint' and other stuff in it", 241 cwdPath: setting_test.TestDataPath("js_config", "non_pure_package"), 242 wantExternalConfig: &config.ExternalConfig{ 243 SourcePath: "package.json", 244 Lint: config.Lint{ 245 RulesOption: config.RulesOption{ 246 Indent: config.IndentOption{ 247 Style: "\t", 248 Newline: "\n", 249 }, 250 }, 251 }, 252 }, 253 }, 254 { 255 name: "found a pyproject.toml with 'tools.protolint' and other stuff in it", 256 cwdPath: setting_test.TestDataPath("py_project", "with_pyproject"), 257 wantExternalConfig: &config.ExternalConfig{ 258 SourcePath: "pyproject.toml", 259 Lint: config.Lint{ 260 RulesOption: config.RulesOption{ 261 Indent: config.IndentOption{ 262 Style: "\t", 263 Newline: "\n", 264 }, 265 }, 266 }, 267 }, 268 }, 269 { 270 name: "found a package.json with 'protolint' and other stuff in it, but superseded by sibling protolint.yaml", 271 cwdPath: setting_test.TestDataPath("js_config", "package_with_yaml"), 272 wantExternalConfig: &config.ExternalConfig{ 273 SourcePath: "protolint.yaml", 274 Lint: config.Lint{ 275 RulesOption: config.RulesOption{ 276 Indent: config.IndentOption{ 277 Style: "\t", 278 Newline: "\n", 279 }, 280 }, 281 }, 282 }, 283 }, 284 { 285 name: "found a pyproject.toml with 'toolsprotolint' and other stuff in it, but superseded by sibling protolint.yaml", 286 cwdPath: setting_test.TestDataPath("py_project", "project_with_yaml"), 287 wantExternalConfig: &config.ExternalConfig{ 288 SourcePath: "protolint.yaml", 289 Lint: config.Lint{ 290 RulesOption: config.RulesOption{ 291 Indent: config.IndentOption{ 292 Style: "\t", 293 Newline: "\n", 294 }, 295 }, 296 }, 297 }, 298 }, 299 { 300 name: "found a package.json with 'protolint' and other stuff in it, but superseded by parent protolint.yaml", 301 cwdPath: setting_test.TestDataPath("js_config", "package_with_yaml_parent", "child"), 302 wantExternalConfig: &config.ExternalConfig{ 303 SourcePath: setting_test.TestDataPath("js_config", "package_with_yaml_parent", "protolint.yaml"), 304 Lint: config.Lint{ 305 RulesOption: config.RulesOption{ 306 Indent: config.IndentOption{ 307 Style: "\t", 308 Newline: "\n", 309 }, 310 }, 311 }, 312 }, 313 }, 314 { 315 name: "found a pyproject.toml with 'toolsprotolint' and other stuff in it, but superseded by parent protolint.yaml", 316 cwdPath: setting_test.TestDataPath("py_project", "project_with_yaml_parent", "child"), 317 wantExternalConfig: &config.ExternalConfig{ 318 SourcePath: setting_test.TestDataPath("py_project", "project_with_yaml_parent", "protolint.yaml"), 319 Lint: config.Lint{ 320 RulesOption: config.RulesOption{ 321 Indent: config.IndentOption{ 322 Style: "\t", 323 Newline: "\n", 324 }, 325 }, 326 }, 327 }, 328 }, 329 } { 330 test := test 331 t.Run(test.name, func(t *testing.T) { 332 if len(test.cwdPath) != 0 { 333 err := os.Chdir(test.cwdPath) 334 if err != nil { 335 t.Errorf("got err %v", err) 336 return 337 } 338 } 339 340 got, err := config.GetExternalConfig(test.inputFilePath, test.inputDirPath) 341 if test.wantExistErr { 342 if err == nil { 343 t.Errorf("got err nil, but want err") 344 } 345 return 346 } 347 if err != nil { 348 t.Errorf("got err %v, but want nil", err) 349 return 350 } 351 352 if !reflect.DeepEqual(got, test.wantExternalConfig) { 353 t.Errorf("got %v, but want %v", got, test.wantExternalConfig) 354 } 355 }) 356 } 357 }