Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
6ecb8cbc
Unverified
Commit
6ecb8cbc
authored
Jan 29, 2021
by
Jenn Magder
Committed by
GitHub
Jan 29, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Replace MockUsage with TestUsage (#74946)
parent
0491db4a
Changes
18
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
509 additions
and
547 deletions
+509
-547
usage.dart
packages/flutter_tools/lib/src/reporting/usage.dart
+3
-2
config_test.dart
...utter_tools/test/commands.shard/hermetic/config_test.dart
+30
-83
doctor_test.dart
...utter_tools/test/commands.shard/hermetic/doctor_test.dart
+63
-74
run_test.dart
.../flutter_tools/test/commands.shard/hermetic/run_test.dart
+0
-1
build_aar_test.dart
...r_tools/test/commands.shard/permeable/build_aar_test.dart
+10
-11
build_apk_test.dart
...r_tools/test/commands.shard/permeable/build_apk_test.dart
+41
-34
build_appbundle_test.dart
...s/test/commands.shard/permeable/build_appbundle_test.dart
+28
-27
analytics_test.dart
...ages/flutter_tools/test/general.shard/analytics_test.dart
+16
-26
gradle_errors_test.dart
..._tools/test/general.shard/android/gradle_errors_test.dart
+51
-43
gradle_test.dart
...flutter_tools/test/general.shard/android/gradle_test.dart
+63
-61
error_handling_io_test.dart
...tools/test/general.shard/base/error_handling_io_test.dart
+5
-4
crash_reporting_test.dart
...lutter_tools/test/general.shard/crash_reporting_test.dart
+13
-18
pub_get_test.dart
...s/flutter_tools/test/general.shard/dart/pub_get_test.dart
+25
-22
ios_project_migration_test.dart
...ls/test/general.shard/ios/ios_project_migration_test.dart
+31
-22
mac_test.dart
packages/flutter_tools/test/general.shard/ios/mac_test.dart
+18
-16
macos_project_migration_test.dart
...est/general.shard/macos/macos_project_migration_test.dart
+17
-32
events_test.dart
...utter_tools/test/general.shard/reporting/events_test.dart
+31
-25
resident_runner_test.dart
...lutter_tools/test/general.shard/resident_runner_test.dart
+64
-46
No files found.
packages/flutter_tools/lib/src/reporting/usage.dart
View file @
6ecb8cbc
...
...
@@ -473,6 +473,7 @@ class TestUsage implements Usage {
final
List
<
TestUsageEvent
>
events
=
<
TestUsageEvent
>[];
final
List
<
dynamic
>
exceptions
=
<
dynamic
>[];
final
List
<
TestTimingEvent
>
timings
=
<
TestTimingEvent
>[];
int
ensureAnalyticsSentCalls
=
0
;
@override
bool
enabled
=
true
;
...
...
@@ -484,8 +485,8 @@ class TestUsage implements Usage {
String
get
clientId
=>
'test-client'
;
@override
Future
<
void
>
ensureAnalyticsSent
()
{
throw
UnimplementedError
()
;
Future
<
void
>
ensureAnalyticsSent
()
async
{
ensureAnalyticsSentCalls
++
;
}
@override
...
...
packages/flutter_tools/test/commands.shard/hermetic/config_test.dart
View file @
6ecb8cbc
...
...
@@ -25,7 +25,7 @@ void main() {
MockAndroidStudio
mockAndroidStudio
;
MockAndroidSdk
mockAndroidSdk
;
MockFlutterVersion
mockFlutterVersion
;
MockUsage
mock
Usage
;
TestUsage
test
Usage
;
setUpAll
(()
{
Cache
.
disableLocking
();
...
...
@@ -35,27 +35,13 @@ void main() {
mockAndroidStudio
=
MockAndroidStudio
();
mockAndroidSdk
=
MockAndroidSdk
();
mockFlutterVersion
=
MockFlutterVersion
();
mockUsage
=
Mock
Usage
();
testUsage
=
Test
Usage
();
});
void
verifyNoAnalytics
()
{
verifyNever
(
mockUsage
.
sendCommand
(
any
,
parameters:
anyNamed
(
'parameters'
),
));
verifyNever
(
mockUsage
.
sendEvent
(
any
,
any
,
label:
anyNamed
(
'label'
),
value:
anyNamed
(
'value'
),
parameters:
anyNamed
(
'parameters'
),
));
verifyNever
(
mockUsage
.
sendTiming
(
any
,
any
,
any
,
label:
anyNamed
(
'label'
),
));
expect
(
testUsage
.
commands
,
isEmpty
);
expect
(
testUsage
.
events
,
isEmpty
);
expect
(
testUsage
.
timings
,
isEmpty
);
}
group
(
'config'
,
()
{
...
...
@@ -76,7 +62,7 @@ void main() {
},
overrides:
<
Type
,
Generator
>{
AndroidStudio:
()
=>
mockAndroidStudio
,
AndroidSdk:
()
=>
mockAndroidSdk
,
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
testUsingContext
(
'Can set build-dir'
,
()
async
{
...
...
@@ -91,7 +77,7 @@ void main() {
expect
(
getBuildDirectory
(),
'foo'
);
verifyNoAnalytics
();
},
overrides:
<
Type
,
Generator
>{
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
testUsingContext
(
'throws error on absolute path to build-dir'
,
()
async
{
...
...
@@ -104,7 +90,7 @@ void main() {
]),
throwsToolExit
());
verifyNoAnalytics
();
},
overrides:
<
Type
,
Generator
>{
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
testUsingContext
(
'allows setting and removing feature flags'
,
()
async
{
...
...
@@ -149,7 +135,7 @@ void main() {
},
overrides:
<
Type
,
Generator
>{
AndroidStudio:
()
=>
mockAndroidStudio
,
AndroidSdk:
()
=>
mockAndroidSdk
,
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
testUsingContext
(
'warns the user to reload IDE'
,
()
async
{
...
...
@@ -166,7 +152,7 @@ void main() {
containsIgnoringWhitespace
(
'You may need to restart any open editors'
),
);
},
overrides:
<
Type
,
Generator
>{
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
testUsingContext
(
'displays which config settings are available on stable'
,
()
async
{
...
...
@@ -207,49 +193,33 @@ void main() {
AndroidStudio:
()
=>
mockAndroidStudio
,
AndroidSdk:
()
=>
mockAndroidSdk
,
FlutterVersion:
()
=>
mockFlutterVersion
,
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
testUsingContext
(
'no-analytics flag flips usage flag and sends event'
,
()
async
{
final
ConfigCommand
configCommand
=
ConfigCommand
();
final
CommandRunner
<
void
>
commandRunner
=
createTestCommandRunner
(
configCommand
);
when
(
mockUsage
.
sendEvent
(
captureAny
,
captureAny
,
label:
captureAnyNamed
(
'label'
),
value:
anyNamed
(
'value'
),
parameters:
anyNamed
(
'parameters'
),
)).
thenAnswer
((
Invocation
invocation
)
async
{
expect
(
mockUsage
.
enabled
,
true
);
expect
(
invocation
.
positionalArguments
,
<
String
>[
'analytics'
,
'enabled'
]);
expect
(
invocation
.
namedArguments
[
#label
],
'false'
);
});
expect
(
testUsage
.
enabled
,
true
);
await
commandRunner
.
run
(<
String
>[
'config'
,
'--no-analytics'
,
]);
expect
(
mock
Usage
.
enabled
,
false
);
expect
(
test
Usage
.
enabled
,
false
);
// Verify that we flushed the analytics queue.
verify
(
mockUsage
.
ensureAnalyticsSent
()
);
expect
(
testUsage
.
ensureAnalyticsSentCalls
,
1
);
// Verify that we only send the analytics disable event, and no other
// info.
verifyNever
(
mockUsage
.
sendCommand
(
any
,
parameters:
anyNamed
(
'parameters'
),
));
verifyNever
(
mockUsage
.
sendTiming
(
any
,
any
,
any
,
label:
anyNamed
(
'label'
),
));
expect
(
testUsage
.
events
,
equals
(<
TestUsageEvent
>[
const
TestUsageEvent
(
'analytics'
,
'enabled'
,
label:
'false'
),
]));
expect
(
testUsage
.
commands
,
isEmpty
);
expect
(
testUsage
.
timings
,
isEmpty
);
},
overrides:
<
Type
,
Generator
>{
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
testUsingContext
(
'analytics flag flips usage flag and sends event'
,
()
async
{
...
...
@@ -261,39 +231,24 @@ void main() {
'--analytics'
,
]);
expect
(
mock
Usage
.
enabled
,
true
);
expect
(
test
Usage
.
enabled
,
true
);
// Verify that we only send the analytics
dis
able event, and no other
// Verify that we only send the analytics
en
able event, and no other
// info.
verifyNever
(
mockUsage
.
sendCommand
(
any
,
parameters:
anyNamed
(
'parameters'
),
));
verifyNever
(
mockUsage
.
sendTiming
(
any
,
any
,
any
,
label:
anyNamed
(
'label'
),
));
expect
(
verify
(
mockUsage
.
sendEvent
(
captureAny
,
captureAny
,
label:
captureAnyNamed
(
'label'
),
value:
anyNamed
(
'value'
),
parameters:
anyNamed
(
'parameters'
),
)).
captured
,
<
dynamic
>[
'analytics'
,
'enabled'
,
'true'
],
);
expect
(
testUsage
.
events
,
equals
(<
TestUsageEvent
>[
const
TestUsageEvent
(
'analytics'
,
'enabled'
,
label:
'true'
),
]));
expect
(
testUsage
.
commands
,
isEmpty
);
expect
(
testUsage
.
timings
,
isEmpty
);
},
overrides:
<
Type
,
Generator
>{
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
testUsingContext
(
'analytics reported disabled when suppressed'
,
()
async
{
final
ConfigCommand
configCommand
=
ConfigCommand
();
final
CommandRunner
<
void
>
commandRunner
=
createTestCommandRunner
(
configCommand
);
mock
Usage
.
suppressAnalytics
=
true
;
test
Usage
.
suppressAnalytics
=
true
;
await
commandRunner
.
run
(<
String
>[
'config'
,
...
...
@@ -304,7 +259,7 @@ void main() {
containsIgnoringWhitespace
(
'Analytics reporting is currently disabled'
),
);
},
overrides:
<
Type
,
Generator
>{
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
});
}
...
...
@@ -320,11 +275,3 @@ class MockAndroidSdk extends Mock implements AndroidSdk {
}
class
MockFlutterVersion
extends
Mock
implements
FlutterVersion
{}
class
MockUsage
extends
Mock
implements
Usage
{
@override
bool
enabled
=
true
;
@override
bool
suppressAnalytics
=
false
;
}
packages/flutter_tools/test/commands.shard/hermetic/doctor_test.dart
View file @
6ecb8cbc
...
...
@@ -221,132 +221,123 @@ void main() {
});
group
(
'doctor usage params'
,
()
{
Usage
mock
Usage
;
TestUsage
test
Usage
;
setUp
(()
{
mockUsage
=
Mock
Usage
();
testUsage
=
Test
Usage
();
});
testUsingContext
(
'contains installed'
,
()
async
{
final
Doctor
doctor
=
Doctor
(
logger:
logger
);
await
doctor
.
diagnose
(
verbose:
false
);
expect
(
verify
(
mockUsage
.
sendEvent
(
expect
(
testUsage
.
events
.
length
,
3
);
expect
(
testUsage
.
events
,
contains
(
const
TestUsageEvent
(
'doctor-result'
,
'PassingValidator'
,
label:
captureAnyNamed
(
'label'
),
)).
captured
,
<
dynamic
>[
'installed'
,
'installed'
,
'installed'
],
);
label:
'installed'
,
),
));
},
overrides:
<
Type
,
Generator
>{
DoctorValidatorsProvider:
()
=>
FakeDoctorValidatorsProvider
(),
Platform:
_kNoColorOutputPlatform
,
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
testUsingContext
(
'contains installed and partial'
,
()
async
{
await
FakePassingDoctor
(
logger
).
diagnose
(
verbose:
false
);
expect
(
verify
(
mockUsage
.
send
Event
(
expect
(
testUsage
.
events
,
unorderedEquals
(<
TestUsageEvent
>[
const
TestUsage
Event
(
'doctor-result'
,
'PassingValidator'
,
label:
captureAnyNamed
(
'label'
),
)).
captured
,
<
dynamic
>[
'installed'
,
'installed'
],
);
expect
(
verify
(
mockUsage
.
sendEvent
(
label:
'installed'
,
),
const
TestUsageEvent
(
'doctor-result'
,
'PassingValidator'
,
label:
'installed'
,
),
const
TestUsageEvent
(
'doctor-result'
,
'PartialValidatorWithHintsOnly'
,
label:
captureAnyNamed
(
'label'
),
)).
captured
,
<
dynamic
>[
'partial'
],
);
expect
(
verify
(
mockUsage
.
sendEvent
(
label:
'partial'
,
),
const
TestUsageEvent
(
'doctor-result'
,
'PartialValidatorWithErrors'
,
label:
captureAnyNamed
(
'label'
),
)).
captured
,
<
dynamic
>[
'partial'
],
);
label:
'partial'
,
),
]));
},
overrides:
<
Type
,
Generator
>{
Platform:
_kNoColorOutputPlatform
,
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
testUsingContext
(
'contains installed, missing and partial'
,
()
async
{
await
FakeDoctor
(
logger
).
diagnose
(
verbose:
false
);
expect
(
verify
(
mockUsage
.
send
Event
(
expect
(
testUsage
.
events
,
unorderedEquals
(<
TestUsageEvent
>[
const
TestUsage
Event
(
'doctor-result'
,
'PassingValidator'
,
label:
captureAnyNamed
(
'label'
),
)).
captured
,
<
dynamic
>[
'installed'
],
);
expect
(
verify
(
mockUsage
.
sendEvent
(
label:
'installed'
,
),
const
TestUsageEvent
(
'doctor-result'
,
'MissingValidator'
,
label:
captureAnyNamed
(
'label'
),
)).
captured
,
<
dynamic
>[
'missing'
],
);
expect
(
verify
(
mockUsage
.
sendEvent
(
label:
'missing'
,
),
const
TestUsageEvent
(
'doctor-result'
,
'NotAvailableValidator'
,
label:
captureAnyNamed
(
'label'
),
)).
captured
,
<
dynamic
>[
'notAvailable'
],
);
expect
(
verify
(
mockUsage
.
sendEvent
(
label:
'notAvailable'
,
),
const
TestUsageEvent
(
'doctor-result'
,
'PartialValidatorWithHintsOnly'
,
label:
captureAnyNamed
(
'label'
),
)).
captured
,
<
dynamic
>[
'partial'
],
);
expect
(
verify
(
mockUsage
.
sendEvent
(
label:
'partial'
,
),
const
TestUsageEvent
(
'doctor-result'
,
'PartialValidatorWithErrors'
,
label:
captureAnyNamed
(
'label'
),
)).
captured
,
<
dynamic
>[
'partial'
],
);
label:
'partial'
,
),
]));
},
overrides:
<
Type
,
Generator
>{
Platform:
_kNoColorOutputPlatform
,
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
testUsingContext
(
'events for grouped validators are properly decomposed'
,
()
async
{
await
FakeGroupedDoctor
(
logger
).
diagnose
(
verbose:
false
);
expect
(
verify
(
mockUsage
.
send
Event
(
expect
(
testUsage
.
events
,
unorderedEquals
(<
TestUsageEvent
>[
const
TestUsage
Event
(
'doctor-result'
,
'PassingGroupedValidator'
,
label:
captureAnyNamed
(
'label'
),
)).
captured
,
<
dynamic
>[
'installed'
,
'installed'
,
'installed'
],
);
expect
(
verify
(
mockUsage
.
sendEvent
(
label:
'installed'
,
),
const
TestUsageEvent
(
'doctor-result'
,
'PassingGroupedValidator'
,
label:
'installed'
,
),
const
TestUsageEvent
(
'doctor-result'
,
'PassingGroupedValidator'
,
label:
'installed'
,
),
const
TestUsageEvent
(
'doctor-result'
,
'MissingGroupedValidator'
,
label:
captureAnyNamed
(
'label'
),
)).
captured
,
<
dynamic
>[
'missing'
],
);
label:
'missing'
,
),
]));
},
overrides:
<
Type
,
Generator
>{
Platform:
_kNoColorOutputPlatform
,
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
});
...
...
@@ -726,8 +717,6 @@ class NoOpDoctor implements Doctor {
List
<
Workflow
>
get
workflows
=>
<
Workflow
>[];
}
class
MockUsage
extends
Mock
implements
Usage
{}
class
PassingValidator
extends
DoctorValidator
{
PassingValidator
(
String
name
)
:
super
(
name
);
...
...
packages/flutter_tools/test/commands.shard/hermetic/run_test.dart
View file @
6ecb8cbc
...
...
@@ -484,7 +484,6 @@ void main() {
}
class
MockCache
extends
Mock
implements
Cache
{}
class
MockUsage
extends
Mock
implements
Usage
{}
class
MockDeviceManager
extends
Mock
implements
DeviceManager
{}
class
MockDevice
extends
Mock
implements
Device
{
...
...
packages/flutter_tools/test/commands.shard/permeable/build_aar_test.dart
View file @
6ecb8cbc
...
...
@@ -41,10 +41,10 @@ void main() {
group
(
'Usage'
,
()
{
Directory
tempDir
;
Usage
mock
Usage
;
TestUsage
test
Usage
;
setUp
(()
{
mockUsage
=
Mock
Usage
();
testUsage
=
Test
Usage
();
tempDir
=
globals
.
fs
.
systemTempDirectory
.
createTempSync
(
'flutter_tools_packages_test.'
);
});
...
...
@@ -96,17 +96,17 @@ void main() {
await
runCommandIn
(
projectPath
,
arguments:
<
String
>[
'--target-platform=android-arm'
]);
verify
(
mockUsage
.
sendEvent
(
'tool-command-result'
,
'aar
'
,
label:
'success
'
,
value:
anyNamed
(
'value'
)
,
parameters:
anyNamed
(
'parameters'
),
))
.
called
(
1
)
;
expect
(
testUsage
.
events
,
contains
(
const
TestUsageEvent
(
'tool-command-result
'
,
'aar
'
,
label:
'success'
,
),
));
},
overrides:
<
Type
,
Generator
>{
AndroidBuilder:
()
=>
FakeAndroidBuilder
(),
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
});
...
...
@@ -297,4 +297,3 @@ class MockAndroidBuilder extends Mock implements AndroidBuilder {}
class
MockAndroidSdk
extends
Mock
implements
AndroidSdk
{}
class
MockProcessManager
extends
Mock
implements
ProcessManager
{}
class
MockProcess
extends
Mock
implements
Process
{}
class
MockUsage
extends
Mock
implements
Usage
{}
packages/flutter_tools/test/commands.shard/permeable/build_apk_test.dart
View file @
6ecb8cbc
...
...
@@ -30,10 +30,10 @@ void main() {
group
(
'Usage'
,
()
{
Directory
tempDir
;
Usage
mock
Usage
;
TestUsage
test
Usage
;
setUp
(()
{
mockUsage
=
Mock
Usage
();
testUsage
=
Test
Usage
();
tempDir
=
globals
.
fs
.
systemTempDirectory
.
createTempSync
(
'flutter_tools_packages_test.'
);
});
...
...
@@ -103,17 +103,17 @@ void main() {
await
runBuildApkCommand
(
projectPath
);
verify
(
mockUsage
.
sendEvent
(
'tool-command-result'
,
'apk
'
,
label:
'success
'
,
value:
anyNamed
(
'value'
)
,
parameters:
anyNamed
(
'parameters'
),
))
.
called
(
1
)
;
expect
(
testUsage
.
events
,
contains
(
const
TestUsageEvent
(
'tool-command-result
'
,
'apk
'
,
label:
'success'
,
),
));
},
overrides:
<
Type
,
Generator
>{
AndroidBuilder:
()
=>
FakeAndroidBuilder
(),
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
});
...
...
@@ -122,10 +122,10 @@ void main() {
ProcessManager
mockProcessManager
;
String
gradlew
;
AndroidSdk
mockAndroidSdk
;
Usage
mock
Usage
;
TestUsage
test
Usage
;
setUp
(()
{
mockUsage
=
Mock
Usage
();
testUsage
=
Test
Usage
();
tempDir
=
globals
.
fs
.
systemTempDirectory
.
createTempSync
(
'flutter_tools_packages_test.'
);
gradlew
=
globals
.
fs
.
path
.
join
(
tempDir
.
path
,
'flutter_project'
,
'android'
,
...
...
@@ -390,18 +390,20 @@ void main() {
containsIgnoringWhitespace
(
'To learn more, see: https://developer.android.com/studio/build/shrink-code'
),
);
verify
(
mockUsage
.
sendEvent
(
'build'
,
'apk'
,
label:
'gradle-r8-failure'
,
parameters:
anyNamed
(
'parameters'
),
)).
called
(
1
);
expect
(
testUsage
.
events
,
contains
(
const
TestUsageEvent
(
'build'
,
'apk'
,
label:
'gradle-r8-failure'
,
parameters:
<
String
,
String
>{},
),
));
},
overrides:
<
Type
,
Generator
>{
AndroidSdk:
()
=>
mockAndroidSdk
,
FlutterProjectFactory:
()
=>
FakeFlutterProjectFactory
(
tempDir
),
ProcessManager:
()
=>
mockProcessManager
,
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
testUsingContext
(
"reports when the app isn't using AndroidX"
,
()
async
{
...
...
@@ -452,18 +454,21 @@ void main() {
'following the steps on https://goo.gl/CP92wY'
),
);
verify
(
mockUsage
.
sendEvent
(
'build'
,
'apk'
,
label:
'app-not-using-android-x'
,
parameters:
anyNamed
(
'parameters'
),
)).
called
(
1
);
expect
(
testUsage
.
events
,
contains
(
const
TestUsageEvent
(
'build'
,
'apk'
,
label:
'app-not-using-android-x'
,
parameters:
<
String
,
String
>{},
),
));
},
overrides:
<
Type
,
Generator
>{
AndroidSdk:
()
=>
mockAndroidSdk
,
FlutterProjectFactory:
()
=>
FakeFlutterProjectFactory
(
tempDir
),
ProcessManager:
()
=>
mockProcessManager
,
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
testUsingContext
(
'reports when the app is using AndroidX'
,
()
async
{
...
...
@@ -505,18 +510,21 @@ void main() {
),
isFalse
,
);
verify
(
mockUsage
.
sendEvent
(
'build'
,
'apk'
,
label:
'app-using-android-x'
,
parameters:
anyNamed
(
'parameters'
),
)).
called
(
1
);
expect
(
testUsage
.
events
,
contains
(
const
TestUsageEvent
(
'build'
,
'apk'
,
label:
'app-using-android-x'
,
parameters:
<
String
,
String
>{},
),
));
},
overrides:
<
Type
,
Generator
>{
AndroidSdk:
()
=>
mockAndroidSdk
,
FlutterProjectFactory:
()
=>
FakeFlutterProjectFactory
(
tempDir
),
ProcessManager:
()
=>
mockProcessManager
,
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
});
}
...
...
@@ -539,4 +547,3 @@ Future<BuildApkCommand> runBuildApkCommand(
class
MockAndroidSdk
extends
Mock
implements
AndroidSdk
{}
class
MockProcessManager
extends
Mock
implements
ProcessManager
{}
class
MockProcess
extends
Mock
implements
Process
{}
class
MockUsage
extends
Mock
implements
Usage
{}
packages/flutter_tools/test/commands.shard/permeable/build_appbundle_test.dart
View file @
6ecb8cbc
...
...
@@ -29,11 +29,11 @@ void main() {
group
(
'Usage'
,
()
{
Directory
tempDir
;
Usage
mock
Usage
;
TestUsage
test
Usage
;
setUp
(()
{
tempDir
=
globals
.
fs
.
systemTempDirectory
.
createTempSync
(
'flutter_tools_packages_test.'
);
mockUsage
=
Mock
Usage
();
testUsage
=
Test
Usage
();
});
tearDown
(()
{
...
...
@@ -85,17 +85,13 @@ void main() {
await
runBuildAppBundleCommand
(
projectPath
);
verify
(
mockUsage
.
sendEvent
(
'tool-command-result'
,
'appbundle'
,
label:
'success'
,
value:
anyNamed
(
'value'
),
parameters:
anyNamed
(
'parameters'
),
)).
called
(
1
);
expect
(
testUsage
.
events
,
contains
(
const
TestUsageEvent
(
'tool-command-result'
,
'appbundle'
,
label:
'success'
),
));
},
overrides:
<
Type
,
Generator
>{
AndroidBuilder:
()
=>
FakeAndroidBuilder
(),
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
});
...
...
@@ -104,10 +100,10 @@ void main() {
ProcessManager
mockProcessManager
;
MockAndroidSdk
mockAndroidSdk
;
String
gradlew
;
Usage
mock
Usage
;
TestUsage
test
Usage
;
setUp
(()
{
mockUsage
=
Mock
Usage
();
testUsage
=
Test
Usage
();
tempDir
=
globals
.
fs
.
systemTempDirectory
.
createTempSync
(
'flutter_tools_packages_test.'
);
gradlew
=
globals
.
fs
.
path
.
join
(
tempDir
.
path
,
'flutter_project'
,
'android'
,
globals
.
platform
.
isWindows
?
'gradlew.bat'
:
'gradlew'
);
...
...
@@ -254,18 +250,21 @@ void main() {
'following the steps on https://goo.gl/CP92wY'
),
);
verify
(
mockUsage
.
sendEvent
(
'build'
,
'appbundle'
,
label:
'app-not-using-android-x'
,
parameters:
anyNamed
(
'parameters'
),
)).
called
(
1
);
expect
(
testUsage
.
events
,
contains
(
const
TestUsageEvent
(
'build'
,
'appbundle'
,
label:
'app-not-using-android-x'
,
parameters:
<
String
,
String
>{},
),
));
},
overrides:
<
Type
,
Generator
>{
AndroidSdk:
()
=>
mockAndroidSdk
,
FlutterProjectFactory:
()
=>
FakeFlutterProjectFactory
(
tempDir
),
ProcessManager:
()
=>
mockProcessManager
,
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
testUsingContext
(
'reports when the app is using AndroidX'
,
()
async
{
...
...
@@ -310,18 +309,21 @@ void main() {
'following the steps on https://goo.gl/CP92wY'
),
)
);
verify
(
mockUsage
.
sendEvent
(
'build'
,
'appbundle'
,
label:
'app-using-android-x'
,
parameters:
anyNamed
(
'parameters'
),
)).
called
(
1
);
expect
(
testUsage
.
events
,
contains
(
const
TestUsageEvent
(
'build'
,
'appbundle'
,
label:
'app-using-android-x'
,
parameters:
<
String
,
String
>{},
),
));
},
overrides:
<
Type
,
Generator
>{
AndroidSdk:
()
=>
mockAndroidSdk
,
FlutterProjectFactory:
()
=>
FakeFlutterProjectFactory
(
tempDir
),
ProcessManager:
()
=>
mockProcessManager
,
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
});
}
...
...
@@ -348,4 +350,3 @@ Matcher not(Matcher target){
class
MockAndroidSdk
extends
Mock
implements
AndroidSdk
{}
class
MockProcessManager
extends
Mock
implements
ProcessManager
{}
class
MockProcess
extends
Mock
implements
Process
{}
class
MockUsage
extends
Mock
implements
Usage
{}
packages/flutter_tools/test/general.shard/analytics_test.dart
View file @
6ecb8cbc
...
...
@@ -153,7 +153,7 @@ void main() {
group
(
'analytics with mocks'
,
()
{
MemoryFileSystem
memoryFileSystem
;
MockStdio
mockStdio
;
Usage
mock
Usage
;
TestUsage
test
Usage
;
SystemClock
mockClock
;
Doctor
mockDoctor
;
List
<
int
>
mockTimes
;
...
...
@@ -161,7 +161,7 @@ void main() {
setUp
(()
{
memoryFileSystem
=
MemoryFileSystem
.
test
();
mockStdio
=
MockStdio
();
mockUsage
=
Mock
Usage
();
testUsage
=
Test
Usage
();
mockClock
=
MockClock
();
mockDoctor
=
MockDoctor
();
when
(
mockClock
.
now
()).
thenAnswer
(
...
...
@@ -182,19 +182,15 @@ void main() {
verify
(
mockClock
.
now
()).
called
(
2
);
expect
(
verify
(
mockUsage
.
sendTiming
(
captureAny
,
captureAny
,
captureAny
,
label:
captureAnyNamed
(
'label'
),
)).
captured
,
<
dynamic
>[
'flutter'
,
'doctor'
,
const
Duration
(
milliseconds:
1000
),
'success'
],
);
expect
(
testUsage
.
timings
,
contains
(
const
TestTimingEvent
(
'flutter'
,
'doctor'
,
Duration
(
milliseconds:
1000
),
label:
'success'
,
),
));
},
overrides:
<
Type
,
Generator
>{
SystemClock:
()
=>
mockClock
,
Doctor:
()
=>
mockDoctor
,
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
testUsingContext
(
'doctor fail sends warning'
,
()
async
{
...
...
@@ -207,19 +203,15 @@ void main() {
verify
(
mockClock
.
now
()).
called
(
2
);
expect
(
verify
(
mockUsage
.
sendTiming
(
captureAny
,
captureAny
,
captureAny
,
label:
captureAnyNamed
(
'label'
),
)).
captured
,
<
dynamic
>[
'flutter'
,
'doctor'
,
const
Duration
(
milliseconds:
1000
),
'warning'
],
);
expect
(
testUsage
.
timings
,
contains
(
const
TestTimingEvent
(
'flutter'
,
'doctor'
,
Duration
(
milliseconds:
1000
),
label:
'warning'
,
),
));
},
overrides:
<
Type
,
Generator
>{
SystemClock:
()
=>
mockClock
,
Doctor:
()
=>
mockDoctor
,
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
testUsingContext
(
'single command usage path'
,
()
async
{
...
...
@@ -227,7 +219,7 @@ void main() {
expect
(
await
doctorCommand
.
usagePath
,
'doctor'
);
},
overrides:
<
Type
,
Generator
>{
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
testUsingContext
(
'compound command usage path'
,
()
async
{
...
...
@@ -236,7 +228,7 @@ void main() {
expect
(
await
buildApkCommand
.
usagePath
,
'build/apk'
);
},
overrides:
<
Type
,
Generator
>{
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
testUsingContext
(
'command sends localtime'
,
()
async
{
...
...
@@ -383,8 +375,6 @@ class FakeFlutterCommand extends FlutterCommand {
}
}
class
MockUsage
extends
Mock
implements
Usage
{}
class
MockDoctor
extends
Mock
implements
Doctor
{}
class
MockFlutterConfig
extends
Mock
implements
Config
{}
packages/flutter_tools/test/general.shard/android/gradle_errors_test.dart
View file @
6ecb8cbc
...
...
@@ -24,7 +24,7 @@ import '../../src/mocks.dart';
void
main
(
)
{
group
(
'gradleErrors'
,
()
{
test
(
'list of errors'
,
()
{
test
WithoutContext
(
'list of errors'
,
()
{
// If you added a new Gradle error, please update this test.
expect
(
gradleErrors
,
equals
(<
GradleHandledError
>[
...
...
@@ -325,9 +325,9 @@ Command: /home/android/gradlew assembleRelease
});
group('
AndroidX
', () {
final
Usage mockUsage = Mock
Usage();
final
TestUsage testUsage = Test
Usage();
test('
pattern
', () {
test
WithoutContext
('
pattern
', () {
expect(androidXFailureHandler.test(
'
AAPT:
error:
resource
android:
attr
/
fontVariationSettings
not
found
.
'
), isTrue);
...
...
@@ -357,20 +357,22 @@ Command: /home/android/gradlew assembleRelease
final GradleBuildStatus status = await androidXFailureHandler
.handler(line: '', project: FlutterProject.current());
verify(mockUsage.sendEvent(
any,
any,
label: '
gradle
-
android
-
x
-
failure
',
parameters: <String, String>{
'
cd43
': '
app
-
not
-
using
-
plugins
',
},
)).called(1);
expect(testUsage.events, contains(
const TestUsageEvent(
'
build
',
'
unspecified
',
label: '
gradle
-
android
-
x
-
failure
',
parameters: <String, String>{
'
cd43
': '
app
-
not
-
using
-
plugins
',
},
),
));
expect(status, equals(GradleBuildStatus.exit));
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem.test(),
ProcessManager: () => MockProcessManager(),
Usage: () =>
mock
Usage,
Usage: () =>
test
Usage,
});
testUsingContext('
handler
-
plugins
and
no
AndroidX
', () async {
...
...
@@ -389,20 +391,23 @@ Command: /home/android/gradlew assembleRelease
'
Please
migrate
your
app
to
AndroidX
.
See
https:
//goo.gl/CP92wY .'
)
);
verify
(
mockUsage
.
sendEvent
(
any
,
any
,
label:
'gradle-android-x-failure'
,
parameters:
<
String
,
String
>{
'cd43'
:
'app-not-using-androidx'
,
},
)).
called
(
1
);
expect
(
testUsage
.
events
,
contains
(
const
TestUsageEvent
(
'build'
,
'unspecified'
,
label:
'gradle-android-x-failure'
,
parameters:
<
String
,
String
>{
'cd43'
:
'app-not-using-androidx'
,
},
),
));
expect
(
status
,
equals
(
GradleBuildStatus
.
exit
));
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
MemoryFileSystem
.
test
(),
ProcessManager:
()
=>
MockProcessManager
(),
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
testUsingContext
(
'handler - plugins, AndroidX, and AAR'
,
()
async
{
...
...
@@ -415,20 +420,22 @@ Command: /home/android/gradlew assembleRelease
shouldBuildPluginAsAar:
true
,
);
verify
(
mockUsage
.
sendEvent
(
any
,
any
,
label:
'gradle-android-x-failure'
,
parameters:
<
String
,
String
>{
'cd43'
:
'using-jetifier'
,
},
)).
called
(
1
);
expect
(
testUsage
.
events
,
contains
(
const
TestUsageEvent
(
'build'
,
'unspecified'
,
label:
'gradle-android-x-failure'
,
parameters:
<
String
,
String
>{
'cd43'
:
'using-jetifier'
,
},
),
));
expect
(
status
,
equals
(
GradleBuildStatus
.
exit
));
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
MemoryFileSystem
.
test
(),
ProcessManager:
()
=>
MockProcessManager
(),
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
testUsingContext
(
'handler - plugins, AndroidX, and no AAR'
,
()
async
{
...
...
@@ -447,19 +454,22 @@ Command: /home/android/gradlew assembleRelease
'The tool is about to try using Jetifier to solve the incompatibility.'
)
);
verify
(
mockUsage
.
sendEvent
(
any
,
any
,
label:
'gradle-android-x-failure'
,
parameters:
<
String
,
String
>{
'cd43'
:
'not-using-jetifier'
,
},
)).
called
(
1
);
expect
(
testUsage
.
events
,
contains
(
const
TestUsageEvent
(
'build'
,
'unspecified'
,
label:
'gradle-android-x-failure'
,
parameters:
<
String
,
String
>{
'cd43'
:
'not-using-jetifier'
,
},
),
));
expect
(
status
,
equals
(
GradleBuildStatus
.
retryWithAarPlugins
));
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
MemoryFileSystem
.
test
(),
ProcessManager:
()
=>
MockProcessManager
(),
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
});
...
...
@@ -490,7 +500,7 @@ Command: /home/android/gradlew assembleRelease
});
group
(
'license not accepted'
,
()
{
test
(
'pattern'
,
()
{
test
WithoutContext
(
'pattern'
,
()
{
expect
(
licenseNotAcceptedHandler
.
test
(
'You have not accepted the license agreements of the following SDK components'
...
...
@@ -525,7 +535,7 @@ Command: /home/android/gradlew assembleRelease
mockProcessManager
=
MockProcessManager
();
});
test
(
'pattern'
,
()
{
test
WithoutContext
(
'pattern'
,
()
{
expect
(
flavorUndefinedHandler
.
test
(
'Task assembleFooRelease not found in root project.'
...
...
@@ -657,8 +667,6 @@ assembleProfile
});
}
class
MockUsage
extends
Mock
implements
Usage
{}
bool
formatTestErrorMessage
(
String
errorMessage
,
GradleHandledError
error
)
{
return
errorMessage
.
split
(
'
\n
'
)
...
...
packages/flutter_tools/test/general.shard/android/gradle_test.dart
View file @
6ecb8cbc
...
...
@@ -22,7 +22,6 @@ import 'package:flutter_tools/src/base/terminal.dart';
import
'package:flutter_tools/src/build_info.dart'
;
import
'package:flutter_tools/src/cache.dart'
;
import
'package:flutter_tools/src/globals.dart'
as
globals
;
import
'package:flutter_tools/src/ios/xcodeproj.dart'
;
import
'package:flutter_tools/src/project.dart'
;
import
'package:flutter_tools/src/reporting/reporting.dart'
;
import
'package:mockito/mockito.dart'
;
...
...
@@ -139,11 +138,11 @@ void main() {
group
(
'findBundleFile'
,
()
{
FileSystem
fileSystem
;
Usage
mock
Usage
;
TestUsage
test
Usage
;
setUp
(()
{
fileSystem
=
MemoryFileSystem
.
test
();
mockUsage
=
Mock
Usage
();
testUsage
=
Test
Usage
();
});
testWithoutContext
(
'Finds app bundle when flavor contains underscores in release mode'
,
()
{
...
...
@@ -312,20 +311,20 @@ void main() {
"was generated under
${project.android.buildDirectory.path}
, but the tool couldn't find it."
)
);
verify
(
mockUsage
.
send
Event
(
any
,
any
,
expect
(
testUsage
.
events
,
contains
(
const
TestUsage
Event
(
'build'
,
'unspecified'
,
label:
'gradle-expected-file-not-found'
,
parameters:
const
<
String
,
String
>
{
parameters:
<
String
,
String
>
{
'cd37'
:
'androidGradlePluginVersion: 6.7, fileExtension: .aab'
,
},
),
)
.
called
(
1
);
));
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
MemoryFileSystem
.
test
(),
ProcessManager:
()
=>
FakeProcessManager
.
any
(),
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
});
...
...
@@ -1007,7 +1006,7 @@ plugin1=${plugin1.path}
});
group
(
'gradle build'
,
()
{
Usage
mock
Usage
;
TestUsage
test
Usage
;
MockAndroidSdk
mockAndroidSdk
;
MockAndroidStudio
mockAndroidStudio
;
MockLocalEngineArtifacts
mockArtifacts
;
...
...
@@ -1018,7 +1017,7 @@ plugin1=${plugin1.path}
Cache
cache
;
setUp
(()
{
mockUsage
=
Mock
Usage
();
testUsage
=
Test
Usage
();
fileSystem
=
MemoryFileSystem
.
test
();
fileSystemUtils
=
MockFileSystemUtils
();
mockAndroidSdk
=
MockAndroidSdk
();
...
...
@@ -1117,20 +1116,21 @@ plugin1=${plugin1.path}
expect
(
handlerCalled
,
isTrue
);
verify
(
mockUsage
.
sendEvent
(
any
,
any
,
label:
'gradle-random-event-label-failure'
,
parameters:
anyNamed
(
'parameters'
),
)).
called
(
1
);
expect
(
testUsage
.
events
,
contains
(
const
TestUsageEvent
(
'build'
,
'unspecified'
,
label:
'gradle-random-event-label-failure'
,
parameters:
<
String
,
String
>{},
),
));
},
overrides:
<
Type
,
Generator
>{
AndroidSdk:
()
=>
mockAndroidSdk
,
Cache:
()
=>
cache
,
Platform:
()
=>
android
,
FileSystem:
()
=>
fileSystem
,
ProcessManager:
()
=>
mockProcessManager
,
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
testUsingContext
(
'recognizes common errors - retry build'
,
()
async
{
...
...
@@ -1198,21 +1198,21 @@ plugin1=${plugin1.path}
));
expect
(
testFnCalled
,
equals
(
2
));
verify
(
mockUsage
.
send
Event
(
any
,
any
,
label:
'gradle-random-event-label-failure'
,
parameters:
anyNamed
(
'parameters'
)
,
)).
called
(
1
);
expect
(
testUsage
.
events
,
contains
(
const
TestUsage
Event
(
'build'
,
'unspecified'
,
label:
'gradle-random-event-label-failure'
,
parameters:
<
String
,
String
>{}
,
),
));
},
overrides:
<
Type
,
Generator
>{
AndroidSdk:
()
=>
mockAndroidSdk
,
Cache:
()
=>
cache
,
Platform:
()
=>
android
,
FileSystem:
()
=>
fileSystem
,
ProcessManager:
()
=>
mockProcessManager
,
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
testUsingContext
(
'recognizes process exceptions - tool exit'
,
()
async
{
...
...
@@ -1273,20 +1273,21 @@ plugin1=${plugin1.path}
expect
(
handlerCalled
,
isTrue
);
verify
(
mockUsage
.
sendEvent
(
any
,
any
,
label:
'gradle-random-event-label-failure'
,
parameters:
anyNamed
(
'parameters'
),
)).
called
(
1
);
expect
(
testUsage
.
events
,
contains
(
const
TestUsageEvent
(
'build'
,
'unspecified'
,
label:
'gradle-random-event-label-failure'
,
parameters:
<
String
,
String
>{},
),
));
},
overrides:
<
Type
,
Generator
>{
AndroidSdk:
()
=>
mockAndroidSdk
,
Cache:
()
=>
cache
,
Platform:
()
=>
android
,
FileSystem:
()
=>
fileSystem
,
ProcessManager:
()
=>
mockProcessManager
,
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
testUsingContext
(
'rethrows unrecognized ProcessException'
,
()
async
{
...
...
@@ -1406,19 +1407,21 @@ plugin1=${plugin1.path}
],
);
verify
(
mockUsage
.
sendEvent
(
any
,
any
,
label:
'gradle-random-event-label-success'
,
parameters:
anyNamed
(
'parameters'
),
)).
called
(
1
);
expect
(
testUsage
.
events
,
contains
(
const
TestUsageEvent
(
'build'
,
'unspecified'
,
label:
'gradle-random-event-label-success'
,
parameters:
<
String
,
String
>{},
),
));
},
overrides:
<
Type
,
Generator
>{
AndroidSdk:
()
=>
mockAndroidSdk
,
Cache:
()
=>
cache
,
FileSystem:
()
=>
fileSystem
,
Platform:
()
=>
android
,
ProcessManager:
()
=>
mockProcessManager
,
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
testUsingContext
(
'performs code size analysis and sends analytics'
,
()
async
{
...
...
@@ -1492,17 +1495,19 @@ plugin1=${plugin1.path}
localGradleErrors:
<
GradleHandledError
>[],
);
verify
(
mockUsage
.
sendEvent
(
'code-size-analysis'
,
'apk'
,
)).
called
(
1
);
expect
(
testUsage
.
events
,
contains
(
const
TestUsageEvent
(
'code-size-analysis'
,
'apk'
,
),
));
},
overrides:
<
Type
,
Generator
>{
AndroidSdk:
()
=>
mockAndroidSdk
,
Cache:
()
=>
cache
,
FileSystem:
()
=>
fileSystem
,
Platform:
()
=>
android
,
ProcessManager:
()
=>
mockProcessManager
,
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
testUsingContext
(
'recognizes common errors - retry build with AAR plugins'
,
()
async
{
...
...
@@ -1576,20 +1581,21 @@ plugin1=${plugin1.path}
expect
(
testFnCalled
,
equals
(
2
));
expect
(
builtPluginAsAar
,
isTrue
);
verify
(
mockUsage
.
sendEvent
(
any
,
any
,
label:
'gradle-random-event-label-failure'
,
parameters:
anyNamed
(
'parameters'
),
)).
called
(
1
);
expect
(
testUsage
.
events
,
contains
(
const
TestUsageEvent
(
'build'
,
'unspecified'
,
label:
'gradle-random-event-label-failure'
,
parameters:
<
String
,
String
>{},
),
));
},
overrides:
<
Type
,
Generator
>{
AndroidSdk:
()
=>
mockAndroidSdk
,
Cache:
()
=>
cache
,
Platform:
()
=>
android
,
FileSystem:
()
=>
fileSystem
,
ProcessManager:
()
=>
mockProcessManager
,
Usage:
()
=>
mock
Usage
,
Usage:
()
=>
test
Usage
,
});
testUsingContext
(
'indicates that an APK has been built successfully'
,
()
async
{
...
...
@@ -2797,11 +2803,7 @@ class FakeGradleUtils extends GradleUtils {
class
MockAndroidSdk
extends
Mock
implements
AndroidSdk
{}
class
MockAndroidProject
extends
Mock
implements
AndroidProject
{}
class
MockAndroidStudio
extends
Mock
implements
AndroidStudio
{}
class
MockDirectory
extends
Mock
implements
Directory
{}
class
MockFile
extends
Mock
implements
File
{}
class
MockFileSystemUtils
extends
Mock
implements
FileSystemUtils
{}
class
MockFlutterProject
extends
Mock
implements
FlutterProject
{}
class
MockLocalEngineArtifacts
extends
Mock
implements
LocalEngineArtifacts
{}
class
MockProcessManager
extends
Mock
implements
ProcessManager
{}
class
MockXcodeProjectInterpreter
extends
Mock
implements
XcodeProjectInterpreter
{}
class
MockUsage
extends
Mock
implements
Usage
{}
packages/flutter_tools/test/general.shard/base/error_handling_io_test.dart
View file @
6ecb8cbc
...
...
@@ -25,7 +25,6 @@ class MockPathContext extends Mock implements path.Context {}
class
MockDirectory
extends
Mock
implements
Directory
{}
class
MockRandomAccessFile
extends
Mock
implements
RandomAccessFile
{}
class
MockProcessManager
extends
Mock
implements
ProcessManager
{}
class
MockUsage
extends
Mock
implements
Usage
{}
final
Platform
windowsPlatform
=
FakePlatform
(
operatingSystem:
'windows'
,
...
...
@@ -927,9 +926,11 @@ void main() {
fileSystem
.
file
(
'source'
).
copySync
(
'dest'
);
expect
(
memoryDest
.
readAsBytesSync
(),
expectedBytes
);
verify
(
globals
.
flutterUsage
.
sendEvent
(
'error-handling'
,
'copy-fallback'
)).
called
(
1
);
expect
((
globals
.
flutterUsage
as
TestUsage
).
events
,
contains
(
const
TestUsageEvent
(
'error-handling'
,
'copy-fallback'
),
));
},
overrides:
<
Type
,
Generator
>{
Usage:
()
=>
Mock
Usage
(),
Usage:
()
=>
Test
Usage
(),
});
// Uses context for analytics.
...
...
@@ -963,7 +964,7 @@ void main() {
verify
(
dest
.
deleteSync
(
recursive:
true
)).
called
(
1
);
},
overrides:
<
Type
,
Generator
>{
Usage:
()
=>
Mock
Usage
(),
Usage:
()
=>
Test
Usage
(),
});
});
}
...
...
packages/flutter_tools/test/general.shard/crash_reporting_test.dart
View file @
6ecb8cbc
...
...
@@ -17,7 +17,6 @@ import 'package:flutter_tools/src/project.dart';
import
'package:flutter_tools/src/reporting/reporting.dart'
;
import
'package:http/http.dart'
;
import
'package:http/testing.dart'
;
import
'package:mockito/mockito.dart'
;
import
'../src/common.dart'
;
import
'../src/context.dart'
;
...
...
@@ -26,16 +25,14 @@ import '../src/testbed.dart';
void
main
(
)
{
BufferLogger
logger
;
FileSystem
fs
;
MockUsage
mock
Usage
;
TestUsage
test
Usage
;
Platform
platform
;
OperatingSystemUtils
operatingSystemUtils
;
setUp
(()
async
{
logger
=
BufferLogger
.
test
();
fs
=
MemoryFileSystem
.
test
();
mockUsage
=
MockUsage
();
when
(
mockUsage
.
clientId
).
thenReturn
(
'00000000-0000-4000-0000-000000000000'
);
testUsage
=
TestUsage
();
platform
=
FakePlatform
(
environment:
<
String
,
String
>{},
operatingSystem:
'linux'
);
operatingSystemUtils
=
OperatingSystemUtils
(
...
...
@@ -63,7 +60,7 @@ void main() {
'version'
:
'test-version'
,
},
));
expect
(
crashInfo
.
fields
[
'uuid'
],
'00000000-0000-4000-0000-000000000000'
);
expect
(
crashInfo
.
fields
[
'uuid'
],
testUsage
.
clientId
);
expect
(
crashInfo
.
fields
[
'product'
],
'Flutter_Tools'
);
expect
(
crashInfo
.
fields
[
'version'
],
'test-version'
);
expect
(
crashInfo
.
fields
[
'osName'
],
'linux'
);
...
...
@@ -101,11 +98,11 @@ void main() {
});
testWithoutContext
(
'suppress analytics'
,
()
async
{
when
(
mockUsage
.
suppressAnalytics
).
thenReturn
(
true
)
;
testUsage
.
suppressAnalytics
=
true
;
final
CrashReportSender
crashReportSender
=
CrashReportSender
(
client:
CrashingCrashReportSender
(
const
SocketException
(
'no internets'
)),
usage:
mock
Usage
,
usage:
test
Usage
,
platform:
platform
,
logger:
logger
,
operatingSystemUtils:
operatingSystemUtils
,
...
...
@@ -123,7 +120,7 @@ void main() {
group
(
'allow analytics'
,
()
{
setUp
(()
async
{
when
(
mockUsage
.
suppressAnalytics
).
thenReturn
(
false
)
;
testUsage
.
suppressAnalytics
=
false
;
});
testWithoutContext
(
'should send crash reports'
,
()
async
{
...
...
@@ -131,7 +128,7 @@ void main() {
final
CrashReportSender
crashReportSender
=
CrashReportSender
(
client:
MockCrashReportSender
(
requestInfo
),
usage:
mock
Usage
,
usage:
test
Usage
,
platform:
platform
,
logger:
logger
,
operatingSystemUtils:
operatingSystemUtils
,
...
...
@@ -150,7 +147,7 @@ void main() {
testWithoutContext
(
'should print an explanatory message when there is a SocketException'
,
()
async
{
final
CrashReportSender
crashReportSender
=
CrashReportSender
(
client:
CrashingCrashReportSender
(
const
SocketException
(
'no internets'
)),
usage:
mock
Usage
,
usage:
test
Usage
,
platform:
platform
,
logger:
logger
,
operatingSystemUtils:
operatingSystemUtils
,
...
...
@@ -169,7 +166,7 @@ void main() {
testWithoutContext
(
'should print an explanatory message when there is an HttpException'
,
()
async
{
final
CrashReportSender
crashReportSender
=
CrashReportSender
(
client:
CrashingCrashReportSender
(
const
HttpException
(
'no internets'
)),
usage:
mock
Usage
,
usage:
test
Usage
,
platform:
platform
,
logger:
logger
,
operatingSystemUtils:
operatingSystemUtils
,
...
...
@@ -188,7 +185,7 @@ void main() {
testWithoutContext
(
'should print an explanatory message when there is a ClientException'
,
()
async
{
final
CrashReportSender
crashReportSender
=
CrashReportSender
(
client:
CrashingCrashReportSender
(
const
HttpException
(
'no internets'
)),
usage:
mock
Usage
,
usage:
test
Usage
,
platform:
platform
,
logger:
logger
,
operatingSystemUtils:
operatingSystemUtils
,
...
...
@@ -209,7 +206,7 @@ void main() {
final
CrashReportSender
crashReportSender
=
CrashReportSender
(
client:
MockCrashReportSender
(
requestInfo
),
usage:
mock
Usage
,
usage:
test
Usage
,
platform:
platform
,
logger:
logger
,
operatingSystemUtils:
operatingSystemUtils
,
...
...
@@ -263,7 +260,7 @@ void main() {
final
CrashReportSender
crashReportSender
=
CrashReportSender
(
client:
mockClient
,
usage:
mock
Usage
,
usage:
test
Usage
,
platform:
platform
,
logger:
logger
,
operatingSystemUtils:
operatingSystemUtils
,
...
...
@@ -301,7 +298,7 @@ void main() {
final
CrashReportSender
crashReportSender
=
CrashReportSender
(
client:
mockClient
,
usage:
mock
Usage
,
usage:
test
Usage
,
platform:
environmentPlatform
,
logger:
logger
,
operatingSystemUtils:
operatingSystemUtils
,
...
...
@@ -392,5 +389,3 @@ class FakeDoctorValidatorsProvider implements DoctorValidatorsProvider {
@override
List
<
Workflow
>
get
workflows
=>
<
Workflow
>[];
}
class
MockUsage
extends
Mock
implements
Usage
{}
packages/flutter_tools/test/general.shard/dart/pub_get_test.dart
View file @
6ecb8cbc
...
...
@@ -48,7 +48,7 @@ void main() {
fileSystem:
fileSystem
,
logger:
logger
,
processManager:
processManager
,
usage:
Mock
Usage
(),
usage:
Test
Usage
(),
platform:
FakePlatform
(
environment:
const
<
String
,
String
>{},
),
...
...
@@ -86,7 +86,7 @@ void main() {
fileSystem:
fileSystem
,
logger:
logger
,
processManager:
processManager
,
usage:
Mock
Usage
(),
usage:
Test
Usage
(),
platform:
FakePlatform
(
environment:
const
<
String
,
String
>{},
),
...
...
@@ -124,7 +124,7 @@ void main() {
fileSystem:
fileSystem
,
logger:
logger
,
processManager:
processManager
,
usage:
Mock
Usage
(),
usage:
Test
Usage
(),
platform:
FakePlatform
(
environment:
const
<
String
,
String
>{},
),
...
...
@@ -162,7 +162,7 @@ void main() {
fileSystem:
fileSystem
,
logger:
logger
,
processManager:
processManager
,
usage:
Mock
Usage
(),
usage:
Test
Usage
(),
platform:
FakePlatform
(
environment:
const
<
String
,
String
>{},
),
...
...
@@ -199,7 +199,7 @@ void main() {
fileSystem:
fileSystem
,
logger:
logger
,
processManager:
processManager
,
usage:
Mock
Usage
(),
usage:
Test
Usage
(),
platform:
FakePlatform
(
environment:
const
<
String
,
String
>{},
),
...
...
@@ -238,7 +238,7 @@ void main() {
fileSystem:
fileSystem
,
logger:
logger
,
processManager:
processManager
,
usage:
Mock
Usage
(),
usage:
Test
Usage
(),
platform:
FakePlatform
(
environment:
const
<
String
,
String
>{},
),
...
...
@@ -279,7 +279,7 @@ void main() {
fileSystem:
fileSystem
,
logger:
logger
,
processManager:
processManager
,
usage:
Mock
Usage
(),
usage:
Test
Usage
(),
platform:
FakePlatform
(
environment:
const
<
String
,
String
>{},
),
...
...
@@ -304,7 +304,7 @@ void main() {
fileSystem:
MockFileSystem
(),
logger:
logger
,
processManager:
processMock
,
usage:
Mock
Usage
(),
usage:
Test
Usage
(),
platform:
FakePlatform
(
environment:
const
<
String
,
String
>{},
),
...
...
@@ -374,7 +374,7 @@ void main() {
platform:
FakePlatform
(
environment:
const
<
String
,
String
>{}),
fileSystem:
MockFileSystem
(),
logger:
logger
,
usage:
Mock
Usage
(),
usage:
Test
Usage
(),
botDetector:
const
BotDetectorAlwaysNo
(),
processManager:
MockProcessManager
(
66
,
stderr:
'err1
\n
err2
\n
err3
\n
'
,
stdout:
'out1
\n
out2
\n
out3
\n
'
),
);
...
...
@@ -403,7 +403,7 @@ void main() {
final
MockFileSystem
fsMock
=
MockFileSystem
();
final
Pub
pub
=
Pub
(
platform:
FakePlatform
(
environment:
const
<
String
,
String
>{}),
usage:
Mock
Usage
(),
usage:
Test
Usage
(),
fileSystem:
fsMock
,
logger:
BufferLogger
.
test
(),
processManager:
processMock
,
...
...
@@ -432,7 +432,7 @@ void main() {
fileSystem:
MockFileSystem
(),
logger:
BufferLogger
.
test
(),
processManager:
processMock
,
usage:
Mock
Usage
(),
usage:
Test
Usage
(),
botDetector:
const
BotDetectorAlwaysNo
(),
platform:
FakePlatform
(
environment:
const
<
String
,
String
>{
...
...
@@ -461,7 +461,7 @@ void main() {
testWithoutContext
(
'analytics sent on success'
,
()
async
{
final
FileSystem
fileSystem
=
MemoryFileSystem
.
test
();
final
MockUsage
usage
=
Mock
Usage
();
final
TestUsage
usage
=
Test
Usage
();
final
Pub
pub
=
Pub
(
fileSystem:
fileSystem
,
logger:
BufferLogger
.
test
(),
...
...
@@ -484,13 +484,14 @@ void main() {
context:
PubContext
.
flutterTests
,
generateSyntheticPackage:
true
,
);
verify
(
usage
.
sendEvent
(
'pub-result'
,
'flutter-tests'
,
label:
'success'
)).
called
(
1
);
expect
(
usage
.
events
,
contains
(
const
TestUsageEvent
(
'pub-result'
,
'flutter-tests'
,
label:
'success'
),
));
});
testWithoutContext
(
'package_config_subset file is generated from packages and not timestamp'
,
()
async
{
final
FileSystem
fileSystem
=
MemoryFileSystem
.
test
();
final
MockUsage
usage
=
Mock
Usage
();
final
TestUsage
usage
=
Test
Usage
();
final
Pub
pub
=
Pub
(
fileSystem:
fileSystem
,
logger:
BufferLogger
.
test
(),
...
...
@@ -536,7 +537,7 @@ void main() {
testWithoutContext
(
'analytics sent on failure'
,
()
async
{
MockDirectory
.
findCache
=
true
;
final
MockUsage
usage
=
Mock
Usage
();
final
TestUsage
usage
=
Test
Usage
();
final
Pub
pub
=
Pub
(
usage:
usage
,
fileSystem:
MockFileSystem
(),
...
...
@@ -555,11 +556,13 @@ void main() {
// Ignore.
}
verify
(
usage
.
sendEvent
(
'pub-result'
,
'flutter-tests'
,
label:
'failure'
)).
called
(
1
);
expect
(
usage
.
events
,
contains
(
const
TestUsageEvent
(
'pub-result'
,
'flutter-tests'
,
label:
'failure'
),
));
});
testWithoutContext
(
'analytics sent on failed version solve'
,
()
async
{
final
MockUsage
usage
=
Mock
Usage
();
final
TestUsage
usage
=
Test
Usage
();
final
FileSystem
fileSystem
=
MemoryFileSystem
.
test
();
final
Pub
pub
=
Pub
(
fileSystem:
fileSystem
,
...
...
@@ -584,7 +587,9 @@ void main() {
// Ignore.
}
verify
(
usage
.
sendEvent
(
'pub-result'
,
'flutter-tests'
,
label:
'version-solving-failed'
)).
called
(
1
);
expect
(
usage
.
events
,
contains
(
const
TestUsageEvent
(
'pub-result'
,
'flutter-tests'
,
label:
'version-solving-failed'
),
));
});
testWithoutContext
(
'Pub error handling'
,
()
async
{
...
...
@@ -633,7 +638,7 @@ void main() {
),
]);
final
Pub
pub
=
Pub
(
usage:
Mock
Usage
(),
usage:
Test
Usage
(),
fileSystem:
fileSystem
,
logger:
logger
,
processManager:
processManager
,
...
...
@@ -763,5 +768,3 @@ class MockDirectory implements Directory {
}
class
MockRandomAccessFile
extends
Mock
implements
RandomAccessFile
{}
class
MockUsage
extends
Mock
implements
Usage
{}
packages/flutter_tools/test/general.shard/ios/ios_project_migration_test.dart
View file @
6ecb8cbc
...
...
@@ -23,9 +23,9 @@ import '../../src/common.dart';
void
main
(
)
{
group
(
'iOS migration'
,
()
{
MockUsage
mock
Usage
;
TestUsage
test
Usage
;
setUp
(()
{
mockUsage
=
Mock
Usage
();
testUsage
=
Test
Usage
();
});
testWithoutContext
(
'migrators succeed'
,
()
{
...
...
@@ -61,10 +61,10 @@ void main () {
mockIosProject
,
testLogger
,
mockXcode
,
mock
Usage
test
Usage
);
expect
(
iosProjectMigration
.
migrate
(),
isTrue
);
verifyNever
(
mockUsage
.
sendEvent
(
any
,
any
,
label:
anyNamed
(
'label'
),
value:
anyNamed
(
'value'
))
);
expect
(
testUsage
.
events
,
isEmpty
);
expect
(
xcodeProjectInfoFile
.
existsSync
(),
isFalse
);
...
...
@@ -81,10 +81,10 @@ void main () {
mockIosProject
,
testLogger
,
mockXcode
,
mock
Usage
,
test
Usage
,
);
expect
(
iosProjectMigration
.
migrate
(),
isTrue
);
verifyNever
(
mockUsage
.
sendEvent
(
any
,
any
,
label:
anyNamed
(
'label'
),
value:
anyNamed
(
'value'
))
);
expect
(
testUsage
.
events
,
isEmpty
);
expect
(
xcodeProjectInfoFile
.
lastModifiedSync
(),
projectLastModified
);
expect
(
xcodeProjectInfoFile
.
readAsStringSync
(),
contents
);
...
...
@@ -102,7 +102,7 @@ shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.
mockIosProject
,
testLogger
,
mockXcode
,
mock
Usage
,
test
Usage
,
);
expect
(
iosProjectMigration
.
migrate
(),
isTrue
);
expect
(
xcodeProjectInfoFile
.
readAsStringSync
(),
contents
);
...
...
@@ -130,10 +130,10 @@ keep this 2
mockIosProject
,
testLogger
,
mockXcode
,
mock
Usage
,
test
Usage
,
);
expect
(
iosProjectMigration
.
migrate
(),
isTrue
);
verifyNever
(
mockUsage
.
sendEvent
(
any
,
any
,
label:
anyNamed
(
'label'
),
value:
anyNamed
(
'value'
))
);
expect
(
testUsage
.
events
,
isEmpty
);
expect
(
xcodeProjectInfoFile
.
readAsStringSync
(),
r''
'
keep this 1
...
...
@@ -154,11 +154,13 @@ keep this 2
mockIosProject
,
testLogger
,
mockXcode
,
mock
Usage
,
test
Usage
,
);
expect
(
iosProjectMigration
.
migrate
,
throwsToolExit
(
message:
'Your Xcode project requires migration'
));
verify
(
mockUsage
.
sendEvent
(
'ios-migration'
,
'remove-frameworks'
,
label:
'failure'
,
value:
null
));
expect
(
testUsage
.
events
,
contains
(
const
TestUsageEvent
(
'ios-migration'
,
'remove-frameworks'
,
label:
'failure'
),
));
});
testWithoutContext
(
'migration fails with leftover Flutter.framework reference'
,
()
{
...
...
@@ -172,10 +174,12 @@ keep this 2
mockIosProject
,
testLogger
,
mockXcode
,
mock
Usage
,
test
Usage
,
);
expect
(
iosProjectMigration
.
migrate
,
throwsToolExit
(
message:
'Your Xcode project requires migration'
));
verify
(
mockUsage
.
sendEvent
(
'ios-migration'
,
'remove-frameworks'
,
label:
'failure'
,
value:
null
));
expect
(
testUsage
.
events
,
contains
(
const
TestUsageEvent
(
'ios-migration'
,
'remove-frameworks'
,
label:
'failure'
),
));
});
testWithoutContext
(
'migration fails without Xcode installed'
,
()
{
...
...
@@ -188,10 +192,12 @@ keep this 2
mockIosProject
,
testLogger
,
mockXcode
,
mock
Usage
,
test
Usage
,
);
expect
(
iosProjectMigration
.
migrate
,
throwsToolExit
(
message:
'Your Xcode project requires migration'
));
verify
(
mockUsage
.
sendEvent
(
'ios-migration'
,
'remove-frameworks'
,
label:
'failure'
,
value:
null
));
expect
(
testUsage
.
events
,
contains
(
const
TestUsageEvent
(
'ios-migration'
,
'remove-frameworks'
,
label:
'failure'
),
));
});
testWithoutContext
(
'migration fails on Xcode < 11.4'
,
()
{
...
...
@@ -205,10 +211,10 @@ keep this 2
mockIosProject
,
testLogger
,
mockXcode
,
mock
Usage
,
test
Usage
,
);
expect
(
iosProjectMigration
.
migrate
(),
isTrue
);
verifyNever
(
mockUsage
.
sendEvent
(
any
,
any
,
label:
anyNamed
(
'label'
),
value:
anyNamed
(
'value'
))
);
expect
(
testUsage
.
events
,
isEmpty
);
expect
(
testLogger
.
errorText
,
isEmpty
);
});
...
...
@@ -223,10 +229,12 @@ keep this 2
mockIosProject
,
testLogger
,
mockXcode
,
mock
Usage
,
test
Usage
,
);
expect
(
iosProjectMigration
.
migrate
,
throwsToolExit
(
message:
'Your Xcode project requires migration'
));
verify
(
mockUsage
.
sendEvent
(
'ios-migration'
,
'remove-frameworks'
,
label:
'failure'
,
value:
null
));
expect
(
testUsage
.
events
,
contains
(
const
TestUsageEvent
(
'ios-migration'
,
'remove-frameworks'
,
label:
'failure'
),
));
});
testWithoutContext
(
'migration fails on Xcode 12,0'
,
()
{
...
...
@@ -240,10 +248,12 @@ keep this 2
mockIosProject
,
testLogger
,
mockXcode
,
mock
Usage
,
test
Usage
,
);
expect
(
iosProjectMigration
.
migrate
,
throwsToolExit
(
message:
'Your Xcode project requires migration'
));
verify
(
mockUsage
.
sendEvent
(
'ios-migration'
,
'remove-frameworks'
,
label:
'failure'
,
value:
null
));
expect
(
testUsage
.
events
,
contains
(
const
TestUsageEvent
(
'ios-migration'
,
'remove-frameworks'
,
label:
'failure'
),
));
});
});
...
...
@@ -556,7 +566,6 @@ keep this 3
class
MockIosProject
extends
Mock
implements
IosProject
{}
class
MockXcode
extends
Mock
implements
Xcode
{}
class
MockUsage
extends
Mock
implements
Usage
{}
class
FakeIOSMigrator
extends
ProjectMigrator
{
FakeIOSMigrator
({
@required
this
.
succeeds
})
...
...
packages/flutter_tools/test/general.shard/ios/mac_test.dart
View file @
6ecb8cbc
...
...
@@ -129,13 +129,13 @@ void main() {
group
(
'Diagnose Xcode build failure'
,
()
{
Map
<
String
,
String
>
buildSettings
;
MockUsage
mock
Usage
;
TestUsage
test
Usage
;
setUp
(()
{
buildSettings
=
<
String
,
String
>{
'PRODUCT_BUNDLE_IDENTIFIER'
:
'test.app'
,
};
mockUsage
=
Mock
Usage
();
testUsage
=
Test
Usage
();
});
testUsingContext
(
'Sends analytics when bitcode fails'
,
()
async
{
...
...
@@ -151,14 +151,18 @@ void main() {
),
);
await
diagnoseXcodeBuildFailure
(
buildResult
,
mockUsage
,
logger
);
verify
(
mockUsage
.
sendEvent
(
'build'
,
any
,
label:
'xcode-bitcode-failure'
,
parameters:
<
String
,
String
>{
cdKey
(
CustomDimensions
.
buildEventCommand
):
buildCommands
.
toString
(),
cdKey
(
CustomDimensions
.
buildEventSettings
):
buildSettings
.
toString
(),
})).
called
(
1
);
await
diagnoseXcodeBuildFailure
(
buildResult
,
testUsage
,
logger
);
expect
(
testUsage
.
events
,
contains
(
TestUsageEvent
(
'build'
,
'unspecified'
,
label:
'xcode-bitcode-failure'
,
parameters:
<
String
,
String
>{
cdKey
(
CustomDimensions
.
buildEventCommand
):
buildCommands
.
toString
(),
cdKey
(
CustomDimensions
.
buildEventSettings
):
buildSettings
.
toString
(),
},
),
));
});
testUsingContext
(
'No provisioning profile shows message'
,
()
async
{
...
...
@@ -227,7 +231,7 @@ Error launching application on iPhone.''',
),
);
await diagnoseXcodeBuildFailure(buildResult,
mock
Usage, logger);
await diagnoseXcodeBuildFailure(buildResult,
test
Usage, logger);
expect(
logger.errorText,
contains("No Provisioning Profile was found for your project'
s
Bundle
Identifier
or
your
\
ndevice
.
"),
...
...
@@ -308,7 +312,7 @@ Could not build the precompiled application for the device.''',
),
);
await diagnoseXcodeBuildFailure(buildResult,
mock
Usage, logger);
await diagnoseXcodeBuildFailure(buildResult,
test
Usage, logger);
expect(
logger.errorText,
contains('Building a deployable iOS app requires a selected Development Team with a
\n
Provisioning Profile.'),
...
...
@@ -345,7 +349,7 @@ Exited (sigterm)''',
),
);
await diagnoseXcodeBuildFailure(buildResult,
mock
Usage, logger);
await diagnoseXcodeBuildFailure(buildResult,
test
Usage, logger);
expect(
logger.errorText,
contains('Your Xcode project requires migration.'),
...
...
@@ -382,7 +386,7 @@ Exited (sigterm)''',
),
);
await diagnoseXcodeBuildFailure(buildResult,
mock
Usage, logger);
await diagnoseXcodeBuildFailure(buildResult,
test
Usage, logger);
expect(
logger.errorText,
contains('Your Xcode project requires migration.'),
...
...
@@ -480,5 +484,3 @@ Exited (sigterm)''',
});
});
}
class MockUsage extends Mock implements Usage {}
packages/flutter_tools/test/general.shard/macos/macos_project_migration_test.dart
View file @
6ecb8cbc
...
...
@@ -19,14 +19,14 @@ import 'package:mockito/mockito.dart';
import
'../../src/common.dart'
;
void
main
(
)
{
MockUsage
mock
Usage
;
TestUsage
test
Usage
;
MemoryFileSystem
memoryFileSystem
;
BufferLogger
testLogger
;
MockMacOSProject
mockMacOSProject
;
File
xcodeProjectInfoFile
;
setUp
(()
{
mockUsage
=
Mock
Usage
();
testUsage
=
Test
Usage
();
memoryFileSystem
=
MemoryFileSystem
.
test
();
xcodeProjectInfoFile
=
memoryFileSystem
.
file
(
'project.pbxproj'
);
...
...
@@ -48,15 +48,10 @@ void main() {
RemoveMacOSFrameworkLinkAndEmbeddingMigration
(
mockMacOSProject
,
testLogger
,
mock
Usage
,
test
Usage
,
);
expect
(
macosProjectMigration
.
migrate
(),
isTrue
);
verifyNever
(
mockUsage
.
sendEvent
(
any
,
any
,
label:
anyNamed
(
'label'
),
value:
anyNamed
(
'value'
),
));
expect
(
testUsage
.
events
,
isEmpty
);
expect
(
xcodeProjectInfoFile
.
existsSync
(),
isFalse
);
...
...
@@ -77,15 +72,10 @@ void main() {
RemoveMacOSFrameworkLinkAndEmbeddingMigration
(
mockMacOSProject
,
testLogger
,
mock
Usage
,
test
Usage
,
);
expect
(
macosProjectMigration
.
migrate
(),
isTrue
);
verifyNever
(
mockUsage
.
sendEvent
(
any
,
any
,
label:
anyNamed
(
'label'
),
value:
anyNamed
(
'value'
),
));
expect
(
testUsage
.
events
,
isEmpty
);
expect
(
xcodeProjectInfoFile
.
lastModifiedSync
(),
projectLastModified
);
expect
(
xcodeProjectInfoFile
.
readAsStringSync
(),
contents
);
...
...
@@ -103,7 +93,7 @@ shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.
RemoveMacOSFrameworkLinkAndEmbeddingMigration
(
mockMacOSProject
,
testLogger
,
mock
Usage
,
test
Usage
,
);
expect
(
macosProjectMigration
.
migrate
(),
isTrue
);
expect
(
xcodeProjectInfoFile
.
readAsStringSync
(),
contents
);
...
...
@@ -126,15 +116,10 @@ keep this 2
RemoveMacOSFrameworkLinkAndEmbeddingMigration
(
mockMacOSProject
,
testLogger
,
mock
Usage
,
test
Usage
,
);
expect
(
macosProjectMigration
.
migrate
(),
isTrue
);
verifyNever
(
mockUsage
.
sendEvent
(
any
,
any
,
label:
anyNamed
(
'label'
),
value:
anyNamed
(
'value'
),
));
expect
(
testUsage
.
events
,
isEmpty
);
expect
(
xcodeProjectInfoFile
.
readAsStringSync
(),
r''
'
keep this 1
...
...
@@ -154,13 +139,14 @@ keep this 2
RemoveMacOSFrameworkLinkAndEmbeddingMigration
(
mockMacOSProject
,
testLogger
,
mock
Usage
,
test
Usage
,
);
expect
(
macosProjectMigration
.
migrate
,
throwsToolExit
(
message:
'Your Xcode project requires migration'
));
verify
(
mockUsage
.
sendEvent
(
'macos-migration'
,
'remove-frameworks'
,
label:
'failure'
,
value:
null
));
expect
(
testUsage
.
events
,
contains
(
const
TestUsageEvent
(
'macos-migration'
,
'remove-frameworks'
,
label:
'failure'
),
));
});
testWithoutContext
(
...
...
@@ -173,19 +159,18 @@ keep this 2
RemoveMacOSFrameworkLinkAndEmbeddingMigration
(
mockMacOSProject
,
testLogger
,
mock
Usage
,
test
Usage
,
);
expect
(
macosProjectMigration
.
migrate
,
throwsToolExit
(
message:
'Your Xcode project requires migration'
));
verify
(
mockUsage
.
sendEvent
(
'macos-migration'
,
'remove-frameworks'
,
label:
'failure'
,
value:
null
));
expect
(
testUsage
.
events
,
contains
(
const
TestUsageEvent
(
'macos-migration'
,
'remove-frameworks'
,
label:
'failure'
),
));
});
}
class
MockMacOSProject
extends
Mock
implements
MacOSProject
{}
class
MockUsage
extends
Mock
implements
Usage
{}
class
FakeMacOSMigrator
extends
ProjectMigrator
{
FakeMacOSMigrator
({
@required
this
.
succeeds
})
:
super
(
null
);
...
...
packages/flutter_tools/test/general.shard/reporting/events_test.dart
View file @
6ecb8cbc
...
...
@@ -7,14 +7,13 @@
import
'package:flutter_tools/src/build_info.dart'
;
import
'package:flutter_tools/src/doctor.dart'
;
import
'package:flutter_tools/src/reporting/reporting.dart'
;
import
'package:mockito/mockito.dart'
;
import
'package:package_config/package_config.dart'
;
import
'../../src/common.dart'
;
void
main
(
)
{
testWithoutContext
(
'DoctorResultEvent sends usage event for each sub validator'
,
()
async
{
final
Usage
usage
=
Mock
Usage
();
final
TestUsage
usage
=
Test
Usage
();
final
GroupedValidator
groupedValidator
=
FakeGroupedValidator
(<
DoctorValidator
>[
FakeDoctorValidator
(
'a'
),
FakeDoctorValidator
(
'b'
),
...
...
@@ -29,14 +28,16 @@ void main() {
);
expect
(
doctorResultEvent
.
send
,
returnsNormally
);
verify
(
usage
.
sendEvent
(
'doctor-result'
,
any
,
label:
anyNamed
(
'label'
))).
called
(
3
);
expect
(
usage
.
events
.
length
,
3
);
expect
(
usage
.
events
,
contains
(
const
TestUsageEvent
(
'doctor-result'
,
'FakeDoctorValidator'
,
label:
'crash'
),
));
});
testWithoutContext
(
'DoctorResultEvent does not crash if a synthetic crash result was used instead'
' of validation. This happens when a grouped validator throws an exception, causing subResults to never '
' be instantiated.'
,
()
async
{
final
Usage
usage
=
Mock
Usage
();
final
TestUsage
usage
=
Test
Usage
();
final
GroupedValidator
groupedValidator
=
FakeGroupedValidator
(<
DoctorValidator
>[
FakeDoctorValidator
(
'a'
),
FakeDoctorValidator
(
'b'
),
...
...
@@ -52,11 +53,14 @@ void main() {
expect
(
doctorResultEvent
.
send
,
returnsNormally
);
verify
(
usage
.
sendEvent
(
'doctor-result'
,
any
,
label:
anyNamed
(
'label'
))).
called
(
1
);
expect
(
usage
.
events
.
length
,
1
);
expect
(
usage
.
events
,
contains
(
const
TestUsageEvent
(
'doctor-result'
,
'FakeGroupedValidator'
,
label:
'crash'
),
));
});
testWithoutContext
(
'Reports null safe analytics events'
,
()
{
final
Usage
usage
=
Mock
Usage
();
final
TestUsage
usage
=
Test
Usage
();
final
PackageConfig
packageConfig
=
PackageConfig
(<
Package
>[
Package
(
'foo'
,
Uri
.
parse
(
'file:///foo/'
),
languageVersion:
LanguageVersion
(
2
,
12
)),
Package
(
'bar'
,
Uri
.
parse
(
'file:///fizz/'
),
languageVersion:
LanguageVersion
(
2
,
1
)),
...
...
@@ -70,15 +74,17 @@ void main() {
usage
,
).
send
();
verify
(
usage
.
sendEvent
(
NullSafetyAnalysisEvent
.
kNullSafetyCategory
,
'runtime-mode'
,
label:
'NullSafetyMode.sound'
)).
called
(
1
);
verify
(
usage
.
sendEvent
(
NullSafetyAnalysisEvent
.
kNullSafetyCategory
,
'stats'
,
parameters:
<
String
,
String
>{
expect
(
usage
.
events
,
unorderedEquals
(<
TestUsageEvent
>[
const
TestUsageEvent
(
NullSafetyAnalysisEvent
.
kNullSafetyCategory
,
'runtime-mode'
,
label:
'NullSafetyMode.sound'
),
const
TestUsageEvent
(
NullSafetyAnalysisEvent
.
kNullSafetyCategory
,
'stats'
,
parameters:
<
String
,
String
>{
'cd49'
:
'1'
,
'cd50'
:
'3'
,
})).
called
(
1
);
verify
(
usage
.
sendEvent
(
NullSafetyAnalysisEvent
.
kNullSafetyCategory
,
'language-version'
,
label:
'2.12'
)).
called
(
1
);
}),
const
TestUsageEvent
(
NullSafetyAnalysisEvent
.
kNullSafetyCategory
,
'language-version'
,
label:
'2.12'
),
]));
});
testWithoutContext
(
'Does not crash if main package is missing'
,
()
{
final
Usage
usage
=
Mock
Usage
();
final
TestUsage
usage
=
Test
Usage
();
final
PackageConfig
packageConfig
=
PackageConfig
(<
Package
>[
Package
(
'foo'
,
Uri
.
parse
(
'file:///foo/lib/'
),
languageVersion:
LanguageVersion
(
2
,
12
)),
Package
(
'bar'
,
Uri
.
parse
(
'file:///fizz/lib/'
),
languageVersion:
LanguageVersion
(
2
,
1
)),
...
...
@@ -92,15 +98,16 @@ void main() {
usage
,
).
send
();
verify
(
usage
.
sendEvent
(
NullSafetyAnalysisEvent
.
kNullSafetyCategory
,
'runtime-mode'
,
label:
'NullSafetyMode.sound'
)).
called
(
1
);
verify
(
usage
.
sendEvent
(
NullSafetyAnalysisEvent
.
kNullSafetyCategory
,
'stats'
,
parameters:
<
String
,
String
>{
'cd49'
:
'1'
,
'cd50'
:
'3'
,
})).
called
(
1
);
verifyNever
(
usage
.
sendEvent
(
NullSafetyAnalysisEvent
.
kNullSafetyCategory
,
'language-version'
,
label:
anyNamed
(
'label'
)));
expect
(
usage
.
events
,
unorderedEquals
(<
TestUsageEvent
>[
const
TestUsageEvent
(
NullSafetyAnalysisEvent
.
kNullSafetyCategory
,
'runtime-mode'
,
label:
'NullSafetyMode.sound'
),
const
TestUsageEvent
(
NullSafetyAnalysisEvent
.
kNullSafetyCategory
,
'stats'
,
parameters:
<
String
,
String
>{
'cd49'
:
'1'
,
'cd50'
:
'3'
,
}),
]));
});
testWithoutContext
(
'a null language version is treated as unmigrated'
,
()
{
final
Usage
usage
=
Mock
Usage
();
final
TestUsage
usage
=
Test
Usage
();
final
PackageConfig
packageConfig
=
PackageConfig
(<
Package
>[
Package
(
'foo'
,
Uri
.
parse
(
'file:///foo/lib/'
),
languageVersion:
null
),
]);
...
...
@@ -112,11 +119,12 @@ void main() {
usage
,
).
send
();
verify
(
usage
.
sendEvent
(
NullSafetyAnalysisEvent
.
kNullSafetyCategory
,
'runtime-mode'
,
label:
'NullSafetyMode.sound'
)).
called
(
1
);
verify
(
usage
.
sendEvent
(
NullSafetyAnalysisEvent
.
kNullSafetyCategory
,
'stats'
,
parameters:
<
String
,
String
>{
'cd49'
:
'0'
,
'cd50'
:
'1'
,
})).
called
(
1
);
verifyNever
(
usage
.
sendEvent
(
NullSafetyAnalysisEvent
.
kNullSafetyCategory
,
'language-version'
,
label:
anyNamed
(
'label'
)));
expect
(
usage
.
events
,
unorderedEquals
(<
TestUsageEvent
>[
const
TestUsageEvent
(
NullSafetyAnalysisEvent
.
kNullSafetyCategory
,
'runtime-mode'
,
label:
'NullSafetyMode.sound'
),
const
TestUsageEvent
(
NullSafetyAnalysisEvent
.
kNullSafetyCategory
,
'stats'
,
parameters:
<
String
,
String
>{
'cd49'
:
'0'
,
'cd50'
:
'1'
,
}),
]));
});
}
...
...
@@ -132,5 +140,3 @@ class FakeDoctorValidator extends DoctorValidator {
return
ValidationResult
.
crash
(
Object
());
}
}
class
MockUsage
extends
Mock
implements
Usage
{}
packages/flutter_tools/test/general.shard/resident_runner_test.dart
View file @
6ecb8cbc
...
...
@@ -546,16 +546,18 @@ void main() {
final
OperationResult
result
=
await
residentRunner
.
restart
(
fullRestart:
false
);
expect
(
result
.
fatal
,
true
);
expect
(
result
.
code
,
1
);
verify
(
globals
.
flutterUsage
.
sendEvent
(
'hot'
,
'exception'
,
parameters:
<
String
,
String
>{
cdKey
(
CustomDimensions
.
hotEventTargetPlatform
):
expect
((
globals
.
flutterUsage
as
TestUsage
).
events
,
contains
(
TestUsageEvent
(
'hot'
,
'exception'
,
parameters:
<
String
,
String
>{
cdKey
(
CustomDimensions
.
hotEventTargetPlatform
):
getNameForTargetPlatform
(
TargetPlatform
.
android_arm
),
cdKey
(
CustomDimensions
.
hotEventSdkName
):
'Example'
,
cdKey
(
CustomDimensions
.
hotEventEmulator
):
'false'
,
cdKey
(
CustomDimensions
.
hotEventFullRestart
):
'false'
,
})).
called
(
1
);
cdKey
(
CustomDimensions
.
hotEventSdkName
):
'Example'
,
cdKey
(
CustomDimensions
.
hotEventEmulator
):
'false'
,
cdKey
(
CustomDimensions
.
hotEventFullRestart
):
'false'
,
}),
));
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
);
},
overrides:
<
Type
,
Generator
>{
Usage:
()
=>
Mock
Usage
(),
Usage:
()
=>
Test
Usage
(),
}),
overrides:
<
Type
,
Generator
>{
DevtoolsLauncher:
()
=>
mockDevtoolsLauncher
,
});
...
...
@@ -633,16 +635,19 @@ void main() {
expect
(
result
.
fatal
,
true
);
expect
(
result
.
code
,
kIsolateReloadBarred
);
expect
(
result
.
message
,
contains
(
'Unable to hot reload application due to an unrecoverable error'
));
verify
(
globals
.
flutterUsage
.
sendEvent
(
'hot'
,
'reload-barred'
,
parameters:
<
String
,
String
>{
cdKey
(
CustomDimensions
.
hotEventTargetPlatform
):
expect
((
globals
.
flutterUsage
as
TestUsage
).
events
,
contains
(
TestUsageEvent
(
'hot'
,
'reload-barred'
,
parameters:
<
String
,
String
>{
cdKey
(
CustomDimensions
.
hotEventTargetPlatform
):
getNameForTargetPlatform
(
TargetPlatform
.
android_arm
),
cdKey
(
CustomDimensions
.
hotEventSdkName
):
'Example'
,
cdKey
(
CustomDimensions
.
hotEventEmulator
):
'false'
,
cdKey
(
CustomDimensions
.
hotEventFullRestart
):
'false'
,
})).
called
(
1
);
cdKey
(
CustomDimensions
.
hotEventSdkName
):
'Example'
,
cdKey
(
CustomDimensions
.
hotEventEmulator
):
'false'
,
cdKey
(
CustomDimensions
.
hotEventFullRestart
):
'false'
,
}),
));
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
);
},
overrides:
<
Type
,
Generator
>{
Usage:
()
=>
Mock
Usage
(),
Usage:
()
=>
Test
Usage
(),
}),
overrides:
<
Type
,
Generator
>{
DevtoolsLauncher:
()
=>
mockDevtoolsLauncher
,
});
...
...
@@ -700,17 +705,20 @@ void main() {
final
OperationResult
result
=
await
residentRunner
.
restart
(
fullRestart:
false
);
expect
(
result
.
fatal
,
true
);
expect
(
result
.
code
,
1
);
verify
(
globals
.
flutterUsage
.
sendEvent
(
'hot'
,
'exception'
,
parameters:
<
String
,
String
>{
cdKey
(
CustomDimensions
.
hotEventTargetPlatform
):
expect
((
globals
.
flutterUsage
as
TestUsage
).
events
,
contains
(
TestUsageEvent
(
'hot'
,
'exception'
,
parameters:
<
String
,
String
>{
cdKey
(
CustomDimensions
.
hotEventTargetPlatform
):
getNameForTargetPlatform
(
TargetPlatform
.
android_arm
),
cdKey
(
CustomDimensions
.
hotEventSdkName
):
'Example'
,
cdKey
(
CustomDimensions
.
hotEventEmulator
):
'false'
,
cdKey
(
CustomDimensions
.
hotEventFullRestart
):
'false'
,
})).
called
(
1
);
cdKey
(
CustomDimensions
.
hotEventSdkName
):
'Example'
,
cdKey
(
CustomDimensions
.
hotEventEmulator
):
'false'
,
cdKey
(
CustomDimensions
.
hotEventFullRestart
):
'false'
,
}),
));
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
);
},
overrides:
<
Type
,
Generator
>{
DevtoolsLauncher:
()
=>
mockDevtoolsLauncher
,
Usage:
()
=>
Mock
Usage
(),
Usage:
()
=>
Test
Usage
(),
}));
testUsingContext
(
'ResidentRunner does not reload sources if no sources changed'
,
()
=>
testbed
.
run
(()
async
{
...
...
@@ -1021,13 +1029,16 @@ void main() {
final
OperationResult
result
=
await
residentRunner
.
restart
(
fullRestart:
false
);
expect
(
result
.
fatal
,
false
);
expect
(
result
.
code
,
0
);
expect
(
verify
(
globals
.
flutterUsage
.
sendEvent
(
'hot'
,
'reload'
,
parameters:
captureAnyNamed
(
'parameters'
))).
captured
[
0
],
containsPair
(
cdKey
(
CustomDimensions
.
hotEventTargetPlatform
),
getNameForTargetPlatform
(
TargetPlatform
.
android_arm
)),
);
final
TestUsageEvent
event
=
(
globals
.
flutterUsage
as
TestUsage
).
events
.
first
;
expect
(
event
.
category
,
'hot'
);
expect
(
event
.
parameter
,
'reload'
);
expect
(
event
.
parameters
,
containsPair
(
cdKey
(
CustomDimensions
.
hotEventTargetPlatform
),
getNameForTargetPlatform
(
TargetPlatform
.
android_arm
),
));
},
overrides:
<
Type
,
Generator
>{
Usage:
()
=>
Mock
Usage
(),
Usage:
()
=>
Test
Usage
(),
}),
overrides:
<
Type
,
Generator
>{
DevtoolsLauncher:
()
=>
mockDevtoolsLauncher
,
});
...
...
@@ -1134,15 +1145,18 @@ void main() {
expect
(
result
.
fatal
,
false
);
expect
(
result
.
code
,
0
);
verify
(
globals
.
flutterUsage
.
sendEvent
(
'hot'
,
'reload'
,
parameters:
argThat
(
containsPair
(
'cd48'
,
'true'
),
named:
'parameters'
,
))).
called
(
1
);
final
TestUsageEvent
event
=
(
globals
.
flutterUsage
as
TestUsage
).
events
.
first
;
expect
(
event
.
category
,
'hot'
);
expect
(
event
.
parameter
,
'reload'
);
expect
(
event
.
parameters
,
containsPair
(
cdKey
(
CustomDimensions
.
fastReassemble
),
'true'
,
));
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
MemoryFileSystem
.
test
(),
Platform:
()
=>
FakePlatform
(
operatingSystem:
'linux'
),
ProjectFileInvalidator:
()
=>
FakeProjectFileInvalidator
(),
Usage:
()
=>
Mock
Usage
(),
Usage:
()
=>
Test
Usage
(),
FeatureFlags:
()
=>
TestFeatureFlags
(
isSingleWidgetReloadEnabled:
true
),
}),
overrides:
<
Type
,
Generator
>{
DevtoolsLauncher:
()
=>
mockDevtoolsLauncher
,
...
...
@@ -1208,14 +1222,16 @@ void main() {
final
OperationResult
result
=
await
residentRunner
.
restart
(
fullRestart:
true
);
expect
(
result
.
fatal
,
false
);
expect
(
result
.
code
,
0
);
expect
(
verify
(
globals
.
flutterUsage
.
sendEvent
(
'hot'
,
'restart'
,
parameters:
captureAnyNamed
(
'parameters'
))).
captured
[
0
],
containsPair
(
cdKey
(
CustomDimensions
.
hotEventTargetPlatform
),
getNameForTargetPlatform
(
TargetPlatform
.
android_arm
)),
);
final
TestUsageEvent
event
=
(
globals
.
flutterUsage
as
TestUsage
).
events
.
first
;
expect
(
event
.
category
,
'hot'
);
expect
(
event
.
parameter
,
'restart'
);
expect
(
event
.
parameters
,
containsPair
(
cdKey
(
CustomDimensions
.
hotEventTargetPlatform
),
getNameForTargetPlatform
(
TargetPlatform
.
android_arm
),
));
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
);
},
overrides:
<
Type
,
Generator
>{
Usage:
()
=>
Mock
Usage
(),
Usage:
()
=>
Test
Usage
(),
}),
overrides:
<
Type
,
Generator
>{
DevtoolsLauncher:
()
=>
mockDevtoolsLauncher
,
});
...
...
@@ -1473,16 +1489,19 @@ void main() {
final
OperationResult
result
=
await
residentRunner
.
restart
(
fullRestart:
true
);
expect
(
result
.
fatal
,
true
);
expect
(
result
.
code
,
1
);
verify
(
globals
.
flutterUsage
.
sendEvent
(
'hot'
,
'exception'
,
parameters:
<
String
,
String
>{
cdKey
(
CustomDimensions
.
hotEventTargetPlatform
):
expect
((
globals
.
flutterUsage
as
TestUsage
).
events
,
contains
(
TestUsageEvent
(
'hot'
,
'exception'
,
parameters:
<
String
,
String
>{
cdKey
(
CustomDimensions
.
hotEventTargetPlatform
):
getNameForTargetPlatform
(
TargetPlatform
.
android_arm
),
cdKey
(
CustomDimensions
.
hotEventSdkName
):
'Example'
,
cdKey
(
CustomDimensions
.
hotEventEmulator
):
'false'
,
cdKey
(
CustomDimensions
.
hotEventFullRestart
):
'true'
,
})).
called
(
1
);
cdKey
(
CustomDimensions
.
hotEventSdkName
):
'Example'
,
cdKey
(
CustomDimensions
.
hotEventEmulator
):
'false'
,
cdKey
(
CustomDimensions
.
hotEventFullRestart
):
'true'
,
}),
));
expect
(
fakeVmServiceHost
.
hasRemainingExpectations
,
false
);
},
overrides:
<
Type
,
Generator
>{
Usage:
()
=>
Mock
Usage
(),
Usage:
()
=>
Test
Usage
(),
}),
overrides:
<
Type
,
Generator
>{
DevtoolsLauncher:
()
=>
mockDevtoolsLauncher
,
});
...
...
@@ -3134,7 +3153,6 @@ class MockDevice extends Mock implements Device {}
class
MockDeviceLogReader
extends
Mock
implements
DeviceLogReader
{}
class
MockDevicePortForwarder
extends
Mock
implements
DevicePortForwarder
{}
class
MockDevtoolsLauncher
extends
Mock
implements
DevtoolsLauncher
{}
class
MockUsage
extends
Mock
implements
Usage
{}
class
MockProcessManager
extends
Mock
implements
ProcessManager
{}
class
MockResidentCompiler
extends
Mock
implements
ResidentCompiler
{}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment