// Copyright (c) 2014, 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.

// This test reflectively enumerates all the methods in the system and tries to
// invoke them with various basic values (nulls, ints, etc). This may result in
// Dart exceptions or hangs, but should never result in crashes or JavaScript
// exceptions.

library test.invoke_natives;

import 'dart:mirrors';
import 'dart:async';
import 'dart:io';

// Methods to be skipped, by qualified name.
var denylist = [
  // Don't recurse on this test.
  'test.invoke_natives',

  // Don't exit the test pre-maturely.
  'dart.io.exit',
  'dart.isolate.Isolate.exit',

  // Don't change the exit code, which may fool the test harness.
  'dart.io.exitCode',

  // Don't kill random other processes.
  'dart.io.Process.killPid',

  // Don't break into the debugger.
  'dart.developer.debugger',

  // Don't run blocking io calls.
  'dart.io.sleep',
  new RegExp(r".*Sync$"),

  // Don't call private methods in dart.async as they may circumvent the zoned
  // error handling below.
  new RegExp(r"^dart\.async\._.*$"),

  // Don't try to invoke FFI Natives on simulator.
  // TODO(http://dartbug.com/48365): Support FFI in simulators.
  'dart._internal.FinalizerEntry.setExternalSize',
];

bool isDenylisted(Symbol qualifiedSymbol) {
  var qualifiedString = MirrorSystem.getName(qualifiedSymbol);
  for (var pattern in denylist) {
    if (qualifiedString.contains(pattern)) {
      print('Skipping $qualifiedString');
      return true;
    }
  }
  return false;
}

class Task {
  dynamic name;
  dynamic action;
}

var queue = <Task>[];

checkMethod(MethodMirror m, ObjectMirror target, [origin]) {
  if (isDenylisted(m.qualifiedName)) return;

  var task = new Task();
  task.name = '${MirrorSystem.getName(m.qualifiedName)} from $origin';

  if (m.isRegularMethod) {
    task.action = () => target.invoke(
        m.simpleName, new List.filled(m.parameters.length, fuzzArgument));
  } else if (m.isGetter) {
    task.action = () => target.getField(m.simpleName);
  } else if (m.isSetter) {
    task.action = () => target.setField(m.simpleName, null);
  } else if (m.isConstructor) {
    return;
  } else {
    throw "Unexpected method kind";
  }

  queue.add(task);
}

checkInstance(instanceMirror, origin) {
  ClassMirror? klass = instanceMirror.type;
  while (klass != null) {
    instanceMirror.type.declarations.values
        .where((d) => d is MethodMirror && !d.isStatic)
        .forEach((m) => checkMethod(m, instanceMirror, origin));
    klass = klass.superclass;
  }
}

checkClass(classMirror) {
  classMirror.declarations.values
      .where((d) => d is MethodMirror && d.isStatic)
      .forEach((m) => checkMethod(m, classMirror));

  classMirror.declarations.values
      .where((d) => d is MethodMirror && d.isConstructor)
      .forEach((m) {
    if (isDenylisted(m.qualifiedName)) return;
    var task = new Task();
    task.name = MirrorSystem.getName(m.qualifiedName);

    task.action = () {
      var instance = classMirror.newInstance(m.constructorName,
          new List.filled(m.parameters.length, fuzzArgument));
      checkInstance(instance, task.name);
    };
    queue.add(task);
  });
}

checkLibrary(libraryMirror) {
  print(libraryMirror.simpleName);
  if (isDenylisted(libraryMirror.qualifiedName)) return;

  libraryMirror.declarations.values
      .where((d) => d is ClassMirror)
      .forEach(checkClass);

  libraryMirror.declarations.values
      .where((d) => d is MethodMirror)
      .forEach((m) => checkMethod(m, libraryMirror));
}

var testZone;

doOneTask() {
  if (queue.length == 0) {
    print('Done');
    // Forcibly exit as we likely opened sockets and timers during the fuzzing.
    exit(0);
  }

  var task = queue.removeLast();
  print(task.name);
  try {
    task.action();
  } catch (e) {}

  // Register the next task in a timer callback so as to yield to async code
  // scheduled in the current task. This isn't necessary for the test itself,
  // but is helpful when trying to figure out which function is responsible for
  // a crash.
  testZone.createTimer(Duration.zero, doOneTask);
}

var fuzzArgument;

main() {
  fuzzArgument = null;
  fuzzArgument = 1; // //# smi: ok
  fuzzArgument = false; // //# false: ok
  fuzzArgument = 'string'; // //# string: ok
  fuzzArgument = new List<dynamic>.filled(0, null); // //# emptyarray: ok

  print('Fuzzing with $fuzzArgument');

  currentMirrorSystem().libraries.values.forEach(checkLibrary);

  var valueObjects = [
    true,
    false,
    null,
    [],
    {},
    dynamic,
    0,
    0xEFFFFFF,
    0xFFFFFFFF,
    0xFFFFFFFFFFFFFFFF,
    3.14159,
    "foo",
    'blåbærgrød',
    'Îñţérñåţîöñåļîžåţîờñ',
    "\u{1D11E}",
    #symbol
  ];
  valueObjects.forEach((v) => checkInstance(reflect(v), 'value object'));

  void uncaughtErrorHandler(self, parent, zone, error, stack) {}

  var zoneSpec =
      new ZoneSpecification(handleUncaughtError: uncaughtErrorHandler);
  testZone = Zone.current.fork(specification: zoneSpec);
  testZone.createTimer(Duration.zero, doOneTask);
}
