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

library test.instrumentation;

import 'dart:async';

import 'package:analyzer/instrumentation/instrumentation.dart';
import 'package:unittest/unittest.dart';

import '../reflective_tests.dart';

main() {
  group('instrumentation', () {
    runReflectiveTests(InstrumentationServiceTest);
    runReflectiveTests(MulticastInstrumentationServerTest);
  });
}

@reflectiveTest
class InstrumentationServiceTest {
  void assertNormal(
      TestInstrumentationServer server, String tag, String message) {
    String sent = server.normalChannel.toString();
    if (!sent.endsWith(':$tag:$message\n')) {
      fail('Expected "...:$tag:$message", found "$sent"');
    }
  }

  void test_logError_withColon() {
    TestInstrumentationServer server = new TestInstrumentationServer();
    InstrumentationService service = new InstrumentationService(server);
    service.logError('Error:message');
    assertNormal(server, InstrumentationService.TAG_ERROR, 'Error::message');
  }

  void test_logError_withLeadingColon() {
    TestInstrumentationServer server = new TestInstrumentationServer();
    InstrumentationService service = new InstrumentationService(server);
    service.logError(':a:bb');
    assertNormal(server, InstrumentationService.TAG_ERROR, '::a::bb');
  }

  void test_logError_withoutColon() {
    TestInstrumentationServer server = new TestInstrumentationServer();
    InstrumentationService service = new InstrumentationService(server);
    String message = 'Error message';
    service.logError(message);
    assertNormal(server, InstrumentationService.TAG_ERROR, message);
  }

  void test_logException_noTrace() {
    TestInstrumentationServer server = new TestInstrumentationServer();
    InstrumentationService service = new InstrumentationService(server);
    String message = 'exceptionMessage';
    service.logException(message, null);
    assertNormal(server, InstrumentationService.TAG_EXCEPTION, '$message:null');
  }

  void test_logFileRead() {
    TestInstrumentationServer server = new TestInstrumentationServer();
    InstrumentationService service = new InstrumentationService(server);
    String path = '/file/path';
    int time = 978336000000;
    String content = 'class C {\n}\n';
    service.logFileRead(path, time, content);
    assertNormal(
        server, InstrumentationService.TAG_FILE_READ, '$path:$time:$content');
  }

  void test_logLogEntry() {
    TestInstrumentationServer server = new TestInstrumentationServer();
    InstrumentationService service = new InstrumentationService(server);
    String level = 'level';
    DateTime time = new DateTime(2001);
    String message = 'message';
    String exception = 'exception';
    String stackTraceText = 'stackTrace';
    StackTrace stackTrace = new StackTrace.fromString(stackTraceText);
    service.logLogEntry(level, time, message, exception, stackTrace);
    assertNormal(server, InstrumentationService.TAG_LOG_ENTRY,
        '$level:${time.millisecondsSinceEpoch}:$message:$exception:$stackTraceText');
  }

  void test_logNotification() {
    TestInstrumentationServer server = new TestInstrumentationServer();
    InstrumentationService service = new InstrumentationService(server);
    String message = 'notificationText';
    service.logNotification(message);
    assertNormal(server, InstrumentationService.TAG_NOTIFICATION, message);
  }

  void test_logRequest() {
    TestInstrumentationServer server = new TestInstrumentationServer();
    InstrumentationService service = new InstrumentationService(server);
    String message = 'requestText';
    service.logRequest(message);
    assertNormal(server, InstrumentationService.TAG_REQUEST, message);
  }

  void test_logResponse() {
    TestInstrumentationServer server = new TestInstrumentationServer();
    InstrumentationService service = new InstrumentationService(server);
    String message = 'responseText';
    service.logResponse(message);
    assertNormal(server, InstrumentationService.TAG_RESPONSE, message);
  }

  void test_logVersion() {
    TestInstrumentationServer server = new TestInstrumentationServer();
    InstrumentationService service = new InstrumentationService(server);
    service.logVersion('myUuid', 'someClientId', 'someClientVersion',
        'aServerVersion', 'anSdkVersion');
    expect(server.normalChannel.toString(), '');
    expect(
        server.priorityChannel.toString(),
        endsWith(
            ':myUuid:someClientId:someClientVersion:aServerVersion:anSdkVersion\n'));
  }
}

@reflectiveTest
class MulticastInstrumentationServerTest {
  TestInstrumentationServer serverA = new TestInstrumentationServer();
  TestInstrumentationServer serverB = new TestInstrumentationServer();
  MulticastInstrumentationServer server;

  void setUp() {
    server = new MulticastInstrumentationServer([serverA, serverB]);
  }

  void test_log() {
    server.log('foo bar');
    _assertNormal(serverA, 'foo bar');
    _assertNormal(serverB, 'foo bar');
  }

  void test_logWithPriority() {
    server.logWithPriority('foo bar');
    _assertPriority(serverA, 'foo bar');
    _assertPriority(serverB, 'foo bar');
  }

  void test_shutdown() {
    server.shutdown();
  }

  void _assertNormal(TestInstrumentationServer server, String message) {
    String sent = server.normalChannel.toString();
    if (!sent.endsWith('$message\n')) {
      fail('Expected "...$message", found "$sent"');
    }
  }

  void _assertPriority(TestInstrumentationServer server, String message) {
    String sent = server.priorityChannel.toString();
    if (!sent.endsWith('$message\n')) {
      fail('Expected "...$message", found "$sent"');
    }
  }
}

class TestInstrumentationServer implements InstrumentationServer {
  StringBuffer normalChannel = new StringBuffer();
  StringBuffer priorityChannel = new StringBuffer();

  @override
  void log(String message) {
    normalChannel.writeln(message);
  }

  @override
  void logWithPriority(String message) {
    priorityChannel.writeln(message);
  }

  @override
  Future shutdown() async {
    // Ignored
  }
}
