symbolize_test.dart 5.65 KB
Newer Older
1 2 3 4
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
import 'dart:async';
6 7 8
import 'dart:typed_data';

import 'package:file/memory.dart';
9
import 'package:file_testing/file_testing.dart';
10
import 'package:flutter_tools/src/base/common.dart';
11
import 'package:flutter_tools/src/base/file_system.dart';
12
import 'package:flutter_tools/src/base/terminal.dart';
13 14 15
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/symbolize.dart';
import 'package:flutter_tools/src/convert.dart';
16
import 'package:test/fake.dart';
17 18 19

import '../../src/common.dart';
import '../../src/context.dart';
20
import '../../src/fakes.dart';
21
import '../../src/test_flutter_command_runner.dart';
22 23

void main() {
24 25
  late MemoryFileSystem fileSystem;
  late FakeStdio stdio;
26 27 28 29 30 31 32

  setUpAll(() {
    Cache.disableLocking();
  });

  setUp(() {
    fileSystem = MemoryFileSystem.test();
33
    stdio = FakeStdio();
34 35
  });

36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
  testUsingContext('Regression test for type error in codec', () async {
    final DwarfSymbolizationService symbolizationService = DwarfSymbolizationService.test();
    final StreamController<List<int>> output = StreamController<List<int>>();

    unawaited(symbolizationService.decode(
      input: Stream<Uint8List>.fromIterable(<Uint8List>[
        utf8.encode('Hello, World\n') as Uint8List,
      ]),
      symbols: Uint8List(0),
      output: IOSink(output.sink),
    ));

    await expectLater(
      output.stream.transform(utf8.decoder),
      emits('Hello, World'),
    );
  });

54 55

  testUsingContext('symbolize exits when --debug-info argument is missing', () async {
56 57 58 59 60
    final SymbolizeCommand command = SymbolizeCommand(
      stdio: stdio,
      fileSystem: fileSystem,
      dwarfSymbolizationService: DwarfSymbolizationService.test(),
    );
61 62 63
    final Future<void> result = createTestCommandRunner(command)
      .run(const <String>['symbolize']);

64
    expect(result, throwsToolExit(message: '"--debug-info" is required to symbolize stack traces.'));
65 66
  }, overrides: <Type, Generator>{
    OutputPreferences: () => OutputPreferences.test(),
67 68
  });

69
  testUsingContext('symbolize exits when --debug-info dwarf file is missing', () async {
70 71 72 73 74
    final SymbolizeCommand command = SymbolizeCommand(
      stdio: stdio,
      fileSystem: fileSystem,
      dwarfSymbolizationService: DwarfSymbolizationService.test(),
    );
75 76 77 78
    final Future<void> result = createTestCommandRunner(command)
      .run(const <String>['symbolize', '--debug-info=app.debug']);

    expect(result, throwsToolExit(message: 'app.debug does not exist.'));
79 80
  }, overrides: <Type, Generator>{
    OutputPreferences: () => OutputPreferences.test(),
81 82
  });

83 84 85 86 87 88 89 90 91 92 93 94 95 96
  testUsingContext('symbolize exits when --debug-info dSYM is missing', () async {
    final SymbolizeCommand command = SymbolizeCommand(
      stdio: stdio,
      fileSystem: fileSystem,
      dwarfSymbolizationService: DwarfSymbolizationService.test(),
    );
    final Future<void> result = createTestCommandRunner(command)
      .run(const <String>['symbolize', '--debug-info=app.dSYM']);

    expect(result, throwsToolExit(message: 'app.dSYM does not exist.'));
  }, overrides: <Type, Generator>{
    OutputPreferences: () => OutputPreferences.test(),
  });

97
  testUsingContext('symbolize exits when --input file is missing', () async {
98 99 100 101 102
    final SymbolizeCommand command = SymbolizeCommand(
      stdio: stdio,
      fileSystem: fileSystem,
      dwarfSymbolizationService: DwarfSymbolizationService.test(),
    );
103 104 105 106 107
    fileSystem.file('app.debug').createSync();
    final Future<void> result = createTestCommandRunner(command)
      .run(const <String>['symbolize', '--debug-info=app.debug', '--input=foo.stack', '--output=results/foo.result']);

    expect(result, throwsToolExit(message: ''));
108 109
  }, overrides: <Type, Generator>{
    OutputPreferences: () => OutputPreferences.test(),
110 111
  });

112
  testUsingContext('symbolize succeeds when DwarfSymbolizationService does not throw', () async {
113 114 115 116 117
    final SymbolizeCommand command = SymbolizeCommand(
      stdio: stdio,
      fileSystem: fileSystem,
      dwarfSymbolizationService: DwarfSymbolizationService.test(),
    );
118 119 120 121 122
    fileSystem.file('app.debug').writeAsBytesSync(<int>[1, 2, 3]);
    fileSystem.file('foo.stack').writeAsStringSync('hello');

    await createTestCommandRunner(command)
      .run(const <String>['symbolize', '--debug-info=app.debug', '--input=foo.stack', '--output=results/foo.result']);
123 124 125

    expect(fileSystem.file('results/foo.result'), exists);
    expect(fileSystem.file('results/foo.result').readAsBytesSync(), <int>[104, 101, 108, 108, 111, 10]); // hello
126 127
  }, overrides: <Type, Generator>{
    OutputPreferences: () => OutputPreferences.test(),
128 129 130
  });

  testUsingContext('symbolize throws when DwarfSymbolizationService throws', () async {
131
    final SymbolizeCommand command = SymbolizeCommand(
132 133 134 135 136
      stdio: stdio,
      fileSystem: fileSystem,
      dwarfSymbolizationService: ThrowingDwarfSymbolizationService(),
    );

137 138 139 140 141
    fileSystem.file('app.debug').writeAsBytesSync(<int>[1, 2, 3]);
    fileSystem.file('foo.stack').writeAsStringSync('hello');

    expect(
      createTestCommandRunner(command).run(const <String>[
142 143
        'symbolize', '--debug-info=app.debug', '--input=foo.stack', '--output=results/foo.result',
      ]),
144 145
      throwsToolExit(message: 'test'),
    );
146 147
  }, overrides: <Type, Generator>{
    OutputPreferences: () => OutputPreferences.test(),
148 149 150
  });
}

151 152 153
class ThrowingDwarfSymbolizationService extends Fake implements DwarfSymbolizationService {
  @override
  Future<void> decode({
154 155 156
    required Stream<List<int>> input,
    required IOSink output,
    required Uint8List symbols,
157 158 159 160
  }) async {
    throwToolExit('test');
  }
}