// Copyright 2020 The Go 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 cache

import (
	"context"
	"os"
	"testing"

	"golang.org/x/tools/internal/lsp/fake"
	"golang.org/x/tools/internal/lsp/source"
	"golang.org/x/tools/internal/span"
)

// osFileSource is a fileSource that just reads from the operating system.
type osFileSource struct{}

func (s osFileSource) GetFile(ctx context.Context, uri span.URI) (source.FileHandle, error) {
	fi, statErr := os.Stat(uri.Filename())
	if statErr != nil {
		return &fileHandle{
			err: statErr,
			uri: uri,
		}, nil
	}
	fh, err := readFile(ctx, uri, fi.ModTime())
	if err != nil {
		return nil, err
	}
	return fh, nil
}

func TestWorkspaceModule(t *testing.T) {
	tests := []struct {
		desc           string
		initial        string // txtar-encoded
		legacyMode     bool
		initialSource  workspaceSource
		initialModules []string
		initialDirs    []string
		initialSum     string
		updates        map[string]string
		finalSource    workspaceSource
		finalModules   []string
		finalDirs      []string
		finalSum       string
	}{
		{
			desc: "legacy mode",
			initial: `
-- go.mod --
module mod.com
-- go.sum --
golang.org/x/mod v0.3.0 h1:deadbeef
-- a/go.mod --
module moda.com`,
			legacyMode:     true,
			initialModules: []string{"./go.mod"},
			initialSource:  legacyWorkspace,
			initialDirs:    []string{"."},
			initialSum:     "golang.org/x/mod v0.3.0 h1:deadbeef\n",
		},
		{
			desc: "nested module",
			initial: `
-- go.mod --
module mod.com
-- a/go.mod --
module moda.com`,
			initialModules: []string{"./go.mod", "a/go.mod"},
			initialSource:  fileSystemWorkspace,
			initialDirs:    []string{".", "a"},
		},
		{
			desc: "removing module",
			initial: `
-- a/go.mod --
module moda.com
-- a/go.sum --
golang.org/x/mod v0.3.0 h1:deadbeef
-- b/go.mod --
module modb.com
-- b/go.sum --
golang.org/x/mod v0.3.0 h1:beefdead`,
			initialModules: []string{"a/go.mod", "b/go.mod"},
			initialSource:  fileSystemWorkspace,
			initialDirs:    []string{".", "a", "b"},
			initialSum:     "golang.org/x/mod v0.3.0 h1:beefdead\ngolang.org/x/mod v0.3.0 h1:deadbeef\n",
			updates: map[string]string{
				"gopls.mod": `module gopls-workspace

require moda.com v0.0.0-goplsworkspace
replace moda.com => $SANDBOX_WORKDIR/a`,
			},
			finalModules: []string{"a/go.mod"},
			finalSource:  goplsModWorkspace,
			finalDirs:    []string{".", "a"},
			finalSum:     "golang.org/x/mod v0.3.0 h1:deadbeef\n",
		},
		{
			desc: "adding module",
			initial: `
-- gopls.mod --
require moda.com v0.0.0-goplsworkspace
replace moda.com => $SANDBOX_WORKDIR/a
-- a/go.mod --
module moda.com
-- b/go.mod --
module modb.com`,
			initialModules: []string{"a/go.mod"},
			initialSource:  goplsModWorkspace,
			initialDirs:    []string{".", "a"},
			updates: map[string]string{
				"gopls.mod": `module gopls-workspace

require moda.com v0.0.0-goplsworkspace
require modb.com v0.0.0-goplsworkspace

replace moda.com => $SANDBOX_WORKDIR/a
replace modb.com => $SANDBOX_WORKDIR/b`,
			},
			finalModules: []string{"a/go.mod", "b/go.mod"},
			finalSource:  goplsModWorkspace,
			finalDirs:    []string{".", "a", "b"},
		},
		{
			desc: "deleting gopls.mod",
			initial: `
-- gopls.mod --
module gopls-workspace

require moda.com v0.0.0-goplsworkspace
replace moda.com => $SANDBOX_WORKDIR/a
-- a/go.mod --
module moda.com
-- b/go.mod --
module modb.com`,
			initialModules: []string{"a/go.mod"},
			initialSource:  goplsModWorkspace,
			initialDirs:    []string{".", "a"},
			updates: map[string]string{
				"gopls.mod": "",
			},
			finalModules: []string{"a/go.mod", "b/go.mod"},
			finalSource:  fileSystemWorkspace,
			finalDirs:    []string{".", "a", "b"},
		},
		{
			desc: "broken module parsing",
			initial: `
-- a/go.mod --
module moda.com

require gopls.test v0.0.0-goplsworkspace
replace gopls.test => ../../gopls.test // (this path shouldn't matter)
-- b/go.mod --
module modb.com`,
			initialModules: []string{"a/go.mod", "b/go.mod"},
			initialSource:  fileSystemWorkspace,
			initialDirs:    []string{".", "a", "b", "../gopls.test"},
			updates: map[string]string{
				"a/go.mod": `modul moda.com

require gopls.test v0.0.0-goplsworkspace
replace gopls.test => ../../gopls.test2`,
			},
			finalModules: []string{"a/go.mod", "b/go.mod"},
			finalSource:  fileSystemWorkspace,
			// finalDirs should be unchanged: we should preserve dirs in the presence
			// of a broken modfile.
			finalDirs: []string{".", "a", "b", "../gopls.test"},
		},
	}

	for _, test := range tests {
		t.Run(test.desc, func(t *testing.T) {
			ctx := context.Background()
			dir, err := fake.Tempdir(test.initial)
			if err != nil {
				t.Fatal(err)
			}
			defer os.RemoveAll(dir)
			root := span.URIFromPath(dir)

			fs := osFileSource{}
			excludeNothing := func(string) bool { return false }
			w, err := newWorkspace(ctx, root, fs, excludeNothing, false, !test.legacyMode)
			if err != nil {
				t.Fatal(err)
			}
			rel := fake.RelativeTo(dir)
			checkWorkspaceModule(t, rel, w, test.initialSource, test.initialModules)
			gotDirs := w.dirs(ctx, fs)
			checkWorkspaceDirs(t, rel, gotDirs, test.initialDirs)

			// Verify the initial sum.
			gotSumBytes, err := w.sumFile(ctx, fs)
			if err != nil {
				t.Fatal(err)
			}
			if gotSum := string(gotSumBytes); gotSum != test.initialSum {
				t.Errorf("got initial sum %q, want %q", gotSum, test.initialSum)
			}

			// Apply updates.
			if test.updates != nil {
				changes := make(map[span.URI]*fileChange)
				for k, v := range test.updates {
					if v == "" {
						// for convenience, use this to signal a deletion. TODO: more doc
						err := os.Remove(rel.AbsPath(k))
						if err != nil {
							t.Fatal(err)
						}
					} else {
						fake.WriteFileData(k, []byte(v), rel)
					}
					uri := span.URIFromPath(rel.AbsPath(k))
					fh, err := fs.GetFile(ctx, uri)
					if err != nil {
						t.Fatal(err)
					}
					content, err := fh.Read()
					changes[uri] = &fileChange{
						content:    content,
						exists:     err == nil,
						fileHandle: &closedFile{fh},
					}
				}
				w, _ := w.invalidate(ctx, changes)
				checkWorkspaceModule(t, rel, w, test.finalSource, test.finalModules)
				gotDirs := w.dirs(ctx, fs)
				checkWorkspaceDirs(t, rel, gotDirs, test.finalDirs)

				// Verify that the final sumfile reflects any changes (for example,
				// that modules may have gone out of scope).
				gotSumBytes, err := w.sumFile(ctx, fs)
				if err != nil {
					t.Fatal(err)
				}
				if gotSum := string(gotSumBytes); gotSum != test.finalSum {
					t.Errorf("got final sum %q, want %q", gotSum, test.finalSum)
				}
			}
		})
	}
}

