// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:io' as io;

import 'package:analysis_server/src/plugin/notification_manager.dart';
import 'package:analysis_server/src/plugin/plugin_manager.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
import 'package:analyzer/src/dart/analysis/context_root.dart';
import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:analyzer/src/workspace/basic.dart';
import 'package:analyzer_plugin/channel/channel.dart';
import 'package:analyzer_plugin/protocol/protocol.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:analyzer_plugin/protocol/protocol_generated.dart'
    hide ContextRoot;
import 'package:path/path.dart' as path;
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'package:watcher/watcher.dart' as watcher;

void main() {
  defineReflectiveSuite(() {
    defineReflectiveTests(BuiltInPluginInfoTest);
    defineReflectiveTests(DiscoveredPluginInfoTest);
    defineReflectiveTests(PluginManagerTest);
    defineReflectiveTests(PluginManagerFromDiskTest);
    defineReflectiveTests(PluginSessionTest);
    defineReflectiveTests(PluginSessionFromDiskTest);
  });
}

@reflectiveTest
class BuiltInPluginInfoTest with ResourceProviderMixin, _ContextRoot {
  late TestNotificationManager notificationManager;
  late BuiltInPluginInfo plugin;

  void setUp() {
    notificationManager = TestNotificationManager();
    plugin = BuiltInPluginInfo((_) {}, 'test plugin', notificationManager,
        InstrumentationService.NULL_SERVICE);
  }

  void test_addContextRoot() {
    var contextRoot1 = _newContextRoot('/pkg1');
    plugin.addContextRoot(contextRoot1);
    expect(plugin.contextRoots, [contextRoot1]);
    plugin.addContextRoot(contextRoot1);
    expect(plugin.contextRoots, [contextRoot1]);
  }

  void test_creation() {
    expect(plugin.pluginId, 'test plugin');
    expect(plugin.notificationManager, notificationManager);
    expect(plugin.contextRoots, isEmpty);
    expect(plugin.currentSession, isNull);
  }

  void test_removeContextRoot() {
    var contextRoot1 = _newContextRoot('/pkg1');
    var contextRoot2 = _newContextRoot('/pkg2');
    plugin.addContextRoot(contextRoot1);
    expect(plugin.contextRoots, unorderedEquals([contextRoot1]));
    plugin.addContextRoot(contextRoot2);
    expect(plugin.contextRoots, unorderedEquals([contextRoot1, contextRoot2]));
    plugin.removeContextRoot(contextRoot1);
    expect(plugin.contextRoots, unorderedEquals([contextRoot2]));
    plugin.removeContextRoot(contextRoot2);
    expect(plugin.contextRoots, isEmpty);
  }

  @failingTest
  Future<void> test_start_notRunning() {
    fail('Not tested');
  }

  Future<void> test_start_running() async {
    plugin.currentSession = PluginSession(plugin);
    try {
      await plugin.start('', '');
      fail('Expected a StateError');
    } on StateError {
      // Expected.
    }
  }

  void test_stop_notRunning() {
    expect(() => plugin.stop(), throwsStateError);
  }

  Future<void> test_stop_running() async {
    var session = PluginSession(plugin);
    var channel = TestServerCommunicationChannel(session);
    plugin.currentSession = session;
    await plugin.stop();
    expect(plugin.currentSession, isNull);
    expect(channel.sentRequests, hasLength(1));
    expect(channel.sentRequests[0].method, 'plugin.shutdown');
  }
}

@reflectiveTest
class DiscoveredPluginInfoTest with ResourceProviderMixin, _ContextRoot {
  late TestNotificationManager notificationManager;
  String pluginPath = '/pluginDir';
  String executionPath = '/pluginDir/bin/plugin.dart';
  String packagesPath = '/pluginDir/.packages';
  late DiscoveredPluginInfo plugin;

  void setUp() {
    notificationManager = TestNotificationManager();
    plugin = DiscoveredPluginInfo(pluginPath, executionPath, packagesPath,
        notificationManager, InstrumentationService.NULL_SERVICE);
  }

