99///
1010/// For any use other than CI, use test.dart instead.
1111////////////////////////////////////////////////////////////////////////////////
12- import 'dart:io' show Platform, exit ;
12+ import 'dart:io' ;
1313
14+ import 'package:path/path.dart' as p;
15+
16+ import 'shared/generation.dart' ;
1417import 'shared/test_runner.dart' ;
1518import 'shared/test_suites.dart' ;
1619
@@ -29,6 +32,77 @@ void _validateTestCoverage(List<List<String>> shards) {
2932 }
3033}
3134
35+ Future <void > _validateGeneratedTestFiles () async {
36+ final String baseDir = p.dirname (p.dirname (Platform .script.toFilePath ()));
37+ final String repositoryRoot = p.dirname (p.dirname (baseDir));
38+ final String relativePigeonPath = p.relative (baseDir, from: repositoryRoot);
39+
40+ print ('Validating generated files:' );
41+ print (' Generating output...' );
42+ final int generateExitCode = await generatePigeons (baseDir: baseDir);
43+ if (generateExitCode != 0 ) {
44+ print ('Generation failed; see above for errors.' );
45+ exit (generateExitCode);
46+ }
47+
48+ print (' Formatting output...' );
49+ final int formatExitCode =
50+ await formatAllFiles (repositoryRoot: repositoryRoot);
51+ if (formatExitCode != 0 ) {
52+ print ('Formatting failed; see above for errors.' );
53+ exit (formatExitCode);
54+ }
55+
56+ print (' Checking for changes...' );
57+ final List <String > modifiedFiles = await _modifiedFiles (
58+ repositoryRoot: repositoryRoot, relativePigeonPath: relativePigeonPath);
59+
60+ if (modifiedFiles.isEmpty) {
61+ return ;
62+ }
63+
64+ print ('The following files are not updated, or not formatted correctly:' );
65+ modifiedFiles.map ((String line) => ' $line ' ).forEach (print);
66+
67+ print ('\n To fix run "dart run tool/generate.dart --format" from the pigeon/ '
68+ 'directory, or apply the diff with the command below.\n ' );
69+
70+ final ProcessResult diffResult = await Process .run (
71+ 'git' ,
72+ < String > ['diff' , relativePigeonPath],
73+ workingDirectory: repositoryRoot,
74+ );
75+ if (diffResult.exitCode != 0 ) {
76+ print ('Unable to determine diff.' );
77+ exit (1 );
78+ }
79+ print ('patch -p1 <<DONE' );
80+ print (diffResult.stdout);
81+ print ('DONE' );
82+ exit (1 );
83+ }
84+
85+ Future <List <String >> _modifiedFiles (
86+ {required String repositoryRoot,
87+ required String relativePigeonPath}) async {
88+ final ProcessResult result = await Process .run (
89+ 'git' ,
90+ < String > ['ls-files' , '--modified' , relativePigeonPath],
91+ workingDirectory: repositoryRoot,
92+ );
93+ if (result.exitCode != 0 ) {
94+ print ('Unable to determine changed files.' );
95+ print (result.stdout);
96+ print (result.stderr);
97+ exit (1 );
98+ }
99+ return (result.stdout as String )
100+ .split ('\n ' )
101+ .map ((String line) => line.trim ())
102+ .where ((String line) => line.isNotEmpty)
103+ .toList ();
104+ }
105+
32106Future <void > main (List <String > args) async {
33107 // Run most tests on Linux, since Linux tends to be the easiest and cheapest.
34108 const List <String > linuxHostTests = < String > [
@@ -85,6 +159,14 @@ Future<void> main(List<String> args) async {
85159 ],
86160 ]);
87161
162+ // Ensure that all generated files are up to date. This is run only on Linux
163+ // both to avoid duplication of work, and to avoid issues if different CI
164+ // configurations have different setups (e.g., different clang-format versions
165+ // or no clang-format at all).
166+ if (Platform .isLinux) {
167+ await _validateGeneratedTestFiles ();
168+ }
169+
88170 final List <String > testsToRun;
89171 if (Platform .isMacOS) {
90172 if (Platform .environment['LUCI_CI' ] != null ) {
0 commit comments