// 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/');
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,
      []
        ..add('--verbosity=warning')
        ..addAll(executableArguments)
        ..add(pathOfData.resolve('http_launch_main.dart').toFilePath()));
  Future<ProcessResult> http_run = Process.run(
      pathToExecutable,
      []
        ..add('--verbosity=warning')
        ..addAll(executableArguments)
        ..add('http://127.0.0.1:$port/http_launch_main.dart'));
  Future<ProcessResult> http_pkg_root_run = Process.run(
      pathToExecutable,
      []
        ..add('--verbosity=warning')
        ..addAll(executableArguments)
        ..addAll(['http://127.0.0.1:$port/http_launch_main.dart']));
  Future<ProcessResult> isolate_run = Process.run(
      pathToExecutable,
      []
        ..add('--verbosity=warning')
        ..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);
}