  void test_addContextRoot() {
    var contextRoot1 = _newContextRoot('/pkg1');
    var optionsFile = getFile('/pkg1/analysis_options.yaml');
    contextRoot1.optionsFile = optionsFile;
    var session = PluginSession(plugin);
    var channel = TestServerCommunicationChannel(session);
    plugin.currentSession = session;
    plugin.addContextRoot(contextRoot1);
    expect(plugin.contextRoots, [contextRoot1]);
    plugin.addContextRoot(contextRoot1);
    expect(plugin.contextRoots, [contextRoot1]);
    var sentRequests = channel.sentRequests;
    expect(sentRequests, hasLength(1));
    var roots = sentRequests[0].params['roots'] as List<Map>;
    expect(roots[0]['optionsFile'], optionsFile.path);
  }

  void test_creation() {
    expect(plugin.path, pluginPath);
    expect(plugin.executionPath, executionPath);
    expect(plugin.notificationManager, notificationManager);
    expect(plugin.contextRoots, isEmpty);
    expect(plugin.currentSession, isNull);
  }

  void test_removeContextRoot() {
    var contextRoot1 = _newContextRoot('/pkg1');
    var contextRoot2 = _newContextRoot('/pkg2');
    plugin.addContextRoot(contextRoot1);
    expect(plugin.contextRoots, unorderedEquals([contextRoot1]));
    plugin.addContextRoot(contextRoot2);
    expect(plugin.contextRoots, unorderedEquals([contextRoot1, contextRoot2]));
    plugin.removeContextRoot(contextRoot1);
    expect(plugin.contextRoots, unorderedEquals([contextRoot2]));
    plugin.removeContextRoot(contextRoot2);
    expect(plugin.contextRoots, isEmpty);
  }

  @failingTest
  Future<void> test_start_notRunning() {
    fail('Not tested');
  }

  Future<void> test_start_running() async {
    plugin.currentSession = PluginSession(plugin);
    try {
      await plugin.start('', '');
      fail('Expected a StateError');
    } on StateError {
      // Expected.
    }
  }

  void test_stop_notRunning() {
    expect(() => plugin.stop(), throwsStateError);
  }

  Future<void> test_stop_running() async {
    var session = PluginSession(plugin);
    var channel = TestServerCommunicationChannel(session);
    plugin.currentSession = session;
    await plugin.stop();
    expect(plugin.currentSession, isNull);
    expect(channel.sentRequests, hasLength(1));
    expect(channel.sentRequests[0].method, 'plugin.shutdown');
  }
}

@reflectiveTest
class PluginManagerFromDiskTest extends PluginTestSupport {
  String byteStorePath = '/byteStore';
  late PluginManager manager;

  @override
  void setUp() {
    super.setUp();
    manager = PluginManager(resourceProvider, byteStorePath, '',
        notificationManager, InstrumentationService.NULL_SERVICE);
  }

  @SkippedTest(
      reason: 'flaky timeouts',
      issue: 'https://github.com/dart-lang/sdk/issues/38629')
  Future<void> test_addPluginToContextRoot() async {
    var pkg1Dir = io.Directory.systemTemp.createTempSync('pkg1');
    var pkgPath = pkg1Dir.resolveSymbolicLinksSync();
    await withPlugin(test: (String pluginPath) async {
      var contextRoot = _newContextRoot(pkgPath);
      await manager.addPluginToContextRoot(contextRoot, pluginPath);
      await manager.stopAll();
    });
    pkg1Dir.deleteSync(recursive: true);
  }

  @failingTest
  Future<void> test_addPluginToContextRoot_pubspec() async {
    // We can't successfully run pub until after the analyzer_plugin package has
    // been published.
    fail('Cannot run pub');
//    io.Directory pkg1Dir = io.Directory.systemTemp.createTempSync('pkg1');
//    String pkgPath = pkg1Dir.resolveSymbolicLinksSync();
//    await withPubspecPlugin(test: (String pluginPath) async {
//      ContextRoot contextRoot = _newContextRoot(pkgPath);
//      await manager.addPluginToContextRoot(contextRoot, pluginPath);
//      String packagesPath =
//          resourceProvider.pathContext.join(pluginPath, '.packages');
//      File packagesFile = resourceProvider.getFile(packagesPath);
//      bool exists = packagesFile.exists;
//      await manager.stopAll();
//      expect(exists, isTrue, reason: '.packages file was not created');
//    });
//    pkg1Dir.deleteSync(recursive: true);
  }

