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

// Flags: --expose-wasm

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

let {session, contextGroup, Protocol} = InspectorTest.start('Tests breakable locations in wasm');

var builder = new WasmModuleBuilder();

// clang-format off
var func_idx = builder.addFunction('helper', kSig_v_v)
    .addLocals(kWasmI32, 1 )
    .addBody([
        kExprNop,
        kExprI32Const, 12,
        kExprLocalSet, 0,
    ]).index;

builder.addFunction('main', kSig_v_i)
    .addBody([
        kExprLocalGet, 0,
        kExprIf, kWasmStmt,
        kExprBlock, kWasmStmt,
        kExprCallFunction, func_idx,
        kExprEnd,
        kExprEnd
    ]).exportAs('main');
// clang-format on

var module_bytes = builder.toArray();

Protocol.Debugger.enable();
Protocol.Debugger.onScriptParsed(handleScriptParsed);

async function runTest() {
  InspectorTest.log('Running testFunction...');
  await WasmInspectorTest.instantiate(module_bytes);
  await getBreakableLocationsForAllWasmScripts();
  await setAllBreakableLocations();
  InspectorTest.log('Running wasm code...');
  // Begin executing code:
  var promise = WasmInspectorTest.evalWithUrl('instance.exports.main(1)', 'runWasm');
  await waitForAllPauses();
  // Code should now complete
  await promise;
  InspectorTest.log('Finished!');
}

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

var allBreakableLocations = [];

var urls = {};
var numScripts = 0;
var wasmScripts = [];
function handleScriptParsed(messageObject) {
  var scriptId = messageObject.params.scriptId;
  var url = messageObject.params.url;
  urls[scriptId] = url;
  InspectorTest.log('Script nr ' + numScripts + ' parsed. URL: ' + url);
  ++numScripts;

  if (url.startsWith('wasm://')) {
    // Only want the full module script, not the function specific ones.
    if (url.split('/').length == 4) {
      InspectorTest.log('This is a wasm script (nr ' + wasmScripts.length + ').');
      wasmScripts.push(scriptId);
    }
  }
}

function printFailure(message) {
  if (!message.result) {
    InspectorTest.logMessage(message);
  }
}

function printBreakableLocations(message, expectedScriptId, bytecode) {
  var locations = message.result.locations;
  InspectorTest.log(locations.length + ' breakable location(s):');
  for (var i = 0; i < locations.length; ++i) {
    if (locations[i].scriptId != expectedScriptId) {
      InspectorTest.log(
          'SCRIPT ID MISMATCH!! ' + locations[i].scriptId + ' != ' +
          expectedScriptId);
    }
    if (locations[i].lineNumber != 0) {
      InspectorTest.log(`Unexpected line number: ${bytecode[locations[i].lineNumber]}`);
    }
    var line = `byte=${bytecode[locations[i].columnNumber]}`;
    InspectorTest.log(
        '[' + i + '] ' + locations[i].lineNumber + ':' +
        locations[i].columnNumber + ' || ' + line);
  }
}

function checkModuleBytes(encoded, bytecode) {
  // Encode bytecode as base64.
  var BASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  var PAD = '=';
  var ret = '';
  var leftchar = 0;
  var leftbits = 0;
  for (var i = 0; i < bytecode.length; i++) {
    leftchar = (leftchar << 8) | bytecode[i];
    leftbits += 8;
    while (leftbits >= 6) {
      var curr = (leftchar >> (leftbits-6)) & 0x3f;
      leftbits -= 6;
      ret += BASE[curr];
    }
  }
  if (leftbits == 2) {
    ret += BASE[(leftchar&3) << 4];
    ret += PAD + PAD;
  } else if (leftbits == 4) {
    ret += BASE[(leftchar&0xf) << 2];
    ret += PAD;
  }

  // Check the base64 strings match.
  if(ret == encoded) {
    InspectorTest.log('Bytecode matches!');
  } else {
    InspectorTest.log('Original: ' + ret);
    InspectorTest.log('Returned by API: ' + encoded);
  }
}

