// Copyright (c) 2013, 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.
// VMOptions=
// VMOptions=--short_socket_read
// VMOptions=--short_socket_write
// VMOptions=--short_socket_read --short_socket_write
// OtherResources=http_launch_data/http_isolate_main.dart
// OtherResources=http_launch_data/http_launch_main.dart
// OtherResources=http_launch_data/http_spawn_main.dart
// OtherResources=http_launch_data/the_packages/simple/simple.dart
// OtherResources=http_launch_data/.packages
//
// Test:
//   *) Launching a script fetched over HTTP.
//   *) Importing a library fetched over HTTP.
//   *) Automatically resolving package_root when script is fetched over HTTP.
//   *) Spawning a URI over HTTP.

library http_launch_test;

import 'dart:async';
import 'dart:io';
import 'package:expect/expect.dart';

String pathToExecutable = Platform.executable;
List<String> executableArguments = Platform.executableArguments
    .where((arg) => !arg.startsWith('--packages='))
    .toList();
Uri pathOfData = Platform.script.resolve('http_launch_data/');
late int port;

_sendNotFound(HttpResponse response) {
  response.statusCode = HttpStatus.notFound;
  response.close();
}

handleRequest(HttpRequest request) {
  final String path = request.uri.path.substring(1);
  final Uri requestPath = pathOfData.resolve(path);
  final File file = new File(requestPath.toFilePath());
  file.exists().then((bool found) {
    if (found) {
      file.openRead().cast<List<int>>().pipe(request.response).catchError((e) {
        _sendNotFound(request.response);
      });
    } else {
      _sendNotFound(request.response);
    }
  });
}

serverRunning(HttpServer server) {
  port = server.port;
  server.listen(handleRequest);
  Future<ProcessResult> no_http_run = Process.run(
      pathToExecutable,
      []
        ..addAll(executableArguments)
        ..add(pathOfData.resolve('http_launch_main.dart').toFilePath()));
  Future<ProcessResult> http_run = Process.run(
      pathToExecutable,
      []
        ..addAll(executableArguments)
        ..add('http://127.0.0.1:$port/http_launch_main.dart'));
  Future<ProcessResult> http_pkg_root_run = Process.run(
      pathToExecutable,
      []
        ..addAll(executableArguments)
        ..addAll(['http://127.0.0.1:$port/http_launch_main.dart']));
  Future<ProcessResult> isolate_run = Process.run(
      pathToExecutable,
      []
        ..addAll(executableArguments)
        ..addAll(['http://127.0.0.1:$port/http_spawn_main.dart', '$port']));
  Future<List<ProcessResult>> results =
      Future.wait([no_http_run, http_run, http_pkg_root_run, isolate_run]);
  results.then((results) {
    // Close server.
    server.close();
    // Check results.
    checkResults(results);
  });
}

checkResults(List<ProcessResult> results) {
  Expect.equals(4, results.length);
  // Exited cleanly.
  for (int i = 0; i < results.length; i++) {
    ProcessResult result = results[i];
    if (result.exitCode != 0) {
      print("Exit code for process $i = ${result.exitCode}");
      print("---stdout:---\n${result.stdout}");
      print("---stderr:---\n${result.stderr}\n---");
    }
    Expect.equals(0, result.exitCode);
  }
  String stdout = results[0].stdout;
  // Output is the string 'hello'. Use startsWith to avoid new line differences.
  if (!stdout.startsWith('hello')) {
    print("---- stdout of remote process:\n$stdout\n----");
  }
  Expect.isTrue(stdout.startsWith('hello'));
  // Same output from all three process runs.
  for (int i = 0; i < results.length; i++) {
    Expect.equals(stdout, results[i].stdout);
  }
}

main() {
  HttpServer.bind(InternetAddress.loopbackIPv4, 0).then(serverRunning);
}
