// Copyright 2020 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.

utils.load('test/inspector/wasm-inspector-test.js');

let {session, contextGroup, Protocol} =
    InspectorTest.start('Tests stepping through wasm scripts by byte offsets');
session.setupScriptMap();

const builder = new WasmModuleBuilder();

const func_a =
    builder.addFunction('wasm_A', kSig_v_i).addBody([kExprNop, kExprNop]);
const func_a_idx = func_a.index;

// wasm_B calls wasm_A <param0> times.
const func_b = builder.addFunction('wasm_B', kSig_v_i)
    .addBody([
      // clang-format off
      kExprLoop, kWasmStmt,               // while
        kExprLocalGet, 0,                 // -
        kExprIf, kWasmStmt,               // if <param0> != 0
          kExprLocalGet, 0,               // -
          kExprI32Const, 1,               // -
          kExprI32Sub,                    // -
          kExprLocalSet, 0,               // decrease <param0>
          ...wasmI32Const(1024),          // some longer i32 const (2 byte imm)
          kExprCallFunction, func_a_idx,  // -
          kExprBr, 1,                     // continue
          kExprEnd,                       // -
        kExprEnd,                         // break
      // clang-format on
    ])
    .exportAs('main');

const module_bytes = builder.toArray();
const loop_start_offset = func_b.body_offset + 2;
const loop_body_start_offset = loop_start_offset + 2;
const loop_body_end_offset = loop_body_start_offset + 14;
const if_statement_offset = loop_body_start_offset + 2
const call_function_offset = loop_body_start_offset + 12;

const func_a_start_offset = func_a.body_offset;
const func_a_end_offset = func_a_start_offset + 2;

runTest()
    .catch(reason => InspectorTest.log(`Failed: ${reason}`))
    .then(InspectorTest.completeTest);

async function runTest() {
  await Protocol.Debugger.enable();
  InspectorTest.log('Setting up global instance variable');
  WasmInspectorTest.instantiate(module_bytes);
  const [, {params: wasmScript}] = await Protocol.Debugger.onceScriptParsed(2);
  const scriptId = wasmScript.scriptId;

  InspectorTest.log('Got wasm script: ' + wasmScript.url);

  let bpmsg = await Protocol.Debugger.setBreakpoint({
    location:
        {scriptId: scriptId, lineNumber: 0, columnNumber: loop_start_offset}
  });
  InspectorTest.logMessage(bpmsg.result.actualLocation);

  await checkValidSkipLists(scriptId);
  await checkInvalidSkipLists(scriptId);

  InspectorTest.log('Finished!');
}

async function checkValidSkipLists(scriptId) {
  InspectorTest.log('Test with valid skip lists');
  Protocol.Runtime.evaluate({expression: 'instance.exports.main(8)'});
  const {params: {callFrames}} = await Protocol.Debugger.oncePaused();
  await session.logSourceLocation(callFrames[0].location);

  InspectorTest.log('Test: Stepping over without skip list');
  let skipList = [];
  await stepThroughOneLoopIteration(skipList, 'stepOver');

  InspectorTest.log('Test: Stepping over with skip list');
  skipList = [
    createLocationRange(scriptId, loop_body_start_offset, if_statement_offset),
    createLocationRange(scriptId, call_function_offset, loop_body_end_offset)
  ];
  await stepThroughOneLoopIteration(skipList, 'stepOver');

  InspectorTest.log('Test: Stepping over start location is inclusive');
  skipList = [
    createLocationRange(
        scriptId, loop_body_start_offset, loop_body_end_offset - 1),
  ];
  await stepThroughOneLoopIteration(skipList, 'stepOver');

  InspectorTest.log('Test: Stepping over end location is exclusive');
  skipList = [
    createLocationRange(
        scriptId, loop_body_start_offset + 1, loop_body_end_offset),
  ];
  await stepThroughOneLoopIteration(skipList, 'stepOver');

  InspectorTest.log('Test: Stepping into without skip list');
  skipList = [];
  await stepThroughOneLoopIteration(skipList, 'stepInto');

  InspectorTest.log(
      'Test: Stepping into with skip list, while call itself is skipped');
  skipList = [
    createLocationRange(scriptId, func_a_start_offset, func_a_end_offset),
    createLocationRange(scriptId, if_statement_offset, loop_body_end_offset)
  ];
  await stepThroughOneLoopIteration(skipList, 'stepInto');

  InspectorTest.log('Test: Stepping into start location is inclusive');
  skipList = [
    createLocationRange(scriptId, func_a_start_offset, func_a_end_offset - 1),
  ];
  await stepThroughOneLoopIteration(skipList, 'stepInto');

  InspectorTest.log('Test: Stepping into end location is exclusive');
  skipList = [
    createLocationRange(scriptId, func_a_start_offset - 1, func_a_end_offset),
  ];
  await stepThroughOneLoopIteration(skipList, 'stepInto');

  await Protocol.Debugger.resume();
}

async function checkInvalidSkipLists(scriptId) {
  InspectorTest.log('Test with invalid skip lists');
  Protocol.Runtime.evaluate({expression: 'instance.exports.main(8)'});
  const {params: {callFrames}} = await Protocol.Debugger.oncePaused();
  await session.logSourceLocation(callFrames[0].location);

  const actions = ['stepOver', 'stepInto'];
  for (let action of actions) {
    InspectorTest.log('Test: start position has invalid column number');
    let skipList = [
      createLocationRange(scriptId, -1, loop_body_end_offset),
    ];
    await stepThroughOneLoopIteration(skipList, action);

    InspectorTest.log('Test: start position has invalid line number');
    skipList = [{
      scriptId: scriptId,
      start: {lineNumber: -1, columnNumber: 0},
      end: {lineNumber: 0, columnNumber: loop_body_end_offset}
    }];
    await stepThroughOneLoopIteration(skipList, action);

    InspectorTest.log('Test: end position smaller than start position');
    skipList = [createLocationRange(
        scriptId, loop_body_end_offset, loop_body_start_offset)];
    await stepThroughOneLoopIteration(skipList, action);

    InspectorTest.log('Test: skip list is not maximally merged');
    skipList = [
      createLocationRange(
          scriptId, loop_body_start_offset, if_statement_offset),
      createLocationRange(scriptId, if_statement_offset, loop_body_end_offset)
    ];
    await stepThroughOneLoopIteration(skipList, action);

    InspectorTest.log('Test: skip list is not sorted');
    skipList = [
      createLocationRange(scriptId, if_statement_offset, loop_body_end_offset),
      createLocationRange(
          scriptId, loop_body_start_offset, loop_body_end_offset)
    ];
    await stepThroughOneLoopIteration(skipList, action);
  }
}

async function stepThroughOneLoopIteration(skipList, stepAction) {
  InspectorTest.log(
      `Testing ${stepAction} with skipList: ${JSON.stringify(skipList)}`);
  let topFrameLocation = -1;
  while (topFrameLocation.columnNumber != loop_start_offset) {
    const stepOverMsg = await Protocol.Debugger[stepAction]({skipList});
    if (stepOverMsg.error) {
      InspectorTest.log(stepOverMsg.error.message);
      return;
    }
    const {params: {callFrames}} = await Protocol.Debugger.oncePaused();
    topFrameLocation = callFrames[0].location;
    await session.logSourceLocation(topFrameLocation);
  }
}

function createLocationRange(scriptId, startColumn, endColumn) {
  return {
    scriptId: scriptId, start: {lineNumber: 0, columnNumber: startColumn},
        end: {lineNumber: 0, columnNumber: endColumn}
  }
}
