blob: b27140bb61b6312fdf57e8a394c07230a0b95bc8 [file] [log] [blame]
// 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{})
defer analyzer.Cleanup()
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{})
defer analyzer.Cleanup()
analyzer.ImportCompiledLibraries(
analysis.CompiledLibraries{
{
Name: "fuchsia.import1",
Files: []string{"import1.fidl"},
},
{
Name: "fuchsia.import2",
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{})
defer analyzer.Cleanup()
analyzer.ImportCompiledLibraries(
analysis.CompiledLibraries{
{
Name: "fuchsia.import1",
Files: []string{"import1.fidl"},
Deps: []string{"fuchsia.import2", "fuchsia.import3"},
},
{
Name: "fuchsia.import2",
Files: []string{"import2.fidl"},
Deps: []string{"fuchsia.import4"},
},
{
Name: "fuchsia.import3",
Files: []string{"import3.fidl"},
},
{
Name: "fuchsia.import4",
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{})
defer analyzer.Cleanup()
analyzer.ImportCompiledLibraries(
analysis.CompiledLibraries{
{
Name: "fuchsia.import1",
Files: []string{"import1_1.fidl", "import1_2.fidl"},
Deps: []string{"fuchsia.import3", "fuchsia.import4"},
},
{
Name: "fuchsia.import2",
Files: []string{"import2_1.fidl", "import2_2.fidl"},
Deps: []string{"fuchsia.import4"},
},
{
Name: "fuchsia.import3",
Files: []string{"import3.fidl"},
},
{
Name: "fuchsia.import4",
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{})
defer analyzer.Cleanup()
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{})
defer analyzer.Cleanup()
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{})
defer analyzer.Cleanup()
analyzer.ImportCompiledLibraries(
analysis.CompiledLibraries{
{
Name: "fuchsia.foo",
Files: []string{"foo.fidl"},
Deps: []string{"fuchsia.bar"},
},
{
Name: "fuchsia.bar",
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")
}
}