  @SkippedTest(
      reason: 'flaky timeouts',
      issue: 'https://github.com/dart-lang/sdk/issues/38629')
  Future<void> test_broadcastRequest_many() async {
    var pkg1Dir = io.Directory.systemTemp.createTempSync('pkg1');
    var pkgPath = pkg1Dir.resolveSymbolicLinksSync();
    await withPlugin(
        pluginName: 'plugin1',
        test: (String plugin1Path) async {
          await withPlugin(
              pluginName: 'plugin2',
              test: (String plugin2Path) async {
                var contextRoot = _newContextRoot(pkgPath);
                await manager.addPluginToContextRoot(contextRoot, plugin1Path);
                await manager.addPluginToContextRoot(contextRoot, plugin2Path);

                var responses = manager.broadcastRequest(
                    CompletionGetSuggestionsParams('/pkg1/lib/pkg1.dart', 100),
                    contextRoot: contextRoot);
                expect(responses, hasLength(2));

                await manager.stopAll();
              });
        });
    pkg1Dir.deleteSync(recursive: true);
  }

  @SkippedTest(
      reason: 'flaky timeouts',
      issue: 'https://github.com/dart-lang/sdk/issues/38629')
  Future<void> test_broadcastRequest_many_noContextRoot() async {
    var pkg1Dir = io.Directory.systemTemp.createTempSync('pkg1');
    var pkgPath = pkg1Dir.resolveSymbolicLinksSync();
    await withPlugin(
        pluginName: 'plugin1',
        test: (String plugin1Path) async {
          await withPlugin(
              pluginName: 'plugin2',
              test: (String plugin2Path) async {
                var contextRoot = _newContextRoot(pkgPath);
                await manager.addPluginToContextRoot(contextRoot, plugin1Path);
                await manager.addPluginToContextRoot(contextRoot, plugin2Path);

                var responses = manager.broadcastRequest(
                    CompletionGetSuggestionsParams('/pkg1/lib/pkg1.dart', 100));
                expect(responses, hasLength(2));

                await manager.stopAll();
              });
        });
    pkg1Dir.deleteSync(recursive: true);
  }

  @SkippedTest(
      reason: 'flaky timeouts',
      issue: 'https://github.com/dart-lang/sdk/issues/38629')
  Future<void> test_broadcastRequest_noCurrentSession() async {
    var pkg1Dir = io.Directory.systemTemp.createTempSync('pkg1');
    var pkgPath = pkg1Dir.resolveSymbolicLinksSync();
    await withPlugin(
        pluginName: 'plugin1',
        content: '(invalid content here)',
        test: (String plugin1Path) async {
          var contextRoot = _newContextRoot(pkgPath);
          await manager.addPluginToContextRoot(contextRoot, plugin1Path);

          var responses = manager.broadcastRequest(
              CompletionGetSuggestionsParams('/pkg1/lib/pkg1.dart', 100),
              contextRoot: contextRoot);
          expect(responses, hasLength(0));

          await manager.stopAll();
        });
    pkg1Dir.deleteSync(recursive: true);
  }

  @SkippedTest(
      reason: 'flaky timeouts',
      issue: 'https://github.com/dart-lang/sdk/issues/38629')
  Future<void> test_broadcastWatchEvent() async {
    var pkg1Dir = io.Directory.systemTemp.createTempSync('pkg1');
    var pkgPath = pkg1Dir.resolveSymbolicLinksSync();
    await withPlugin(
        pluginName: 'plugin1',
        test: (String plugin1Path) async {
          var contextRoot = _newContextRoot(pkgPath);
          await manager.addPluginToContextRoot(contextRoot, plugin1Path);
          var plugins = manager.pluginsForContextRoot(contextRoot);
          expect(plugins, hasLength(1));
          var watchEvent = watcher.WatchEvent(
              watcher.ChangeType.MODIFY, path.join(pkgPath, 'lib', 'lib.dart'));
          var responses = await manager.broadcastWatchEvent(watchEvent);
          expect(responses, hasLength(1));
          var response = await responses[0];
          expect(response, isNotNull);
          expect(response.error, isNull);
          await manager.stopAll();
        });
    pkg1Dir.deleteSync(recursive: true);
  }

