Add LICENSE file to packages/flutter, add test to make sure it… (#53799)
This adds a LICENSE file to the packages/flutter directory so that it can be found when building, and a test to make sure it exists in produced binaries.
diff --git a/dev/integration_tests/ui/lib/license_check.dart b/dev/integration_tests/ui/lib/license_check.dart
new file mode 100644
index 0000000..b226821
--- /dev/null
+++ b/dev/integration_tests/ui/lib/license_check.dart
@@ -0,0 +1,71 @@
+// 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.
+
+import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_driver/driver_extension.dart';
+
+/// This application does nothing but show a screen with the flutter package
+/// license in it.
+void main() {
+ enableFlutterDriverExtension();
+ runApp(ShowLicenses());
+}
+
+class ShowLicenses extends StatelessWidget {
+ Widget _buildTestResultWidget(
+ BuildContext context,
+ AsyncSnapshot<List<LicenseEntry>> snapshot,
+ ) {
+ final List<LicenseEntry> entries = snapshot.data;
+ String flutterPackage = '';
+ final List<String> flutterParagraphs = <String>[];
+ String enginePackage = '';
+ final List<String> engineParagraphs = <String>[];
+ for (final LicenseEntry entry in entries) {
+ if (entry.packages.contains('flutter')) {
+ flutterPackage = 'flutter';
+ flutterParagraphs.addAll(
+ entry.paragraphs.map<String>((LicenseParagraph para) => para.text),
+ );
+ }
+ if (entry.packages.contains('engine')) {
+ enginePackage = 'engine';
+ engineParagraphs.addAll(
+ entry.paragraphs.map<String>((LicenseParagraph para) => para.text),
+ );
+ }
+ }
+
+ final List<Widget> result = <Widget>[];
+ if (entries.isNotEmpty) {
+ result.addAll(<Widget>[
+ const Text('License Check Test', key: ValueKey<String>('Header')),
+ Text(flutterPackage, key: const ValueKey<String>('FlutterPackage')),
+ Text(flutterParagraphs.join(' '), key: const ValueKey<String>('FlutterLicense')),
+ Text('${flutterParagraphs.length}', key: const ValueKey<String>('FlutterCount')),
+ Text(enginePackage, key: const ValueKey<String>('EnginePackage')),
+ Text(engineParagraphs.join(' '), key: const ValueKey<String>('EngineLicense')),
+ Text('${engineParagraphs.length}', key: const ValueKey<String>('EngineCount')),
+ ]);
+ }
+
+ return ListView(
+ children: result,
+ );
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return MaterialApp(
+ home: Scaffold(
+ body: FutureBuilder<List<LicenseEntry>>(
+ initialData: const <LicenseEntry>[],
+ builder: _buildTestResultWidget,
+ future: LicenseRegistry.licenses.toList(),
+ ),
+ ),
+ );
+ }
+}
diff --git a/dev/integration_tests/ui/test_driver/license_check_test.dart b/dev/integration_tests/ui/test_driver/license_check_test.dart
new file mode 100644
index 0000000..38169a8
--- /dev/null
+++ b/dev/integration_tests/ui/test_driver/license_check_test.dart
@@ -0,0 +1,96 @@
+// 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.
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:flutter_driver/flutter_driver.dart';
+import 'package:path/path.dart' as path;
+import 'package:test/test.dart' hide TypeMatcher, isInstanceOf;
+import 'package:vm_service_client/vm_service_client.dart';
+
+// Connect and disconnect from the empty app.
+void main() {
+ // Load the license file from disk to compare it with the one in the app.
+ final File licenseFile = File(path.join('..', '..', '..', 'packages', 'flutter', 'LICENSE'));
+ if (!licenseFile.existsSync()) {
+ print('Test failed. Unable to find LICENSE file at ${licenseFile.path}');
+ exit(-1);
+ }
+ final RegExp newlineSplit = RegExp(r'\s+');
+ final String license = licenseFile.readAsStringSync().split(newlineSplit).join(' ').trim();
+
+ group('License file check', () {
+ FlutterDriver driver;
+ IsolatesWorkaround workaround;
+
+ setUpAll(() async {
+ driver = await FlutterDriver.connect();
+ workaround = IsolatesWorkaround(driver);
+ await workaround.resumeIsolates();
+ await driver.waitUntilFirstFrameRasterized();
+ });
+
+ tearDownAll(() async {
+ if (driver != null) {
+ await driver.close();
+ await workaround.tearDown();
+ }
+ });
+
+ test('flutter license', () async {
+ await driver.waitFor(find.byValueKey('Header'));
+ final String foundPackage = await driver.getText(find.byValueKey('FlutterPackage'));
+ final String foundLicense = await driver.getText(find.byValueKey('FlutterLicense'));
+ expect(foundPackage, equals('flutter'));
+ expect(foundLicense, equals(license));
+ });
+
+ test('engine license', () async {
+ await driver.waitFor(find.byValueKey('Header'));
+ final String foundPackage = await driver.getText(find.byValueKey('EnginePackage'));
+ final String foundLicense = await driver.getText(find.byValueKey('EngineLicense'));
+ expect(foundPackage, equals('engine'));
+ // The engine has the same license, but with a different Copyright date.
+ expect(foundLicense, contains(license.replaceFirst('2014', '2013')));
+ });
+ });
+}
+
+/// Workaround for isolates being paused by driver tests.
+/// https://github.com/flutter/flutter/issues/24703
+class IsolatesWorkaround {
+ IsolatesWorkaround(this._driver);
+
+ final FlutterDriver _driver;
+ StreamSubscription<VMIsolateRef> _streamSubscription;
+
+ Future<void> resumeIsolates() async {
+ final VM vm = await _driver.serviceClient.getVM();
+ // Resume any paused isolate
+ for (final VMIsolateRef isolateRef in vm.isolates) {
+ final VMIsolate isolate = await isolateRef.load();
+ if (isolate.isPaused) {
+ isolate.resume();
+ }
+ }
+ if (_streamSubscription != null) {
+ return;
+ }
+ _streamSubscription = _driver.serviceClient.onIsolateRunnable
+ .asBroadcastStream()
+ .listen((VMIsolateRef isolateRef) async {
+ final VMIsolate isolate = await isolateRef.load();
+ if (isolate.isPaused) {
+ isolate.resume();
+ }
+ });
+ }
+
+ Future<void> tearDown() async {
+ if (_streamSubscription != null) {
+ await _streamSubscription.cancel();
+ }
+ }
+}
diff --git a/packages/flutter/LICENSE b/packages/flutter/LICENSE
new file mode 100644
index 0000000..aea51a3
--- /dev/null
+++ b/packages/flutter/LICENSE
@@ -0,0 +1,25 @@
+Copyright 2014 The Flutter Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of Google Inc. nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.