cache_test.dart 6.92 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
// 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 'package:file/file.dart';
import 'package:file/memory.dart';
import 'package:mockito/mockito.dart';
import 'package:platform/platform.dart';

import 'package:flutter_tools/src/cache.dart';
13
import 'package:flutter_tools/src/base/io.dart' show InternetAddress, SocketException;
14

15
import 'src/common.dart';
16
import 'src/context.dart';
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42

void main() {
  group('$Cache.checkLockAcquired', () {
    setUp(() {
      Cache.enableLocking();
    });

    tearDown(() {
      // Restore locking to prevent potential side-effects in
      // tests outside this group (this option is globally shared).
      Cache.enableLocking();
    });

    test('should throw when locking is not acquired', () {
      expect(() => Cache.checkLockAcquired(), throwsStateError);
    });

    test('should not throw when locking is disabled', () {
      Cache.disableLocking();
      Cache.checkLockAcquired();
    });

    testUsingContext('should not throw when lock is acquired', () async {
      await Cache.lock();
      Cache.checkLockAcquired();
    }, overrides: <Type, Generator>{
43
      FileSystem: () => MockFileSystem(),
44 45 46 47 48
    });

    testUsingContext('should not throw when FLUTTER_ALREADY_LOCKED is set', () async {
      Cache.checkLockAcquired();
    }, overrides: <Type, Generator>{
49
      Platform: () => FakePlatform()..environment = <String, String>{'FLUTTER_ALREADY_LOCKED': 'true'},
50 51
    });
  });
52

53
  group('Cache', () {
54 55 56 57 58 59 60 61 62
    final MockCache mockCache = MockCache();
    final MemoryFileSystem fs = MemoryFileSystem();

    testUsingContext('Gradle wrapper should not be up to date, if some cached artifact is not available', () {
      final GradleWrapper gradleWrapper = GradleWrapper(mockCache);
      final Directory directory = fs.directory('/Applications/flutter/bin/cache');
      directory.createSync(recursive: true);
      fs.file(fs.path.join(directory.path, 'artifacts', 'gradle_wrapper', 'gradle', 'wrapper', 'gradle-wrapper.jar')).createSync(recursive: true);
      when(mockCache.getCacheDir(fs.path.join('artifacts', 'gradle_wrapper'))).thenReturn(fs.directory(fs.path.join(directory.path, 'artifacts', 'gradle_wrapper')));
63
      expect(gradleWrapper.isUpToDateInner(), false);
64 65
    }, overrides: <Type, Generator>{
      Cache: ()=> mockCache,
66
      FileSystem: () => fs,
67 68 69 70 71 72 73 74 75 76 77
    });

    testUsingContext('Gradle wrapper should be up to date, only if all cached artifact are available', () {
      final GradleWrapper gradleWrapper = GradleWrapper(mockCache);
      final Directory directory = fs.directory('/Applications/flutter/bin/cache');
      directory.createSync(recursive: true);
      fs.file(fs.path.join(directory.path, 'artifacts', 'gradle_wrapper', 'gradle', 'wrapper', 'gradle-wrapper.jar')).createSync(recursive: true);
      fs.file(fs.path.join(directory.path, 'artifacts', 'gradle_wrapper', 'gradlew')).createSync(recursive: true);
      fs.file(fs.path.join(directory.path, 'artifacts', 'gradle_wrapper', 'gradlew.bat')).createSync(recursive: true);

      when(mockCache.getCacheDir(fs.path.join('artifacts', 'gradle_wrapper'))).thenReturn(fs.directory(fs.path.join(directory.path, 'artifacts', 'gradle_wrapper')));
78
      expect(gradleWrapper.isUpToDateInner(), true);
79 80
    }, overrides: <Type, Generator>{
      Cache: ()=> mockCache,
81
      FileSystem: () => fs,
82 83
    });

84
    test('should not be up to date, if some cached artifact is not', () {
85 86
      final CachedArtifact artifact1 = MockCachedArtifact();
      final CachedArtifact artifact2 = MockCachedArtifact();
87 88
      when(artifact1.isUpToDate()).thenReturn(true);
      when(artifact2.isUpToDate()).thenReturn(false);
89
      final Cache cache = Cache(artifacts: <CachedArtifact>[artifact1, artifact2]);
90
      expect(cache.isUpToDate(), isFalse);
91 92
    });
    test('should be up to date, if all cached artifacts are', () {
93 94
      final CachedArtifact artifact1 = MockCachedArtifact();
      final CachedArtifact artifact2 = MockCachedArtifact();
95 96
      when(artifact1.isUpToDate()).thenReturn(true);
      when(artifact2.isUpToDate()).thenReturn(true);
97
      final Cache cache = Cache(artifacts: <CachedArtifact>[artifact1, artifact2]);
98
      expect(cache.isUpToDate(), isTrue);
99 100
    });
    test('should update cached artifacts which are not up to date', () async {
101 102
      final CachedArtifact artifact1 = MockCachedArtifact();
      final CachedArtifact artifact2 = MockCachedArtifact();
103 104
      when(artifact1.isUpToDate()).thenReturn(true);
      when(artifact2.isUpToDate()).thenReturn(false);
105
      final Cache cache = Cache(artifacts: <CachedArtifact>[artifact1, artifact2]);
106 107 108
      await cache.updateAll(<DevelopmentArtifact>{});
      verifyNever(artifact1.update(<DevelopmentArtifact>{}));
      verify(artifact2.update(<DevelopmentArtifact>{}));
109
    });
110
    testUsingContext('failed storage.googleapis.com download shows China warning', () async {
111 112
      final CachedArtifact artifact1 = MockCachedArtifact();
      final CachedArtifact artifact2 = MockCachedArtifact();
113 114
      when(artifact1.isUpToDate()).thenReturn(false);
      when(artifact2.isUpToDate()).thenReturn(false);
115
      final MockInternetAddress address = MockInternetAddress();
116
      when(address.host).thenReturn('storage.googleapis.com');
117
      when(artifact1.update(<DevelopmentArtifact>{})).thenThrow(SocketException(
118 119 120
        'Connection reset by peer',
        address: address,
      ));
121
      final Cache cache = Cache(artifacts: <CachedArtifact>[artifact1, artifact2]);
122
      try {
123
        await cache.updateAll(<DevelopmentArtifact>{});
124 125
        fail('Mock thrown exception expected');
      } catch (e) {
126
        verify(artifact1.update(<DevelopmentArtifact>{}));
127
        // Don't continue when retrieval fails.
128
        verifyNever(artifact2.update(<DevelopmentArtifact>{}));
129 130
        expect(
          testLogger.errorText,
131
          contains('https://flutter.dev/community/china'),
132 133 134
        );
      }
    });
135
  });
136 137

  testUsingContext('flattenNameSubdirs', () {
138
    expect(flattenNameSubdirs(Uri.parse('http://flutter.dev/foo/bar')), 'flutter.dev/foo/bar');
139
    expect(flattenNameSubdirs(Uri.parse('http://docs.flutter.io/foo/bar')), 'docs.flutter.io/foo/bar');
140
    expect(flattenNameSubdirs(Uri.parse('https://www.flutter.dev')), 'www.flutter.dev');
141
  }, overrides: <Type, Generator>{
142
    FileSystem: () => MockFileSystem(),
143
  });
144 145
}

146 147
class MockFileSystem extends ForwardingFileSystem {
  MockFileSystem() : super(MemoryFileSystem());
148

149 150
  @override
  File file(dynamic path) {
151
    return MockFile();
152 153 154 155 156
  }
}

class MockFile extends Mock implements File {
  @override
157
  Future<RandomAccessFile> open({ FileMode mode = FileMode.read }) async {
158
    return MockRandomAccessFile();
159 160 161 162
  }
}

class MockRandomAccessFile extends Mock implements RandomAccessFile {}
163
class MockCachedArtifact extends Mock implements CachedArtifact {}
164
class MockInternetAddress extends Mock implements InternetAddress {}
165
class MockCache extends Mock implements Cache {}