  @SkippedTest(
      reason: 'flaky timeouts',
      issue: 'https://github.com/dart-lang/sdk/issues/38629')
  Future<void> test_pluginsForContextRoot_multiple() async {
    var pkg1Dir = io.Directory.systemTemp.createTempSync('pkg1');
    var pkgPath = pkg1Dir.resolveSymbolicLinksSync();
    await withPlugin(
        pluginName: 'plugin1',
        test: (String plugin1Path) async {
          await withPlugin(
              pluginName: 'plugin2',
              test: (String plugin2Path) async {
                var contextRoot = _newContextRoot(pkgPath);
                await manager.addPluginToContextRoot(contextRoot, plugin1Path);
                await manager.addPluginToContextRoot(contextRoot, plugin2Path);

                var plugins = manager.pluginsForContextRoot(contextRoot);
                expect(plugins, hasLength(2));
                var paths = plugins
                    .map((PluginInfo plugin) => plugin.pluginId)
                    .toList();
                expect(paths, unorderedEquals([plugin1Path, plugin2Path]));

                await manager.stopAll();
              });
        });
    pkg1Dir.deleteSync(recursive: true);
  }

  @SkippedTest(
      reason: 'flaky timeouts',
      issue: 'https://github.com/dart-lang/sdk/issues/38629')
  Future<void> test_pluginsForContextRoot_one() async {
    var pkg1Dir = io.Directory.systemTemp.createTempSync('pkg1');
    var pkgPath = pkg1Dir.resolveSymbolicLinksSync();
    await withPlugin(test: (String pluginPath) async {
      var contextRoot = _newContextRoot(pkgPath);
      await manager.addPluginToContextRoot(contextRoot, pluginPath);

      var plugins = manager.pluginsForContextRoot(contextRoot);
      expect(plugins, hasLength(1));
      expect(plugins[0].pluginId, pluginPath);

      await manager.stopAll();
    });
    pkg1Dir.deleteSync(recursive: true);
  }

  @SkippedTest(
      reason: 'flaky timeouts',
      issue: 'https://github.com/dart-lang/sdk/issues/38629')
  Future<void> test_removedContextRoot() async {
    var pkg1Dir = io.Directory.systemTemp.createTempSync('pkg1');
    var pkgPath = pkg1Dir.resolveSymbolicLinksSync();
    await withPlugin(test: (String pluginPath) async {
      var contextRoot = _newContextRoot(pkgPath);
      await manager.addPluginToContextRoot(contextRoot, pluginPath);

      manager.removedContextRoot(contextRoot);

      await manager.stopAll();
    });
    pkg1Dir.deleteSync(recursive: true);
  }

  @TestTimeout(Timeout.factor(4))
  @SkippedTest(
      reason: 'flaky timeouts',
      issue: 'https://github.com/dart-lang/sdk/issues/38629')
  Future<void> test_restartPlugins() async {
    var pkg1Dir = io.Directory.systemTemp.createTempSync('pkg1');
    var pkg1Path = pkg1Dir.resolveSymbolicLinksSync();
    var pkg2Dir = io.Directory.systemTemp.createTempSync('pkg2');
    var pkg2Path = pkg2Dir.resolveSymbolicLinksSync();
    await withPlugin(
        pluginName: 'plugin1',
        test: (String plugin1Path) async {
          await withPlugin(
              pluginName: 'plugin2',
              test: (String plugin2Path) async {
                var contextRoot1 = _newContextRoot(pkg1Path);
                var contextRoot2 = _newContextRoot(pkg2Path);
                await manager.addPluginToContextRoot(contextRoot1, plugin1Path);
                await manager.addPluginToContextRoot(contextRoot1, plugin2Path);
                await manager.addPluginToContextRoot(contextRoot2, plugin1Path);

                await manager.restartPlugins();
                var plugins = manager.plugins;
                expect(plugins, hasLength(2));
                expect(plugins[0].currentSession, isNotNull);
                expect(plugins[1].currentSession, isNotNull);
                if (plugins[0].pluginId.contains('plugin1')) {
                  expect(plugins[0].contextRoots,
                      unorderedEquals([contextRoot1, contextRoot2]));
                  expect(
                      plugins[1].contextRoots, unorderedEquals([contextRoot1]));
                } else {
                  expect(
                      plugins[0].contextRoots, unorderedEquals([contextRoot1]));
                  expect(plugins[1].contextRoots,
                      unorderedEquals([contextRoot1, contextRoot2]));
                }
                await manager.stopAll();
              });
        });
    pkg1Dir.deleteSync(recursive: true);
  }

