// Copyright (c) 2013, 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 'dart:convert';
@TestOn('vm')
import 'dart:io';

import 'package:path/path.dart' as p;
import 'package:test/test.dart';
import 'package:test_descriptor/test_descriptor.dart' as d;

import 'utils.dart';

void main() {
  group('create()', () {
    test('creates a text file', () async {
      await d.file('name.txt', 'contents').create();

      expect(File(p.join(d.sandbox, 'name.txt')).readAsString(),
          completion(equals('contents')));
    });

    test('creates a binary file', () async {
      await d.file('name.txt', [0, 1, 2, 3]).create();

      expect(File(p.join(d.sandbox, 'name.txt')).readAsBytes(),
          completion(equals([0, 1, 2, 3])));
    });

    test('fails to create a matcher file', () async {
      expect(
          d.file('name.txt', contains('foo')).create(), throwsUnsupportedError);
    });

    test('overwrites an existing file', () async {
      await d.file('name.txt', 'contents1').create();
      await d.file('name.txt', 'contents2').create();

      expect(File(p.join(d.sandbox, 'name.txt')).readAsString(),
          completion(equals('contents2')));
    });
  });

  group('validate()', () {
    test('succeeds if the filesystem matches a text descriptor', () async {
      await File(p.join(d.sandbox, 'name.txt')).writeAsString('contents');
      await d.file('name.txt', 'contents').validate();
    });

    test('succeeds if the filesystem matches a binary descriptor', () async {
      await File(p.join(d.sandbox, 'name.txt')).writeAsBytes([0, 1, 2, 3]);
      await d.file('name.txt', [0, 1, 2, 3]).validate();
    });

    test('succeeds if the filesystem matches a text matcher', () async {
      await File(p.join(d.sandbox, 'name.txt')).writeAsString('contents');
      await d.file('name.txt', contains('ent')).validate();
    });

    test('succeeds if the filesystem matches a binary matcher', () async {
      await File(p.join(d.sandbox, 'name.txt')).writeAsBytes([0, 1, 2, 3]);
      await d.FileDescriptor.binaryMatcher('name.txt', contains(2)).validate();
    });

    test('succeeds if invalid UTF-8 matches a text matcher', () async {
      await File(p.join(d.sandbox, 'name.txt')).writeAsBytes([0xC3, 0x28]);
      await d.file('name.txt', isNot(isEmpty)).validate();
    });

    test("fails if the text contents don't match", () async {
      await File(p.join(d.sandbox, 'name.txt')).writeAsString('wrong');

      expect(d.file('name.txt', 'contents').validate(),
          throwsA(toString(startsWith('File "name.txt" should contain:'))));
    });

    test("fails if the binary contents don't match", () async {
      await File(p.join(d.sandbox, 'name.txt')).writeAsBytes([5, 4, 3, 2]);

      expect(
          d.file('name.txt', [0, 1, 2, 3]).validate(),
          throwsA(toString(equals(
              'File "name.txt" didn\'t contain the expected binary data.'))));
    });

    test("fails if the text contents don't match the matcher", () async {
      await File(p.join(d.sandbox, 'name.txt')).writeAsString('wrong');

      expect(
          d.file('name.txt', contains('ent')).validate(),
          throwsA(
              toString(startsWith('Invalid contents for file "name.txt":'))));
    });

    test("fails if the binary contents don't match the matcher", () async {
      await File(p.join(d.sandbox, 'name.txt')).writeAsBytes([5, 4, 3, 2]);

      expect(
          d.FileDescriptor.binaryMatcher('name.txt', contains(1)).validate(),
          throwsA(
              toString(startsWith('Invalid contents for file "name.txt":'))));
    });

    test("fails if invalid UTF-8 doesn't match a text matcher", () async {
      await File(p.join(d.sandbox, 'name.txt')).writeAsBytes([0xC3, 0x28]);
      expect(
          d.file('name.txt', isEmpty).validate(),
          throwsA(toString(allOf([
            startsWith('Invalid contents for file "name.txt":'),
            contains('�')
          ]))));
    });

    test("fails if there's no file", () {
      expect(d.file('name.txt', 'contents').validate(),
          throwsA(toString(equals('File not found: "name.txt".'))));
    });
  });

  group('reading', () {
    test('read() returns the contents of a text file as a string', () {
      expect(d.file('name.txt', 'contents').read(),
          completion(equals('contents')));
    });

    test('read() returns the contents of a binary file as a string', () {
      expect(d.file('name.txt', [0x68, 0x65, 0x6c, 0x6c, 0x6f]).read(),
          completion(equals('hello')));
    });

    test('read() fails for a matcher file', () {
      expect(d.file('name.txt', contains('hi')).read, throwsUnsupportedError);
    });

    test('readAsBytes() returns the contents of a text file as a byte stream',
        () {
      expect(utf8.decodeStream(d.file('name.txt', 'contents').readAsBytes()),
          completion(equals('contents')));
    });

    test('readAsBytes() returns the contents of a binary file as a byte stream',
        () {
      expect(byteStreamToList(d.file('name.txt', [0, 1, 2, 3]).readAsBytes()),
          completion(equals([0, 1, 2, 3])));
    });

    test('readAsBytes() fails for a matcher file', () {
      expect(d.file('name.txt', contains('hi')).readAsBytes,
          throwsUnsupportedError);
    });
  });

  test('io refers to the file within the sandbox', () {
    expect(d.file('name.txt').io.path, equals(p.join(d.sandbox, 'name.txt')));
  });
}