async function checkGetBreakableLocations(wasmScriptNr) {
  InspectorTest.log(
    'Requesting all breakable locations in wasm script ' + wasmScriptNr);
  var scriptId = wasmScripts[wasmScriptNr];

  var msg = await Protocol.Debugger.getScriptSource({scriptId: scriptId});
  checkModuleBytes(msg.result.bytecode, module_bytes);

  msg = await Protocol.Debugger.getPossibleBreakpoints(
      {start: {lineNumber: 0, columnNumber: 0, scriptId: scriptId}});
  printFailure(msg);
  allBreakableLocations.push(...msg.result.locations);
  printBreakableLocations(msg, scriptId, module_bytes);

  InspectorTest.log('Requesting breakable locations in offsets [0,45)');
  msg = await Protocol.Debugger.getPossibleBreakpoints({
      start: {lineNumber: 0, columnNumber: 0, scriptId: scriptId},
      end: {lineNumber: 0, columnNumber: 45, scriptId: scriptId}});
  printFailure(msg);
  printBreakableLocations(msg, scriptId, module_bytes);

  InspectorTest.log('Requesting breakable locations in offsets [50,60)');
  msg = await Protocol.Debugger.getPossibleBreakpoints({
      start: {lineNumber: 0, columnNumber: 50, scriptId: scriptId},
      end: {lineNumber: 0, columnNumber: 60, scriptId: scriptId}});
  printFailure(msg);
  printBreakableLocations(msg, scriptId, module_bytes);
}

async function getBreakableLocationsForAllWasmScripts() {
  InspectorTest.log('Querying breakable locations for all wasm scripts now...');
  for (var wasmScriptNr = 0; wasmScriptNr < wasmScripts.length;
       ++wasmScriptNr) {
    await checkGetBreakableLocations(wasmScriptNr);
  }
}

function locationMatches(loc1, loc2) {
  return loc1.scriptId == loc2.scriptId && loc1.lineNumber == loc2.lineNumber &&
      loc1.columnNumber == loc2.columnNumber;
}

function locationStr(loc) {
  return urls[loc.scriptId] + ':' + loc.lineNumber + ':' + loc.columnNumber;
}

async function setBreakpoint(loc) {
  InspectorTest.log('Setting at ' + locationStr(loc));

  var msg = await Protocol.Debugger.setBreakpoint({ 'location': loc });
  printFailure(msg);

  if (locationMatches(loc, msg.result.actualLocation)) {
    InspectorTest.log("Success!");
  } else {
    InspectorTest.log("Mismatch!");
    InspectorTest.logMessage(msg);
  }
}

async function setAllBreakableLocations() {
  InspectorTest.log('Setting a breakpoint on each breakable location...');
  for (var loc of allBreakableLocations) {
    await setBreakpoint(loc);
  }
}

function recordPausedLocation(msg) {
  var topLocation = msg.params.callFrames[0].location;
  InspectorTest.log('Stopped at ' + locationStr(topLocation));
  for (var i = 0; i < allBreakableLocations.length; ++i) {
    if (locationMatches(topLocation, allBreakableLocations[i])) {
      allBreakableLocations.splice(i, 1);
      break;
    }
  }
}

async function waitForAllPauses() {
  var remaining = allBreakableLocations.length;
  InspectorTest.log('Missing breakpoints: ' + remaining);
  while (remaining > 0) {
    recordPausedLocation(await Protocol.Debugger.oncePaused());
    await Protocol.Debugger.resume();
    remaining--;
    InspectorTest.log('Missing breakpoints: ' + remaining);
  }
  if (allBreakableLocations.length != 0) {
    InspectorTest.log('Did not hit all breakable locations: '
                      + JSON.stringify(allBreakableLocations));
  }
}