  ContextRootImpl _newContextRoot(String root) {
    throw UnimplementedError();
  }
}

@reflectiveTest
class PluginManagerTest with ResourceProviderMixin, _ContextRoot {
  late String byteStorePath;
  late String sdkPath;
  late TestNotificationManager notificationManager;
  late PluginManager manager;

  void setUp() {
    byteStorePath = resourceProvider.convertPath('/byteStore');
    sdkPath = resourceProvider.convertPath('/sdk');
    notificationManager = TestNotificationManager();
    manager = PluginManager(resourceProvider, byteStorePath, sdkPath,
        notificationManager, InstrumentationService.NULL_SERVICE);
  }

  void test_broadcastRequest_none() {
    var contextRoot = _newContextRoot('/pkg1');
    var responses = manager.broadcastRequest(
        CompletionGetSuggestionsParams('/pkg1/lib/pkg1.dart', 100),
        contextRoot: contextRoot);
    expect(responses, hasLength(0));
  }

  void test_creation() {
    expect(manager.resourceProvider, resourceProvider);
    expect(manager.byteStorePath, byteStorePath);
    expect(manager.sdkPath, sdkPath);
    expect(manager.notificationManager, notificationManager);
  }

  void test_pathsFor_withPackageConfigJsonFile() {
    //
    // Build the minimal directory structure for a plugin package that includes
    // a '.dart_tool/package_config.json' file.
    //
    var pluginDirPath = newFolder('/plugin').path;
    var pluginFile = newFile2('/plugin/bin/plugin.dart', '');
    var packageConfigFile = newPackageConfigJsonFile('/plugin', '');
    //
    // Test path computation.
    //
    var files = manager.filesFor(pluginDirPath);
    expect(files.execution, pluginFile);
    expect(files.packages, packageConfigFile);
  }

  void test_pathsFor_withPubspec_inBazelWorkspace() {
    //
    // Build a Bazel workspace containing four packages, including the plugin.
    //
    newFile2('/workspaceRoot/WORKSPACE', '');
    newFolder('/workspaceRoot/bazel-bin');
    newFolder('/workspaceRoot/bazel-genfiles');

    String newPackage(String packageName, [List<String>? dependencies]) {
      var packageRoot =
          newFolder('/workspaceRoot/third_party/dart/$packageName').path;
      newFile2('$packageRoot/lib/$packageName.dart', '');
      var buffer = StringBuffer();
      if (dependencies != null) {
        buffer.writeln('dependencies:');
        for (var dependency in dependencies) {
          buffer.writeln('  $dependency: any');
        }
      }
      newPubspecYamlFile(packageRoot, buffer.toString());
      return packageRoot;
    }

    var pluginDirPath = newPackage('plugin', ['b', 'c']);
    var bRootPath = newPackage('b', ['d']);
    var cRootPath = newPackage('c', ['d']);
    var dRootPath = newPackage('d');
    var pluginFile = newFile2('$pluginDirPath/bin/plugin.dart', '');
    //
    // Test path computation.
    //
    var files = manager.filesFor(pluginDirPath);
    expect(files.execution, pluginFile);
    var packagesFile = files.packages;
    expect(packagesFile.exists, isTrue);

    var content = packagesFile.readAsStringSync();
    expect(content, '''
{
  "configVersion": 2,
  "packages": [
    {
      "name": "b",
      "rootUri": "${toUriStr(bRootPath)}",
      "packageUri": "lib/"
    },
    {
      "name": "c",
      "rootUri": "${toUriStr(cRootPath)}",
      "packageUri": "lib/"
    },
    {
      "name": "d",
      "rootUri": "${toUriStr(dRootPath)}",
      "packageUri": "lib/"
    },
    {
      "name": "plugin",
      "rootUri": "${toUriStr(pluginDirPath)}",
      "packageUri": "lib/"
    }
  ]
}
''');
  }

  void test_pluginsForContextRoot_none() {
    var contextRoot = _newContextRoot('/pkg1');
    expect(manager.pluginsForContextRoot(contextRoot), isEmpty);
  }

  void test_stopAll_none() {
    manager.stopAll();
  }
}

