| // Copyright 2020 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| package analysis_test |
| |
| import ( |
| "testing" |
| |
| "fidl-lsp/analysis" |
| "fidl-lsp/state" |
| ) |
| |
| func indexOf(slice []string, elem string) int { |
| for i, v := range slice { |
| if v == elem { |
| return i |
| } |
| } |
| return -1 |
| } |
| |
| func TestFindDepsNoDeps(t *testing.T) { |
| analyzer := analysis.NewAnalyzer(analysis.Config{}, analysis.CompiledLibraries{}) |
| fs := state.NewFileSystem() |
| fs.NewFile( |
| "file.fidl", |
| `library test;`, |
| ) |
| |
| analyzer.Analyze(fs, "file.fidl") |
| fidlcArgs, err := analyzer.FindDeps(fs, "file.fidl") |
| if err != nil { |
| t.Error(err) |
| } |
| if len(fidlcArgs) != 2 { |
| t.Fatalf("incorrect number of fidlc --files args %d: expected %d", len(fidlcArgs), 2) |
| } |
| } |
| |
| func TestFindDepsDirectImports(t *testing.T) { |
| analyzer := analysis.NewAnalyzer( |
| analysis.Config{}, |
| analysis.CompiledLibraries{ |
| "fuchsia.import1": analysis.CompiledLibrary{ |
| Files: []string{"import1.fidl"}, |
| }, |
| "fuchsia.import2": analysis.CompiledLibrary{ |
| Files: []string{"import2.fidl"}, |
| }, |
| }, |
| ) |
| |
| fs := state.NewFileSystem() |
| fs.NewFile( |
| "test.fidl", |
| ` |
| library test; |
| using fuchsia.import1; |
| using fuchsia.import2; |
| `, |
| ) |
| |
| analyzer.Analyze(fs, "test.fidl") |
| fidlcArgs, err := analyzer.FindDeps(fs, "test.fidl") |
| if err != nil { |
| t.Error(err) |
| } |
| expArgs := []string{ |
| "--files", "import1.fidl", |
| "--files", "import2.fidl", |
| "--files", |
| } |
| // FindDeps returns the required --files args to fidlc, including the library |
| // itself, which we don't check. So there should be (# of dependencies + 1) |
| // total --files args. |
| if len(fidlcArgs) != len(expArgs)+1 { |
| t.Fatalf("incorrect number of fidlc --files args %d: expected %d", len(fidlcArgs), len(expArgs)+fs.NFiles()) |
| } |
| for _, expArg := range expArgs { |
| if indexOf(fidlcArgs, expArg) == -1 { |
| t.Errorf("missing expected fidlc --files arg %s", expArg) |
| } |
| } |
| } |
| |
| func TestFindDepsIndirectImports(t *testing.T) { |
| analyzer := analysis.NewAnalyzer( |
| analysis.Config{}, |
| analysis.CompiledLibraries{ |
| "fuchsia.import1": analysis.CompiledLibrary{ |
| Files: []string{"import1.fidl"}, |
| Deps: []string{"fuchsia.import2", "fuchsia.import3"}, |
| }, |
| "fuchsia.import2": analysis.CompiledLibrary{ |
| Files: []string{"import2.fidl"}, |
| Deps: []string{"fuchsia.import4"}, |
| }, |
| "fuchsia.import3": analysis.CompiledLibrary{ |
| Files: []string{"import3.fidl"}, |
| }, |
| "fuchsia.import4": analysis.CompiledLibrary{ |
| Files: []string{"import4.fidl"}, |
| }, |
| }, |
| ) |
| |
| fs := state.NewFileSystem() |
| fs.NewFile( |
| "test.fidl", |
| ` |
| library test; |
| using fuchsia.import1; // depends on import2, import3 |
| using fuchsia.import2; // depends on import 4 |
| `, |
| ) |
| |
| analyzer.Analyze(fs, "test.fidl") |
| fidlcArgs, err := analyzer.FindDeps(fs, "test.fidl") |
| if err != nil { |
| t.Error(err) |
| } |
| expArgs := []string{ |
| "--files", "import4.fidl", |
| "--files", "import3.fidl", |
| "--files", "import2.fidl", |
| "--files", "import1.fidl", |
| "--files", |
| } |
| if len(fidlcArgs) != len(expArgs)+1 { |
| t.Fatalf("incorrect number of fidlc --files args %d: expected %d", len(fidlcArgs), len(expArgs)+fs.NFiles()) |
| } |
| for _, expArg := range expArgs { |
| if indexOf(fidlcArgs, expArg) == -1 { |
| t.Errorf("missing expected fidlc --files arg %s", expArg) |
| } |
| } |
| if indexOf(fidlcArgs, "import4.fidl") > indexOf(fidlcArgs, "import2.fidl") || |
| indexOf(fidlcArgs, "import3.fidl") > indexOf(fidlcArgs, "import1.fidl") || |
| indexOf(fidlcArgs, "import2.fidl") > indexOf(fidlcArgs, "import1.fidl") { |
| t.Errorf("fidlc --files are not in correct dependency order") |
| } |
| } |
| |
| func TestFindDepsMultiFileLibraries(t *testing.T) { |
| analyzer := analysis.NewAnalyzer( |
| analysis.Config{}, |
| analysis.CompiledLibraries{ |
| "fuchsia.import1": analysis.CompiledLibrary{ |
| Files: []string{"import1_1.fidl", "import1_2.fidl"}, |
| Deps: []string{"fuchsia.import3", "fuchsia.import4"}, |
| }, |
| "fuchsia.import2": analysis.CompiledLibrary{ |
| Files: []string{"import2_1.fidl", "import2_2.fidl"}, |
| Deps: []string{"fuchsia.import4"}, |
| }, |
| "fuchsia.import3": analysis.CompiledLibrary{ |
| Files: []string{"import3.fidl"}, |
| }, |
| "fuchsia.import4": analysis.CompiledLibrary{ |
| Files: []string{"import4_1.fidl", "import4_2.fidl", "import4_3.fidl"}, |
| }, |
| }, |
| ) |
| |
| fs := state.NewFileSystem() |
| fs.NewFile( |
| "test1.fidl", |
| ` |
| library test; |
| using fuchsia.import1; // depends on import2, import3 |
| `, |
| ) |
| fs.NewFile( |
| "test2.fidl", |
| ` |
| library test; |
| using fuchsia.import2; // depends on import 4 |
| `, |
| ) |
| |
| analyzer.Analyze(fs, "test1.fidl") |
| analyzer.Analyze(fs, "test2.fidl") |
| fidlcArgs, err := analyzer.FindDeps(fs, "test1.fidl") |
| if err != nil { |
| t.Error(err) |
| } |
| expArgs := []string{ |
| "--files", "import4_1.fidl", "import4_2.fidl", "import4_3.fidl", |
| "--files", "import3.fidl", |
| "--files", "import2_1.fidl", "import2_2.fidl", |
| "--files", "import1_1.fidl", "import1_2.fidl", |
| "--files", |
| } |
| if len(fidlcArgs) != len(expArgs)+2 { |
| t.Errorf("args: %v\n", fidlcArgs) |
| t.Fatalf("incorrect number of fidlc --files args %d: expected %d", len(fidlcArgs), len(expArgs)+fs.NFiles()) |
| } |
| // We don't test the topological sort, just that all the required files are present. |
| for _, expArg := range expArgs { |
| if indexOf(fidlcArgs, expArg) == -1 { |
| t.Errorf("missing expected fidlc --files arg %s", expArg) |
| } |
| } |
| } |
| |
| func TestFindDepsNoLibraryInFile(t *testing.T) { |
| analyzer := analysis.NewAnalyzer(analysis.Config{}, analysis.CompiledLibraries{}) |
| fs := state.NewFileSystem() |
| fs.NewFile( |
| "test1.fidl", |
| `const FOO = 0;`, |
| ) |
| |
| analyzer.Analyze(fs, "test1.fidl") |
| if _, err := analyzer.FindDeps(fs, "test1.fidl"); err == nil { |
| t.Errorf("expect error on file with no library") |
| } |
| } |
| |
| func TestFindDepsImportNotInFidlProject(t *testing.T) { |
| analyzer := analysis.NewAnalyzer(analysis.Config{}, analysis.CompiledLibraries{}) |
| fs := state.NewFileSystem() |
| fs.NewFile( |
| "foo.fidl", |
| ` |
| library foo; |
| using fuchsia.bar; |
| `, |
| ) |
| |
| analyzer.Analyze(fs, "foo.fidl") |
| if _, err := analyzer.FindDeps(fs, "foo.fidl"); err == nil { |
| t.Errorf("expect error on unknown import") |
| } |
| } |
| |
| func TestFindDepsImportCycle(t *testing.T) { |
| analyzer := analysis.NewAnalyzer( |
| analysis.Config{}, |
| analysis.CompiledLibraries{ |
| "fuchsia.foo": analysis.CompiledLibrary{ |
| Files: []string{"foo.fidl"}, |
| Deps: []string{"fuchsia.bar"}, |
| }, |
| "fuchsia.bar": analysis.CompiledLibrary{ |
| Files: []string{"bar.fidl"}, |
| Deps: []string{"fuchsia.foo"}, |
| }, |
| }, |
| ) |
| |
| fs := state.NewFileSystem() |
| fs.NewFile( |
| "foo.fidl", |
| ` |
| library fuchsia.foo; |
| using fuchsia.bar; |
| `, |
| ) |
| fs.NewFile( |
| "bar.fidl", |
| ` |
| library fuchsia.bar; |
| using fuchsia.foo; |
| `, |
| ) |
| |
| analyzer.Analyze(fs, "foo.fidl") |
| analyzer.Analyze(fs, "bar.fidl") |
| if _, err := analyzer.FindDeps(fs, "foo.fidl"); err == nil { |
| t.Errorf("expect error on import cycle") |
| } |
| } |