/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/*
 * Tests for correct behavior of the server start() and stop() methods.
 */

XPCOMUtils.defineLazyGetter(this, "PORT", function() {
  return srv.identity.primaryPort;
});

XPCOMUtils.defineLazyGetter(this, "PREPATH", function() {
  return "http://localhost:" + PORT;
});

var srv, srv2;

function run_test()
{
  if (mozinfo.os == "win")
  {
    dumpn("*** not running test_start_stop.js on Windows for now, because " +
          "Windows is dumb");
    return;
  }

  dumpn("*** run_test");

  srv = createServer();
  srv.start(-1);

  try
  {
    srv.start(PORT);
    do_throw("starting a started server");
  }
  catch (e)
  {
    isException(e, Cr.NS_ERROR_ALREADY_INITIALIZED);
  }

  do_test_pending();
  srv.stop(function()
  {
    try
    {
      do_test_pending();
      run_test_2();
    }
    finally
    {
      do_test_finished();
    }
  });
}

function run_test_2()
{
  dumpn("*** run_test_2");

  do_test_finished();

  srv.start(PORT);
  srv2 = createServer();

  try
  {
    srv2.start(PORT);
    do_throw("two servers on one port?");
  }
  catch (e)
  {
    isException(e, Cr.NS_ERROR_NOT_AVAILABLE);
  }

  do_test_pending();
  try
  {
    srv.stop({onStopped: function()
              {
                try
                {
                  do_test_pending();
                  run_test_3();
                }
                finally
                {
                  do_test_finished();
                }
              }
             });
  }
  catch (e)
  {
    do_throw("error stopping with an object: " + e);
  }
}

function run_test_3()
{
  dumpn("*** run_test_3");

  do_test_finished();

  srv.start(PORT);

  do_test_pending();
  try
  {
    srv.stop().then(function()
    {
      try {
        do_test_pending();
        run_test_4();
      } finally {
        do_test_finished();
      }
    });
  }
  catch (e)
  {
    do_throw("error stopping with an object: " + e);
  }
}

function run_test_4()
{
  dumpn("*** run_test_4");

  do_test_finished();

  srv.registerPathHandler("/handle", handle);
  srv.start(PORT);

  // Don't rely on the exact (but implementation-constant) sequence of events
  // as it currently exists by making either run_test_5 or serverStopped handle
  // the final shutdown.
  do_test_pending();

  runHttpTests([new Test(PREPATH + "/handle")], run_test_5);
}

var testsComplete = false;

function run_test_5()
{
  dumpn("*** run_test_5");

  testsComplete = true;
  if (stopped)
    do_test_finished();
}


const INTERVAL = 500;

function handle(request, response)
{
  response.processAsync();

  dumpn("*** stopping server...");
  srv.stop(serverStopped);

  callLater(INTERVAL, function()
  {
    Assert.ok(!stopped);

    callLater(INTERVAL, function()
    {
      Assert.ok(!stopped);
      response.finish();

      try
      {
        response.processAsync();
        do_throw("late processAsync didn't throw?");
      }
      catch (e)
      {
        isException(e, Cr.NS_ERROR_UNEXPECTED);
      }
    });
  });
}

var stopped = false;
function serverStopped()
{
  dumpn("*** server really, fully shut down now");
  stopped = true;
  if (testsComplete)
    do_test_finished();
}