@reflectiveTest
class PluginSessionFromDiskTest extends PluginTestSupport {
  @SkippedTest(
      reason: 'flaky timeouts',
      issue: 'https://github.com/dart-lang/sdk/issues/38629')
  Future<void> test_start_notRunning() async {
    await withPlugin(test: (String pluginPath) async {
      var packagesPath = path.join(pluginPath, '.packages');
      var mainPath = path.join(pluginPath, 'bin', 'plugin.dart');
      var byteStorePath = path.join(pluginPath, 'byteStore');
      io.Directory(byteStorePath).createSync();
      PluginInfo plugin = DiscoveredPluginInfo(
          pluginPath,
          mainPath,
          packagesPath,
          notificationManager,
          InstrumentationService.NULL_SERVICE);
      var session = PluginSession(plugin);
      plugin.currentSession = session;
      expect(await session.start(byteStorePath, ''), isTrue);
      await session.stop();
    });
  }
}

@reflectiveTest
class PluginSessionTest with ResourceProviderMixin {
  late TestNotificationManager notificationManager;
  late String pluginPath;
  late String executionPath;
  late String packagesPath;
  late String sdkPath;
  late PluginInfo plugin;
  late PluginSession session;

  void setUp() {
    notificationManager = TestNotificationManager();
    pluginPath = resourceProvider.convertPath('/pluginDir');
    executionPath = resourceProvider.convertPath('/pluginDir/bin/plugin.dart');
    packagesPath = resourceProvider.convertPath('/pluginDir/.packages');
    sdkPath = resourceProvider.convertPath('/sdk');
    plugin = DiscoveredPluginInfo(pluginPath, executionPath, packagesPath,
        notificationManager, InstrumentationService.NULL_SERVICE);
    session = PluginSession(plugin);
  }

  void test_handleNotification() {
    var notification =
        AnalysisErrorsParams('/test.dart', <AnalysisError>[]).toNotification();
    expect(notificationManager.notifications, hasLength(0));
    session.handleNotification(notification);
    expect(notificationManager.notifications, hasLength(1));
    expect(notificationManager.notifications[0], notification);
  }

  void test_handleOnDone() {
    var channel = TestServerCommunicationChannel(session);
    session.handleOnDone();
    expect(channel.closeCount, 1);
    expect(session.pluginStoppedCompleter.isCompleted, isTrue);
  }

  @failingTest
  void test_handleOnError() {
    session.handleOnError(<String>['message', 'trace']);
    fail('The method handleOnError is not implemented');
  }

  Future<void> test_handleResponse() async {
    TestServerCommunicationChannel(session);
    var response = PluginVersionCheckResult(true, 'name', 'version', <String>[],
            contactInfo: 'contactInfo')
        .toResponse('0', 1);
    var future = session.sendRequest(PluginVersionCheckParams('', '', ''));
    expect(session.pendingRequests, hasLength(1));
    session.handleResponse(response);
    expect(session.pendingRequests, hasLength(0));
    var result = await future;
    expect(result, same(response));
  }

  void test_nextRequestId() {
    expect(session.requestId, 0);
    expect(session.nextRequestId, '0');
    expect(session.requestId, 1);
  }

  void test_sendRequest() {
    var channel = TestServerCommunicationChannel(session);
    session.sendRequest(PluginVersionCheckParams('', '', ''));
    expect(channel.sentRequests, hasLength(1));
    expect(channel.sentRequests[0].method, 'plugin.versionCheck');
  }

  Future<void> test_start_notCompatible() async {
    session.isCompatible = false;
    expect(await session.start(path.join(pluginPath, 'byteStore'), sdkPath),
        isFalse);
  }

  Future<void> test_start_running() async {
    TestServerCommunicationChannel(session);
    try {
      await session.start('', '');
      fail('Expected a StateError to be thrown');
    } on StateError {
      // Expected behavior
    }
  }

  void test_stop_notRunning() {
    expect(() => session.stop(), throwsStateError);
  }

  Future<void> test_stop_running() async {
    var channel = TestServerCommunicationChannel(session);
    await session.stop();
    expect(channel.sentRequests, hasLength(1));
    expect(channel.sentRequests[0].method, 'plugin.shutdown');
  }
}

/// A class designed to be used as a superclass for test classes that define
/// tests that require plugins to be created on disk.
abstract class PluginTestSupport {
  late PhysicalResourceProvider resourceProvider;
  late TestNotificationManager notificationManager;

  /// The content to be used for the '.packages' file, or `null` if the content
  /// has not yet been computed.
  String? _packagesFileContent;

