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

import 'package:analyzer/exception/exception.dart';
import 'package:analyzer/src/task/api/model.dart';
import 'package:analyzer/src/task/manager.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import '../../generated/test_support.dart';

main() {
  defineReflectiveSuite(() {
    defineReflectiveTests(TaskManagerTest);
  });
}

@reflectiveTest
class TaskManagerTest extends EngineTestCase {
  static final ResultDescriptor result1 = new ResultDescriptor('result1', null);
  static final ResultDescriptor result2 = new ResultDescriptor('result2', null);

  test_addGeneralResult() {
    TaskManager manager = new TaskManager();
    manager.addGeneralResult(result1);
    Set<ResultDescriptor> results = manager.generalResults;
    expect(results, unorderedEquals([result1]));
  }

  test_addPriorityResult() {
    TaskManager manager = new TaskManager();
    manager.addPriorityResult(result1);
    Set<ResultDescriptor> results = manager.priorityResults;
    expect(results, unorderedEquals([result1]));
  }

  test_addTaskDescriptor() {
    TaskManager manager = new TaskManager();
    TaskDescriptor descriptor =
        new TaskDescriptor('task', null, null, [result1]);
    manager.addTaskDescriptor(descriptor);
    expect(manager.taskMap.length, 1);
  }

  test_constructor() {
    TaskManager manager = new TaskManager();
    expect(manager, isNotNull);
    expect(manager.generalResults, isEmpty);
    expect(manager.priorityResults, isEmpty);
  }

  test_findTask_defined() {
    TaskManager manager = new TaskManager();
    TaskDescriptor descriptor =
        new TaskDescriptor('task', null, null, [result1]);
    manager.addTaskDescriptor(descriptor);
    AnalysisTarget target = new TestSource();
    expect(manager.findTask(target, result1), descriptor);
  }

  test_findTask_empty() {
    TaskManager manager = new TaskManager();
    AnalysisTarget target = new TestSource();
    expect(() => manager.findTask(target, result1),
        throwsA(new TypeMatcher<AnalysisException>()));
  }

  test_findTask_multiple() {
    TaskManager manager = new TaskManager();
    TaskDescriptor descriptor1 =
        new TaskDescriptor('task1', null, null, [result1]);
    manager.addTaskDescriptor(descriptor1);
    TaskDescriptor descriptor2 =
        new TaskDescriptor('task2', null, null, [result1]);
    manager.addTaskDescriptor(descriptor2);
    TaskDescriptor descriptor3 =
        new TaskDescriptor('task3', null, null, [result2]);
    manager.addTaskDescriptor(descriptor3);

    AnalysisTarget target = new TestSource();
    TaskDescriptor task = manager.findTask(target, result1);
    expect(task == descriptor1 || task == descriptor2, true);
  }

  test_findTask_undefined() {
    TaskManager manager = new TaskManager();
    TaskDescriptor descriptor =
        new TaskDescriptor('task', null, null, [result1]);
    manager.addTaskDescriptor(descriptor);
    AnalysisTarget target = new TestSource();
    expect(() => manager.findTask(target, result2),
        throwsA(new TypeMatcher<AnalysisException>()));
  }

  test_removeGeneralResult_absent() {
    TaskManager manager = new TaskManager();
    manager.addGeneralResult(result1);
    Set<ResultDescriptor> results = manager.generalResults;
    expect(results, unorderedEquals([result1]));
  }

  test_removeGeneralResult_present() {
    TaskManager manager = new TaskManager();
    manager.addGeneralResult(result1);
    manager.addGeneralResult(result2);
    Set<ResultDescriptor> results = manager.generalResults;
    expect(results, unorderedEquals([result1, result2]));
    manager.removeGeneralResult(result1);
    expect(results, unorderedEquals([result2]));
  }

  test_removePriorityResult_absent() {
    TaskManager manager = new TaskManager();
    manager.addPriorityResult(result1);
    manager.removePriorityResult(result2);
    Set<ResultDescriptor> results = manager.priorityResults;
    expect(results, unorderedEquals([result1]));
  }

  test_removePriorityResult_present() {
    TaskManager manager = new TaskManager();
    manager.addPriorityResult(result1);
    manager.addPriorityResult(result2);
    Set<ResultDescriptor> results = manager.priorityResults;
    expect(results, unorderedEquals([result1, result2]));
    manager.removePriorityResult(result1);
    expect(results, unorderedEquals([result2]));
  }
}
