blob: f31a944bffeab355e6f2c7989db2600064ccd182 [file] [log] [blame]
// Copyright 2013 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:io' as io;
import 'package:litetest/litetest.dart';
import 'package:path/path.dart' as path;
import '../bin/format.dart' as target;
final io.File script = io.File.fromUri(io.Platform.script).absolute;
final io.Directory repoDir = script.parent.parent.parent;
class FileContentPair {
FileContentPair(this.original, this.formatted);
final String original;
final String formatted;
}
final FileContentPair ccContentPair = FileContentPair(
'int main(){return 0;}\n', 'int main() {\n return 0;\n}\n');
final FileContentPair hContentPair =
FileContentPair('int\nmain\n()\n;\n', 'int main();\n');
final FileContentPair gnContentPair = FileContentPair(
'test\n(){testvar=true}\n', 'test() {\n testvar = true\n}\n');
final FileContentPair javaContentPair = FileContentPair(
'class Test{public static void main(String args[]){System.out.println("Test");}}\n',
'class Test {\n public static void main(String args[]) {\n System.out.println("Test");\n }\n}\n');
final FileContentPair pythonContentPair = FileContentPair(
"if __name__=='__main__':\n sys.exit(\nMain(sys.argv)\n)\n",
"if __name__ == '__main__':\n sys.exit(Main(sys.argv))\n");
final FileContentPair whitespaceContentPair = FileContentPair(
'int main() {\n return 0; \n}\n',
'int main() {\n return 0;\n}\n');
final FileContentPair headerContentPair = FileContentPair(
<String>[
'#ifndef FOO_H_',
'#define FOO_H_',
'',
'#endif // FOO_H_',
].join('\n'),
<String>[
'#ifndef FLUTTER_FORMAT_TEST_H_',
'#define FLUTTER_FORMAT_TEST_H_',
'',
'#endif // FLUTTER_FORMAT_TEST_H_',
'',
].join('\n'),
);
class TestFileFixture {
TestFileFixture(this.type) {
switch (type) {
case target.FormatCheck.clang:
final io.File ccFile = io.File('${repoDir.path}/format_test.cc');
ccFile.writeAsStringSync(ccContentPair.original);
files.add(ccFile);
final io.File hFile = io.File('${repoDir.path}/format_test.h');
hFile.writeAsStringSync(hContentPair.original);
files.add(hFile);
case target.FormatCheck.gn:
final io.File gnFile = io.File('${repoDir.path}/format_test.gn');
gnFile.writeAsStringSync(gnContentPair.original);
files.add(gnFile);
case target.FormatCheck.java:
final io.File javaFile = io.File('${repoDir.path}/format_test.java');
javaFile.writeAsStringSync(javaContentPair.original);
files.add(javaFile);
case target.FormatCheck.python:
final io.File pyFile = io.File('${repoDir.path}/format_test.py');
pyFile.writeAsStringSync(pythonContentPair.original);
files.add(pyFile);
case target.FormatCheck.whitespace:
final io.File whitespaceFile = io.File('${repoDir.path}/format_test.c');
whitespaceFile.writeAsStringSync(whitespaceContentPair.original);
files.add(whitespaceFile);
case target.FormatCheck.header:
final io.File headerFile = io.File('${repoDir.path}/format_test.h');
headerFile.writeAsStringSync(headerContentPair.original);
files.add(headerFile);
}
}
final target.FormatCheck type;
final List<io.File> files = <io.File>[];
void gitAdd() {
final List<String> args = <String>['add'];
for (final io.File file in files) {
args.add(file.path);
}
io.Process.runSync('git', args);
}
void gitRemove() {
final List<String> args = <String>['rm', '-f'];
for (final io.File file in files) {
args.add(file.path);
}
io.Process.runSync('git', args);
}
Iterable<FileContentPair> getFileContents() {
return files.map((io.File file) {
String content = file.readAsStringSync();
// Avoid clang-tidy formatting CRLF EOL on Windows
content = content.replaceAll('\r\n', '\n');
switch (type) {
case target.FormatCheck.clang:
return FileContentPair(
content,
path.extension(file.path) == '.cc'
? ccContentPair.formatted
: hContentPair.formatted,
);
case target.FormatCheck.gn:
return FileContentPair(
content,
gnContentPair.formatted,
);
case target.FormatCheck.java:
return FileContentPair(
content,
javaContentPair.formatted,
);
case target.FormatCheck.python:
return FileContentPair(
content,
pythonContentPair.formatted,
);
case target.FormatCheck.whitespace:
return FileContentPair(
content,
whitespaceContentPair.formatted,
);
case target.FormatCheck.header:
return FileContentPair(
content,
headerContentPair.formatted,
);
}
});
}
}
void main() {
final String formatterPath =
'${repoDir.path}/ci/format.${io.Platform.isWindows ? 'bat' : 'sh'}';
test('Can fix C++ formatting errors', () {
final TestFileFixture fixture = TestFileFixture(target.FormatCheck.clang);
try {
fixture.gitAdd();
io.Process.runSync(formatterPath, <String>['--check', 'clang', '--fix'],
workingDirectory: repoDir.path);
final Iterable<FileContentPair> files = fixture.getFileContents();
for (final FileContentPair pair in files) {
expect(pair.original, equals(pair.formatted));
}
} finally {
fixture.gitRemove();
}
});
test('Can fix GN formatting errors', () {
final TestFileFixture fixture = TestFileFixture(target.FormatCheck.gn);
try {
fixture.gitAdd();
io.Process.runSync(formatterPath, <String>['--check', 'gn', '--fix'],
workingDirectory: repoDir.path);
final Iterable<FileContentPair> files = fixture.getFileContents();
for (final FileContentPair pair in files) {
expect(pair.original, equals(pair.formatted));
}
} finally {
fixture.gitRemove();
}
});
test('Can fix Java formatting errors', () {
final TestFileFixture fixture = TestFileFixture(target.FormatCheck.java);
try {
fixture.gitAdd();
io.Process.runSync(formatterPath, <String>['--check', 'java', '--fix'],
workingDirectory: repoDir.path);
final Iterable<FileContentPair> files = fixture.getFileContents();
for (final FileContentPair pair in files) {
expect(pair.original, equals(pair.formatted));
}
} finally {
fixture.gitRemove();
}
// TODO(mtolmacs): Fails if Java dependency is unavailable,
// https://github.com/flutter/flutter/issues/129221
}, skip: true);
test('Can fix Python formatting errors', () {
final TestFileFixture fixture = TestFileFixture(target.FormatCheck.python);
try {
fixture.gitAdd();
io.Process.runSync(formatterPath, <String>['--check', 'python', '--fix'],
workingDirectory: repoDir.path);
final Iterable<FileContentPair> files = fixture.getFileContents();
for (final FileContentPair pair in files) {
expect(pair.original, equals(pair.formatted));
}
} finally {
fixture.gitRemove();
}
});
test('Can fix whitespace formatting errors', () {
final TestFileFixture fixture =
TestFileFixture(target.FormatCheck.whitespace);
try {
fixture.gitAdd();
io.Process.runSync(
formatterPath, <String>['--check', 'whitespace', '--fix'],
workingDirectory: repoDir.path);
final Iterable<FileContentPair> files = fixture.getFileContents();
for (final FileContentPair pair in files) {
expect(pair.original, equals(pair.formatted));
}
} finally {
fixture.gitRemove();
}
});
test('Can fix header guard formatting errors', () {
final TestFileFixture fixture = TestFileFixture(target.FormatCheck.header);
try {
fixture.gitAdd();
io.Process.runSync(
formatterPath, <String>['--check', 'header', '--fix'],
workingDirectory: repoDir.path,
);
final Iterable<FileContentPair> files = fixture.getFileContents();
for (final FileContentPair pair in files) {
expect(pair.original, equals(pair.formatted));
}
} finally {
fixture.gitRemove();
}
});
}