  void setUp() {
    resourceProvider = PhysicalResourceProvider.INSTANCE;
    notificationManager = TestNotificationManager();
  }

  /// Create a directory structure representing a plugin on disk, run the given
  /// [test] function, and then remove the directory. The directory will have
  /// the following structure:
  /// ```
  /// pluginDirectory
  ///   .packages
  ///   bin
  ///     plugin.dart
  /// ```
  /// The name of the plugin directory will be the [pluginName], if one is
  /// provided (in order to allow more than one plugin to be created by a single
  /// test). The 'plugin.dart' file will contain the given [content], or default
  /// content that implements a minimal plugin if the contents are not given.
  /// The [test] function will be passed the path of the directory that was
  /// created.
  Future<void> withPlugin(
      {String? content,
      String? pluginName,
      required Future<void> Function(String) test}) async {
    var tempDirectory =
        io.Directory.systemTemp.createTempSync(pluginName ?? 'test_plugin');
    try {
      var pluginPath = tempDirectory.resolveSymbolicLinksSync();
      //
      // Create a .packages file.
      //
      var packagesFile = io.File(path.join(pluginPath, '.packages'));
      packagesFile.writeAsStringSync(_getPackagesFileContent());
      //
      // Create the 'bin' directory.
      //
      var binPath = path.join(pluginPath, 'bin');
      io.Directory(binPath).createSync();
      //
      // Create the 'plugin.dart' file.
      //
      var pluginFile = io.File(path.join(binPath, 'plugin.dart'));
      pluginFile.writeAsStringSync(content ?? _defaultPluginContent());
      //
      // Run the actual test code.
      //
      await test(pluginPath);
    } finally {
      tempDirectory.deleteSync(recursive: true);
    }
  }

  /// Create a directory structure representing a plugin on disk, run the given
  /// [test] function, and then remove the directory. The directory will have
  /// the following structure:
  /// ```
  /// pluginDirectory
  ///   pubspec.yaml
  ///   bin
  ///     plugin.dart
  /// ```
  /// The name of the plugin directory will be the [pluginName], if one is
  /// provided (in order to allow more than one plugin to be created by a single
  /// test). The 'plugin.dart' file will contain the given [content], or default
  /// content that implements a minimal plugin if the contents are not given.
  /// The [test] function will be passed the path of the directory that was
  /// created.
  Future<void> withPubspecPlugin(
      {String? content,
      String? pluginName,
      required Future<void> Function(String) test}) async {
    var tempDirectory =
        io.Directory.systemTemp.createTempSync(pluginName ?? 'test_plugin');
    try {
      var pluginPath = tempDirectory.resolveSymbolicLinksSync();
      //
      // Create a pubspec.yaml file.
      //
      var pubspecFile = io.File(path.join(pluginPath, file_paths.pubspecYaml));
      pubspecFile.writeAsStringSync(_getPubspecFileContent());
      //
      // Create the 'bin' directory.
      //
      var binPath = path.join(pluginPath, 'bin');
      io.Directory(binPath).createSync();
      //
      // Create the 'plugin.dart' file.
      //
      var pluginFile = io.File(path.join(binPath, 'plugin.dart'));
      pluginFile.writeAsStringSync(content ?? _defaultPluginContent());
      //
      // Run the actual test code.
      //
      await test(pluginPath);
    } finally {
      tempDirectory.deleteSync(recursive: true);
    }
  }

  /// Convert the [sdkPackageMap] into a plugin-specific map by applying the
  /// given relative path [delta] to each line.
  String _convertPackageMap(String sdkDirPath, List<String> sdkPackageMap) {
    var buffer = StringBuffer();
    for (var line in sdkPackageMap) {
      if (!line.startsWith('#')) {
        var index = line.indexOf(':');
        var packageName = line.substring(0, index + 1);
        var relativePath = line.substring(index + 1);
        var absolutePath = path.join(sdkDirPath, relativePath);
        // Convert to file:/// URI since that's how absolute paths in
        // .packages must be for windows
        absolutePath = Uri.file(absolutePath).toString();
        buffer.write(packageName);
        buffer.writeln(absolutePath);
      }
    }
    return buffer.toString();
  }

