| // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| // This tests if the modification of a status file is done correctly, by | |
| // checking that all entries in the original status file are to be found in the | |
| // new status file. The check therefore allows the merging of section headers if | |
| // they are equal, alphabetizing sections and entries, removing line columns and | |
| // normalizing section conditions. | |
| import 'dart:io'; | |
| import 'package:status_file/canonical_status_file.dart'; | |
| import 'package:status_file/src/expression.dart'; | |
| import 'package:status_file/status_file_normalizer.dart'; | |
| final Uri statusFilePath = Platform.script.resolve("data/"); | |
| void main() { | |
| sanityCheck(); | |
| normalizeCheck(); | |
| } | |
| void normalizeCheck() { | |
| var files = getStatusFiles(); | |
| for (var file in files) { | |
| print("------- ${file.path} -------"); | |
| var statusFile = StatusFile.read(file.path); | |
| var statusFileOther = normalizeStatusFile( | |
| StatusFile.read(file.path), | |
| deleteNonExisting: false, | |
| ); | |
| checkSemanticallyEqual( | |
| statusFile, | |
| statusFileOther, | |
| warnOnDuplicateHeader: true, | |
| ); | |
| checkFileHeaderIntact(statusFile, statusFileOther); | |
| print("------- ${file.path} -------"); | |
| } | |
| } | |
| void sanityCheck() { | |
| var files = getStatusFiles(); | |
| for (var file in files) { | |
| print("------- ${file.path} -------"); | |
| var statusFile = StatusFile.read(file.path); | |
| var statusFileOther = StatusFile.read(file.path); | |
| checkSemanticallyEqual( | |
| statusFile, | |
| statusFileOther, | |
| warnOnDuplicateHeader: true, | |
| ); | |
| checkFileHeaderIntact(statusFile, statusFileOther); | |
| print("------- ${file.path} -------"); | |
| } | |
| } | |
| List<FileSystemEntity> getStatusFiles() { | |
| var statusFiles = <FileSystemEntity>[]; | |
| for (var entry in Directory.fromUri( | |
| statusFilePath, | |
| ).listSync(recursive: true)) { | |
| statusFiles.add(entry); | |
| } | |
| return statusFiles; | |
| } | |
| void checkSemanticallyEqual( | |
| StatusFile original, | |
| StatusFile normalized, { | |
| bool warnOnDuplicateHeader = false, | |
| }) { | |
| var entriesInOriginal = countEntries(original); | |
| var entriesInNormalized = countEntries(normalized); | |
| if (entriesInOriginal != entriesInNormalized) { | |
| print(original); | |
| print("=================="); | |
| print(normalized); | |
| throw Exception( | |
| "The count of entries in original is " | |
| "$entriesInOriginal and the count of entries in normalized is " | |
| "$entriesInNormalized. Those two numbers are not the same.", | |
| ); | |
| } | |
| for (var section in original.sections) { | |
| section.entries.whereType<StatusEntry>().forEach( | |
| (entry) => findInStatusFile( | |
| normalized, | |
| entry, | |
| section.condition.normalize(), | |
| warnOnDuplicateHeader: warnOnDuplicateHeader, | |
| ), | |
| ); | |
| } | |
| } | |
| int countEntries(StatusFile statusFile) { | |
| return statusFile.sections | |
| .map((section) => section.entries.whereType<StatusEntry>().length) | |
| .fold(0, (count, sum) => count + sum); | |
| } | |
| void findInStatusFile( | |
| StatusFile statusFile, | |
| StatusEntry entryToFind, | |
| Expression condition, { | |
| bool warnOnDuplicateHeader = false, | |
| }) { | |
| int foundEntryPosition = -1; | |
| for (var section in statusFile.sections) { | |
| if (section.condition.normalize().compareTo(condition) != 0) { | |
| continue; | |
| } | |
| var matchingEntries = section.entries | |
| .where( | |
| (entry) => | |
| entry is StatusEntry && | |
| entry.path.compareTo(entryToFind.path) == 0 && | |
| listEqual(entry.expectations, entryToFind.expectations), | |
| ) | |
| .toList(); | |
| if (matchingEntries.isEmpty) { | |
| var message = | |
| "Could not find the entry even though the section " | |
| "header matched on line number ${section.lineNumber}. Sections " | |
| "should be unique."; | |
| if (warnOnDuplicateHeader) { | |
| print(message); | |
| } else { | |
| throw Exception(message); | |
| } | |
| } else if (matchingEntries.length == 1 && foundEntryPosition >= 0) { | |
| throw Exception( | |
| "The entry '$entryToFind' on line " | |
| "${entryToFind.lineNumber} in section ${section.condition} was " | |
| "already found in a previous section on line $foundEntryPosition.", | |
| ); | |
| } else if (matchingEntries.length == 1) { | |
| foundEntryPosition = matchingEntries[0].lineNumber; | |
| } else { | |
| throw Exception( | |
| "The entry '$entryToFind' on line " | |
| "${entryToFind.lineNumber} in section ${section.condition} on line " | |
| "${section.lineNumber} had multiple matches in section.", | |
| ); | |
| } | |
| } | |
| if (foundEntryPosition < 0) { | |
| throw Exception( | |
| "Could not find entry '$entryToFind' under the " | |
| "condition $condition in the status file.", | |
| ); | |
| } | |
| } | |
| void checkFileHeaderIntact(StatusFile original, StatusFile normalized) { | |
| var originalHeader = original.sections.first.sectionHeaderComments.toString(); | |
| var normalizedHeader = normalized.sections.first.sectionHeaderComments | |
| .toString(); | |
| if (originalHeader != normalizedHeader) { | |
| throw Exception( | |
| "File headers changed.\nExpected:\n$originalHeader\n\nActual:\n$normalizedHeader", | |
| ); | |
| } | |
| } | |
| bool listEqual<T>(List<T> first, List<T> second) { | |
| if (first.length != second.length) { | |
| return false; | |
| } | |
| for (int i = 0; i < first.length; i++) { | |
| if (first[i] != second[i]) { | |
| return false; | |
| } | |
| } | |
| return true; | |
| } |