blob: cc46522b7e2840859219acfbd28cb45d32152fa0 [file] [log] [blame]
// Copyright (c) 2018, 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.
import 'dart:convert';
import 'package:checked_yaml/checked_yaml.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:pubspec_parse/pubspec_parse.dart';
import 'package:stack_trace/stack_trace.dart';
import 'package:test/test.dart';
import 'pub_utils.dart';
const defaultPubspec = {
'name': 'sample',
'environment': {'sdk': '>=2.12.0 <3.0.0'},
};
String _encodeJson(Object? input) =>
const JsonEncoder.withIndent(' ').convert(input);
Matcher _throwsParsedYamlException(String prettyValue) => throwsA(
const TypeMatcher<ParsedYamlException>().having(
(e) {
final message = e.formattedMessage;
printOnFailure("Actual error format:\nr'''\n$message'''");
_printDebugParsedYamlException(e);
return message;
},
'formattedMessage',
prettyValue,
),
);
void _printDebugParsedYamlException(ParsedYamlException e) {
var innerError = e.innerError;
StackTrace? innerStack;
if (innerError is CheckedFromJsonException) {
final cfje = innerError;
if (cfje.innerError != null) {
innerError = cfje.innerError;
innerStack = cfje.innerStack;
}
}
if (innerError != null) {
final items = [innerError];
if (innerStack != null) {
items.add(Trace.format(innerStack));
}
final content =
LineSplitter.split(items.join('\n')).map((e) => ' $e').join('\n');
printOnFailure('Inner error details:\n$content');
}
}
Future<Pubspec> parse(
Object? content, {
bool quietOnError = false,
bool skipTryPub = false,
bool lenient = false,
}) async {
final encoded = _encodeJson(content);
ProcResult? pubResult;
if (!skipTryPub) {
// ignore: deprecated_member_use
pubResult = await tryPub(encoded);
expect(pubResult, isNotNull);
}
try {
final value = Pubspec.parse(encoded, lenient: lenient);
if (pubResult != null) {
addTearDown(() {
expect(
pubResult!.cleanParse,
isTrue,
reason:
'On success, parsing from the pub client should also succeed.',
);
});
}
return value;
} catch (e) {
if (pubResult != null) {
addTearDown(() {
expect(
pubResult!.cleanParse,
isFalse,
reason: 'On failure, parsing from the pub client should also fail.',
);
});
}
if (e is ParsedYamlException) {
if (!quietOnError) {
_printDebugParsedYamlException(e);
}
}
rethrow;
}
}
void expectParseThrows(
Object? content,
String expectedError, {
bool skipTryPub = false,
bool lenient = false,
}) =>
expect(
() => parse(
content,
lenient: lenient,
quietOnError: true,
skipTryPub: skipTryPub,
),
_throwsParsedYamlException(expectedError),
);
void expectParseThrowsContaining(
Object? content,
String errorFragment, {
bool skipTryPub = false,
bool lenient = false,
}) {
expect(
() => parse(
content,
lenient: lenient,
quietOnError: true,
skipTryPub: skipTryPub,
),
_throwsParsedYamlExceptionContaining(errorFragment),
);
}
// ignore: prefer_expression_function_bodies
Matcher _throwsParsedYamlExceptionContaining(String errorFragment) {
return throwsA(
const TypeMatcher<ParsedYamlException>().having(
(e) {
final message = e.formattedMessage;
printOnFailure("Actual error format:\nr'''\n$message'''");
_printDebugParsedYamlException(e);
return message;
},
'formattedMessage',
contains(errorFragment),
),
);
}