<commit_before>// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'dart:isolate';

import 'package:logging/logging.dart';
import 'package:stack_trace/stack_trace.dart';

import 'running_processes.dart';
import 'utils.dart';

/// Maximum amount of time a single task is allowed to take to run.
///
/// If exceeded the task is considered to have failed.
const Duration _kDefaultTaskTimeout = Duration(minutes: 15);

/// Represents a unit of work performed in the CI environment that can
/// succeed, fail and be retried independently of others.
typedef TaskFunction = Future<TaskResult> Function();

bool _isTaskRegistered = false;

/// Registers a [task] to run, returns the result when it is complete.
///
/// The task does not run immediately but waits for the request via the
/// VM service protocol to run it.
///
/// It is ok for a [task] to perform many things. However, only one task can be
/// registered per Dart VM.
Future<TaskResult> task(TaskFunction task) {
  if (_isTaskRegistered)
    throw StateError('A task is already registered');

  _isTaskRegistered = true;

  // TODO(ianh): allow overriding logging.
  Logger.root.level = Level.ALL;
  Logger.root.onRecord.listen((LogRecord rec) {
    print('${rec.level.name}: ${rec.time}: ${rec.message}');
  });

  final _TaskRunner runner = _TaskRunner(task);
  runner.keepVmAliveUntilTaskRunRequested();
  return runner.whenDone;
}

class _TaskRunner {
  _TaskRunner(this.task) {
    registerExtension('ext.cocoonRunTask',
        (String method, Map<String, String> parameters) async {
      final Duration taskTimeout = parameters.containsKey('timeoutInMinutes')
        ? Duration(minutes: int.parse(parameters['timeoutInMinutes']))
        : _kDefaultTaskTimeout;
      final TaskResult result = await run(taskTimeout);
      return ServiceExtensionResponse.result(json.encode(result.toJson()));
    });
    registerExtension('ext.cocoonRunnerReady',
        (String method, Map<String, String> parameters) async {
      return ServiceExtensionResponse.result('"ready"');
    });
  }

  final TaskFunction task;

  // TODO(ianh): workaround for https://github.com/dart-lang/sdk/issues/23797
  RawReceivePort _keepAlivePort;
  Timer _startTaskTimeout;
  bool _taskStarted = false;

  final Completer<TaskResult> _completer = Completer<TaskResult>();

  static final Logger logger = Logger('TaskRunner');

  /// Signals that this task runner finished running the task.
  Future<TaskResult> get whenDone => _completer.future;