func checkWorkspaceModule(t *testing.T, rel fake.RelativeTo, got *workspace, wantSource workspaceSource, want []string) {
	t.Helper()
	if got.moduleSource != wantSource {
		t.Errorf("module source = %v, want %v", got.moduleSource, wantSource)
	}
	modules := make(map[span.URI]struct{})
	for k := range got.getActiveModFiles() {
		modules[k] = struct{}{}
	}
	for _, modPath := range want {
		path := rel.AbsPath(modPath)
		uri := span.URIFromPath(path)
		if _, ok := modules[uri]; !ok {
			t.Errorf("missing module %q", uri)
		}
		delete(modules, uri)
	}
	for remaining := range modules {
		t.Errorf("unexpected module %q", remaining)
	}
}

func checkWorkspaceDirs(t *testing.T, rel fake.RelativeTo, got []span.URI, want []string) {
	t.Helper()
	gotM := make(map[span.URI]bool)
	for _, dir := range got {
		gotM[dir] = true
	}
	for _, dir := range want {
		path := rel.AbsPath(dir)
		uri := span.URIFromPath(path)
		if !gotM[uri] {
			t.Errorf("missing dir %q", uri)
		}
		delete(gotM, uri)
	}
	for remaining := range gotM {
		t.Errorf("unexpected dir %q", remaining)
	}
}
