// 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\._.*$"),
];

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);
}