  /// The default content of the plugin. This is a minimal plugin that will only
  /// respond correctly to version checks and to shutdown requests.
  String _defaultPluginContent() {
    return r'''
import 'dart:async';
import 'dart:isolate';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer_plugin/plugin/plugin.dart';
import 'package:analyzer_plugin/protocol/protocol_generated.dart';
import 'package:analyzer_plugin/starter.dart';
import 'package:pub_semver/pub_semver.dart';

void main(List<String> args, SendPort sendPort) {
  MinimalPlugin plugin = new MinimalPlugin(PhysicalResourceProvider.INSTANCE);
  new ServerPluginStarter(plugin).start(sendPort);
}

class MinimalPlugin extends ServerPlugin {
  MinimalPlugin(ResourceProvider provider) : super(provider);

  @override
  List<String> get fileGlobsToAnalyze => <String>['**/*.dart'];

  @override
  String get name => 'minimal';

  @override
  String get version => '0.0.1';

  @override
  AnalysisDriverGeneric createAnalysisDriver(ContextRoot contextRoot) => null;

  @override
  Future<AnalysisHandleWatchEventsResult> handleAnalysisHandleWatchEvents(
      AnalysisHandleWatchEventsParams parameters) async =>
    new AnalysisHandleWatchEventsResult();

  @override
  bool isCompatibleWith(Version serverVersion) => true;
}
''';
  }

  /// Return the content to be used for the '.packages' file.
  String _getPackagesFileContent() {
    var packagesFileContent = _packagesFileContent;
    if (packagesFileContent == null) {
      var sdkPackagesFile = io.File(_sdkPackagesPath());
      var sdkPackageMap = sdkPackagesFile.readAsLinesSync();
      packagesFileContent = _packagesFileContent =
          _convertPackageMap(path.dirname(sdkPackagesFile.path), sdkPackageMap);
    }
    return packagesFileContent;
  }

  /// Return the content to be used for the 'pubspec.yaml' file.
  String _getPubspecFileContent() {
    return '''
name: 'test'
dependencies:
  analyzer: any
  analyzer_plugin: any
''';
  }

  /// Return the path to the '.packages' file in the root of the SDK checkout.
  String _sdkPackagesPath() {
    var packagesPath = io.Platform.script.toFilePath();
    while (packagesPath.isNotEmpty &&
        path.basename(packagesPath) != 'analysis_server') {
      packagesPath = path.dirname(packagesPath);
    }
    packagesPath = path.dirname(packagesPath);
    packagesPath = path.dirname(packagesPath);
    return path.join(packagesPath, '.packages');
  }
}

class TestNotificationManager implements AbstractNotificationManager {
  List<Notification> notifications = <Notification>[];

  Map<String, Map<String, List<AnalysisError>>> recordedErrors =
      <String, Map<String, List<AnalysisError>>>{};

  @override
  void handlePluginNotification(String pluginId, Notification notification) {
    notifications.add(notification);
  }

  @override
  dynamic noSuchMethod(Invocation invocation) {
    fail('Unexpected invocation of ${invocation.memberName}');
  }

  @override
  void recordAnalysisErrors(
      String pluginId, String filePath, List<AnalysisError> errorData) {
    recordedErrors.putIfAbsent(
        pluginId, () => <String, List<AnalysisError>>{})[filePath] = errorData;
  }
}

class TestServerCommunicationChannel implements ServerCommunicationChannel {
  final PluginSession session;
  int closeCount = 0;
  List<Request> sentRequests = <Request>[];

  TestServerCommunicationChannel(this.session) {
    session.channel = this;
  }

  @override
  void close() {
    closeCount++;
  }

  @override
  void kill() {
    fail('Unexpected invocation of kill');
  }

  @override
  void listen(void Function(Response response) onResponse,
      void Function(Notification notification) onNotification,
      {void Function(dynamic error)? onError, void Function()? onDone}) {
    fail('Unexpected invocation of listen');
  }

  @override
  void sendRequest(Request request) {
    sentRequests.add(request);
    if (request.method == 'plugin.shutdown') {
      session.handleOnDone();
    }
  }
}

mixin _ContextRoot on ResourceProviderMixin {
  ContextRootImpl _newContextRoot(String root) {
    root = convertPath(root);
    return ContextRootImpl(
      resourceProvider,
      resourceProvider.getFolder(root),
      BasicWorkspace.find(resourceProvider, {}, root),
    );
  }
}
