// 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,
      []
        ..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);
}
