// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

InspectorTest.log('Checks Debugger.pause');
let contextGroup1 = new InspectorTest.ContextGroup();
let session1 = contextGroup1.connect();
let Protocol1 = session1.Protocol;

session1.setupScriptMap();
Protocol1.Debugger.enable();
InspectorTest.runAsyncTestSuite([
  async function testPause() {
    Protocol1.Debugger.pause();
    Protocol1.Runtime.evaluate({expression: 'var a = 42;'});
    await waitPauseAndDumpLocation(session1);
    await Protocol1.Debugger.resume();
  },

  async function testSkipFrameworks() {
    Protocol1.Debugger.setBlackboxPatterns({patterns: ['framework\.js']});
    Protocol1.Debugger.pause();
    Protocol1.Runtime.evaluate({expression: 'var a = 42; //# sourceURL=framework.js'});
    Protocol1.Runtime.evaluate({expression: 'var a = 239;'});
    await waitPauseAndDumpLocation(session1);
    await Protocol1.Debugger.resume();
  },

  async function testSkipOtherContext1() {
    let contextGroup2 = new InspectorTest.ContextGroup();
    let session2 = contextGroup2.connect();
    let Protocol2 = session2.Protocol;
    Protocol2.Debugger.enable({});
    Protocol1.Debugger.pause();
    Protocol1.Runtime.evaluate({expression: 'var a = 42; //# sourceURL=framework.js'});
    Protocol2.Runtime.evaluate({expression: 'var a = 239;'});
    Protocol1.Runtime.evaluate({expression: 'var a = 1;'});
    await waitPauseAndDumpLocation(session1);
    await Protocol1.Debugger.resume();
    await Protocol2.Debugger.disable({});
  },

  async function testSkipOtherContext2() {
    let contextGroup2 = new InspectorTest.ContextGroup();
    let session2 = contextGroup2.connect();
    let Protocol2 = session2.Protocol;
    session2.setupScriptMap();
    Protocol2.Debugger.enable({});
    Protocol2.Debugger.pause({});
    Protocol1.Runtime.evaluate({expression: 'var a = 42; //# sourceURL=framework.js'});
    Protocol2.Runtime.evaluate({expression: 'var a = 239;'});
    Protocol1.Runtime.evaluate({expression: 'var a = 1;'});
    await waitPauseAndDumpLocation(session2);
    // should not resume pause from different context group id.
    Protocol1.Debugger.resume();
    Protocol2.Debugger.stepOver({});
    await waitPauseAndDumpLocation(session2);
    await Protocol2.Debugger.resume({});
    await Protocol2.Debugger.disable({});
  },

  async function testWithNativeBreakpoint() {
    contextGroup1.schedulePauseOnNextStatement('', '');
    await Protocol1.Debugger.pause();
    contextGroup1.cancelPauseOnNextStatement();
    Protocol1.Runtime.evaluate({expression: 'var a = 42;'});
    await waitPauseAndDumpLocation(session1);
    await Protocol1.Debugger.resume();

    await Protocol1.Debugger.pause();
    contextGroup1.schedulePauseOnNextStatement('', '');
    contextGroup1.cancelPauseOnNextStatement();
    Protocol1.Runtime.evaluate({expression: 'var a = 42;'});
    await waitPauseAndDumpLocation(session1);
    await Protocol1.Debugger.resume();

    contextGroup1.schedulePauseOnNextStatement('', '');
    contextGroup1.cancelPauseOnNextStatement();
    await Protocol1.Debugger.pause();
    Protocol1.Runtime.evaluate({expression: 'var a = 42;'});
    await waitPauseAndDumpLocation(session1);
    await Protocol1.Debugger.resume();
  },

  async function testResumeAnotherGroup() {
    let contextGroup2 = new InspectorTest.ContextGroup();
    let session2 = contextGroup2.connect();
    session2.setupScriptMap();
    let Protocol2 = session2.Protocol;
    Protocol2.Debugger.enable();
    Protocol1.Debugger.pause();
    Protocol1.Runtime.evaluate({expression: 'var a = 42;'});
    await waitPauseAndDumpLocation(session1);
    InspectorTest.logMessage(await Protocol2.Debugger.resume());
    InspectorTest.logMessage(await Protocol2.Debugger.stepOver());
    InspectorTest.logMessage(await Protocol2.Debugger.stepInto());
    InspectorTest.logMessage(await Protocol2.Debugger.stepOut());
    await Protocol1.Debugger.resume();
    await Protocol2.Debugger.disable();
  },

  async function testDisableBreaksShouldCancelPause() {
    await Protocol1.Debugger.pause();
    await Protocol1.Debugger.setBreakpointsActive({active: false});
    Protocol1.Runtime.evaluate({expression: 'var a = 42;'})
      .then(() => Protocol1.Debugger.setBreakpointsActive({active: true}))
      .then(() => Protocol1.Runtime.evaluate({expression: 'debugger'}));
    await waitPauseAndDumpLocation(session1);
    await Protocol1.Debugger.resume();
  }
]);

async function waitPauseAndDumpLocation(session) {
  var message = await session.Protocol.Debugger.oncePaused();
  InspectorTest.log('paused at:');
  await session.logSourceLocation(message.params.callFrames[0].location);
  return message;
}
