filecache_test.dart 5.74 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6
import 'dart:typed_data';

7
import 'package:file/memory.dart';
8
import 'package:flutter_tools/src/base/file_system.dart';
9 10
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/terminal.dart';
11 12
import 'package:flutter_tools/src/build_system/build_system.dart';
import 'package:flutter_tools/src/build_system/file_hash_store.dart';
13
import 'package:mockito/mockito.dart';
14
import 'package:platform/platform.dart';
15 16 17 18 19

import '../../src/common.dart';

void main() {
  Environment environment;
20 21
  FileSystem fileSystem;
  BufferLogger logger;
22 23

  setUp(() {
24 25 26 27 28 29 30 31 32 33
    fileSystem = MemoryFileSystem();
    logger = BufferLogger(
      outputPreferences: OutputPreferences.test(),
      terminal: AnsiTerminal(stdio: null, platform: FakePlatform())
    );
    fileSystem.directory('build').createSync();
    environment = Environment.test(
      fileSystem.currentDirectory,
    );
    environment.buildDir.createSync(recursive: true);
34 35
  });

36 37 38 39 40 41
  test('Initializes file cache', () {
    final FileHashStore fileCache = FileHashStore(
      environment: environment,
      fileSystem: fileSystem,
      logger: logger,
    );
42 43 44
    fileCache.initialize();
    fileCache.persist();

45
    expect(fileSystem.file(fileSystem.path.join(environment.buildDir.path, '.filecache')).existsSync(), true);
46

47
    final Uint8List buffer = fileSystem.file(fileSystem.path.join(environment.buildDir.path, '.filecache'))
48
        .readAsBytesSync();
49
    final FileStorage fileStorage = FileStorage.fromBuffer(buffer);
50 51

    expect(fileStorage.files, isEmpty);
52
    expect(fileStorage.version, 2);
53
  });
54

55 56
  test('saves and restores to file cache', () async {
    final File file = fileSystem.file('foo.dart')
57 58
      ..createSync()
      ..writeAsStringSync('hello');
59 60 61 62 63
    final FileHashStore fileCache = FileHashStore(
      environment: environment,
      fileSystem: fileSystem,
      logger: logger,
    );
64
    fileCache.initialize();
65
    await fileCache.hashFiles(<File>[file]);
66
    fileCache.persist();
67
    final String currentHash =  fileCache.currentHashes[file.path];
68
    final Uint8List buffer = fileSystem.file(fileSystem.path.join(environment.buildDir.path, '.filecache'))
69
        .readAsBytesSync();
70
    FileStorage fileStorage = FileStorage.fromBuffer(buffer);
71 72

    expect(fileStorage.files.single.hash, currentHash);
73
    expect(fileStorage.files.single.path, file.path);
74 75


76 77 78 79 80
    final FileHashStore newFileCache = FileHashStore(
      environment: environment,
      fileSystem: fileSystem,
      logger: logger,
    );
81 82
    newFileCache.initialize();
    expect(newFileCache.currentHashes, isEmpty);
83
    expect(newFileCache.previousHashes['foo.dart'],  currentHash);
84 85 86
    newFileCache.persist();

    // Still persisted correctly.
87
    fileStorage = FileStorage.fromBuffer(buffer);
88 89

    expect(fileStorage.files.single.hash, currentHash);
90
    expect(fileStorage.files.single.path, file.path);
91
  });
92

93 94
  test('handles persisting with a missing build directory', () async {
    final File file = fileSystem.file('foo.dart')
95 96
      ..createSync()
      ..writeAsStringSync('hello');
97 98 99 100 101
    final FileHashStore fileCache = FileHashStore(
      environment: environment,
      fileSystem: fileSystem,
      logger: logger,
    );
102 103 104
    fileCache.initialize();
    environment.buildDir.deleteSync(recursive: true);

105
    await fileCache.hashFiles(<File>[file]);
106

107 108 109 110 111 112 113 114 115
    expect(() => fileCache.persist(), returnsNormally);
  });

  test('handles hashing missing files', () async {
    final FileHashStore fileCache = FileHashStore(
      environment: environment,
      fileSystem: fileSystem,
      logger: logger,
    );
116 117
    fileCache.initialize();

118
    final List<File> results = await fileCache.hashFiles(<File>[fileSystem.file('hello.dart')]);
119 120 121

    expect(results, hasLength(1));
    expect(results.single.path, 'hello.dart');
122 123
    expect(fileCache.currentHashes, isNot(contains(fileSystem.path.absolute('hello.dart'))));
  });
124

125 126 127 128 129 130 131
  test('handles failure to persist file cache', () async {
    final FakeForwardingFileSystem fakeForwardingFileSystem = FakeForwardingFileSystem(fileSystem);
    final FileHashStore fileCache = FileHashStore(
      environment: environment,
      fileSystem: fakeForwardingFileSystem,
      logger: logger,
    );
132 133 134 135 136 137 138 139 140
    final String cacheFile = environment.buildDir.childFile('.filecache').path;
    final MockFile mockFile = MockFile();
    when(mockFile.writeAsBytesSync(any)).thenThrow(const FileSystemException('Out of space!'));
    when(mockFile.existsSync()).thenReturn(true);

    fileCache.initialize();
    fakeForwardingFileSystem.files[cacheFile] = mockFile;
    fileCache.persist();

141 142
    expect(logger.errorText, contains('Out of space!'));
  });
143

144 145 146 147 148 149 150
  test('handles failure to restore file cache', () async {
    final FakeForwardingFileSystem fakeForwardingFileSystem = FakeForwardingFileSystem(fileSystem);
    final FileHashStore fileCache = FileHashStore(
      environment: environment,
      fileSystem: fakeForwardingFileSystem,
      logger: logger,
    );
151 152 153 154 155 156 157 158
    final String cacheFile = environment.buildDir.childFile('.filecache').path;
    final MockFile mockFile = MockFile();
    when(mockFile.readAsBytesSync()).thenThrow(const FileSystemException('Out of space!'));
    when(mockFile.existsSync()).thenReturn(true);

    fakeForwardingFileSystem.files[cacheFile] = mockFile;
    fileCache.initialize();

159 160
    expect(logger.errorText, contains('Out of space!'));
  });
161 162 163 164 165
}

class FakeForwardingFileSystem extends ForwardingFileSystem {
  FakeForwardingFileSystem(FileSystem fileSystem) : super(fileSystem);

166
  final Map<String, File> files = <String, File>{};
167 168 169

  @override
  File file(dynamic path) => files[path] ?? super.file(path);
170
}
171
class MockFile extends Mock implements File {}