  Future<TaskResult> run(Duration taskTimeout) async {
    try {
      _taskStarted = true;
      print('Running task.');
      final String exe = Platform.isWindows ? '.exe' : '';
      section('Checking running Dart$exe processes');
      final Set<RunningProcessInfo> beforeRunningDartInstances = await getRunningProcesses(
        processName: 'dart$exe',
      ).toSet();
      beforeRunningDartInstances.forEach(print);

      TaskResult result = await _performTask().timeout(taskTimeout);

      section('Checking running Dart$exe processes after task...');
      final List<RunningProcessInfo> afterRunningDartInstances = await getRunningProcesses(
        processName: 'dart$exe',
      ).toList();
      for (final RunningProcessInfo info in afterRunningDartInstances) {
        if (!beforeRunningDartInstances.contains(info)) {
          print('$info was leaked by this test.');
          // TODO(dnfield): remove this special casing after https://github.com/flutter/flutter/issues/29141 is resolved.
          if (result is TaskResultCheckProcesses) {
            result = TaskResult.failure('This test leaked dart processes');
          } else {
            result = TaskResult.success(null);
          }
          final bool killed = await killProcess(info.pid);
          if (!killed) {
            print('Failed to kill process ${info.pid}.');
          } else {
            print('Killed process id ${info.pid}.');
          }<commit_msg>Avoid overwriting task result for non-leak checkers (#29989)<commit_after>// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'dart:isolate';

import 'package:logging/logging.dart';
import 'package:stack_trace/stack_trace.dart';

import 'running_processes.dart';
import 'utils.dart';

/// Maximum amount of time a single task is allowed to take to run.
///
/// If exceeded the task is considered to have failed.
const Duration _kDefaultTaskTimeout = Duration(minutes: 15);

/// Represents a unit of work performed in the CI environment that can
/// succeed, fail and be retried independently of others.
typedef TaskFunction = Future<TaskResult> Function();

bool _isTaskRegistered = false;

/// Registers a [task] to run, returns the result when it is complete.
///
/// The task does not run immediately but waits for the request via the
/// VM service protocol to run it.
///
/// It is ok for a [task] to perform many things. However, only one task can be
/// registered per Dart VM.
Future<TaskResult> task(TaskFunction task) {
  if (_isTaskRegistered)
    throw StateError('A task is already registered');

  _isTaskRegistered = true;

  // TODO(ianh): allow overriding logging.
  Logger.root.level = Level.ALL;
  Logger.root.onRecord.listen((LogRecord rec) {
    print('${rec.level.name}: ${rec.time}: ${rec.message}');
  });

  final _TaskRunner runner = _TaskRunner(task);
  runner.keepVmAliveUntilTaskRunRequested();
  return runner.whenDone;
}

class _TaskRunner {
  _TaskRunner(this.task) {
    registerExtension('ext.cocoonRunTask',
        (String method, Map<String, String> parameters) async {
      final Duration taskTimeout = parameters.containsKey('timeoutInMinutes')
        ? Duration(minutes: int.parse(parameters['timeoutInMinutes']))
        : _kDefaultTaskTimeout;
      final TaskResult result = await run(taskTimeout);
      return ServiceExtensionResponse.result(json.encode(result.toJson()));
    });
    registerExtension('ext.cocoonRunnerReady',
        (String method, Map<String, String> parameters) async {
      return ServiceExtensionResponse.result('"ready"');
    });
  }

  final TaskFunction task;

  // TODO(ianh): workaround for https://github.com/dart-lang/sdk/issues/23797
  RawReceivePort _keepAlivePort;
  Timer _startTaskTimeout;
  bool _taskStarted = false;

  final Completer<TaskResult> _completer = Completer<TaskResult>();

  static final Logger logger = Logger('TaskRunner');

  /// Signals that this task runner finished running the task.
  Future<TaskResult> get whenDone => _completer.future;

  Future<TaskResult> run(Duration taskTimeout) async {
    try {
      _taskStarted = true;
      print('Running task.');
      final String exe = Platform.isWindows ? '.exe' : '';
      section('Checking running Dart$exe processes');
      final Set<RunningProcessInfo> beforeRunningDartInstances = await getRunningProcesses(
        processName: 'dart$exe',
      ).toSet();
      beforeRunningDartInstances.forEach(print);

      TaskResult result = await _performTask().timeout(taskTimeout);

      section('Checking running Dart$exe processes after task...');
      final List<RunningProcessInfo> afterRunningDartInstances = await getRunningProcesses(
        processName: 'dart$exe',
      ).toList();
      for (final RunningProcessInfo info in afterRunningDartInstances) {
        if (!beforeRunningDartInstances.contains(info)) {
          print('$info was leaked by this test.');
          // TODO(dnfield): remove this special casing after https://github.com/flutter/flutter/issues/29141 is resolved.
          if (result is TaskResultCheckProcesses) {
            result = TaskResult.failure('This test leaked dart processes');
          }
          final bool killed = await killProcess(info.pid);
          if (!killed) {
            print('Failed to kill process ${info.pid}.');
          } else {
            print('Killed process id ${info.pid}.');
          }
{'fraction_non_alphanumeric': 0.11092335546167773, 'fraction_numerical': 0.004465902232951117, 'mean_word_length': 3.5527472527472526, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 25, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3094817', 'n_tokens_mistral': 2375, 'n_tokens_neox': 2260, 'n_words': 702}