blob: e68c31df39b748a4c600e34270cc60d977c71752 [file] [log] [blame]
// Copyright (c) 2020, 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' show jsonDecode;
import 'package:package_config/package_config_types.dart';
import 'package:test/test.dart';
import 'src/util.dart';
void main() {
var unique = Object();
var root = Uri.file('/tmp/root/');
group('LanguageVersion', () {
test('minimal', () {
var version = LanguageVersion(3, 5);
expect(version.major, 3);
expect(version.minor, 5);
});
test('negative major', () {
expect(
() => LanguageVersion(-1, 1),
throwsA(
isA<RangeError>().having((e) => e.name, 'message', contains('major')),
),
);
});
test('negative minor', () {
expect(
() => LanguageVersion(1, -1),
throwsA(
isA<RangeError>().having((e) => e.name, 'message', contains('minor')),
),
);
});
test('minimal parse', () {
var version = LanguageVersion.parse('3.5');
expect(version.major, 3);
expect(version.minor, 5);
});
void failParse(String name, String input) {
test('$name - error', () {
expect(
() => LanguageVersion.parse(input),
throwsA(isA<PackageConfigError>()),
);
expect(() => LanguageVersion.parse(input), throwsFormatException);
var failed = false;
var actual = LanguageVersion.parse(
input,
onError: (_) {
failed = true;
},
);
expect(failed, true);
expect(actual, isA<LanguageVersion>());
});
}
failParse('Leading zero major', '01.1');
failParse('Leading zero minor', '1.01');
failParse('Sign+ major', '+1.1');
failParse('Sign- major', '-1.1');
failParse('Sign+ minor', '1.+1');
failParse('Sign- minor', '1.-1');
failParse('WhiteSpace 1', ' 1.1');
failParse('WhiteSpace 2', '1 .1');
failParse('WhiteSpace 3', '1. 1');
failParse('WhiteSpace 4', '1.1 ');
test('compareTo valid', () {
var version = LanguageVersion(3, 5);
for (var (otherVersion, matcher) in [
(version, isZero), // Identical.
(LanguageVersion(3, 5), isZero), // Same major, same minor.
(LanguageVersion(3, 4), isPositive), // Same major, lower minor.
(LanguageVersion(3, 6), isNegative), // Same major, greater minor.
(LanguageVersion(2, 5), isPositive), // Lower major, same minor.
(LanguageVersion(2, 4), isPositive), // Lower major, lower minor.
(LanguageVersion(2, 6), isPositive), // Lower major, greater minor.
(LanguageVersion(4, 5), isNegative), // Greater major, same minor.
(LanguageVersion(4, 4), isNegative), // Greater major, lower minor.
(LanguageVersion(4, 6), isNegative), // Greater major, greater minor.
]) {
expect(version.compareTo(otherVersion), matcher);
}
});
test('compareTo invalid', () {
var validVersion = LanguageVersion(3, 5);
var invalidVersion = LanguageVersion.parse('', onError: (_) {});
expect(validVersion.compareTo(invalidVersion), isPositive);
expect(invalidVersion.compareTo(validVersion), isNegative);
});
test('relational valid', () {
/// Test that the relational comparisons between two valid versions
/// match the results of `compareTo`.
void testComparisons(
LanguageVersion version,
LanguageVersion otherVersion,
) {
expect(version == otherVersion, version.compareTo(otherVersion) == 0);
expect(version < otherVersion, version.compareTo(otherVersion) < 0);
expect(version <= otherVersion, version.compareTo(otherVersion) <= 0);
expect(version > otherVersion, version.compareTo(otherVersion) > 0);
expect(version >= otherVersion, version.compareTo(otherVersion) >= 0);
}
var version = LanguageVersion(3, 5);
// Check relational comparisons of a version to itself.
testComparisons(version, version);
// Check relational comparisons of a version to versions with all
// possible combinations of minor and major versions that are
// the same, lower, and greater.
for (final major in [2, 3, 4]) {
for (final minor in [4, 5, 6]) {
testComparisons(version, LanguageVersion(major, minor));
}
}
});
test('relational invalid', () {
void testComparisonsWithInvalid(
LanguageVersion version,
LanguageVersion otherVersion,
) {
expect(version == otherVersion, identical(version, otherVersion));
expect(() => version < otherVersion, throwsA(isA<UnsupportedError>()));
expect(() => version <= otherVersion, throwsA(isA<UnsupportedError>()));
expect(() => version > otherVersion, throwsA(isA<UnsupportedError>()));
expect(() => version >= otherVersion, throwsA(isA<UnsupportedError>()));
}
var validVersion = LanguageVersion(3, 5);
var invalidVersion = LanguageVersion.parse('', onError: (_) {});
var differentInvalidVersion = LanguageVersion.parse('-', onError: (_) {});
testComparisonsWithInvalid(validVersion, invalidVersion);
testComparisonsWithInvalid(invalidVersion, validVersion);
testComparisonsWithInvalid(invalidVersion, invalidVersion);
testComparisonsWithInvalid(invalidVersion, differentInvalidVersion);
});
});
group('Package', () {
test('minimal', () {
var package = Package('name', root, extraData: unique);
expect(package.name, 'name');
expect(package.root, root);
expect(package.packageUriRoot, root);
expect(package.languageVersion, null);
expect(package.extraData, same(unique));
});
test('absolute package root', () {
var version = LanguageVersion(1, 1);
var absolute = root.resolve('foo/bar/');
var package = Package(
'name',
root,
packageUriRoot: absolute,
relativeRoot: false,
languageVersion: version,
extraData: unique,
);
expect(package.name, 'name');
expect(package.root, root);
expect(package.packageUriRoot, absolute);
expect(package.languageVersion, version);
expect(package.extraData, same(unique));
expect(package.relativeRoot, false);
});
test('relative package root', () {
var relative = Uri.parse('foo/bar/');
var absolute = root.resolveUri(relative);
var package = Package(
'name',
root,
packageUriRoot: relative,
relativeRoot: true,
extraData: unique,
);
expect(package.name, 'name');
expect(package.root, root);
expect(package.packageUriRoot, absolute);
expect(package.relativeRoot, true);
expect(package.languageVersion, null);
expect(package.extraData, same(unique));
});
for (var badName in ['a/z', 'a:z', '', '...']) {
test("Invalid name '$badName'", () {
expect(() => Package(badName, root), throwsPackageConfigError);
});
}
test('Invalid root, not absolute', () {
expect(
() => Package('name', Uri.parse('/foo/')),
throwsPackageConfigError,
);
});
test('Invalid root, not ending in slash', () {
expect(
() => Package('name', Uri.parse('file:///foo')),
throwsPackageConfigError,
);
});
test('invalid package root, not ending in slash', () {
expect(
() => Package('name', root, packageUriRoot: Uri.parse('foo')),
throwsPackageConfigError,
);
});
test('invalid package root, not inside root', () {
expect(
() => Package('name', root, packageUriRoot: Uri.parse('../baz/')),
throwsPackageConfigError,
);
});
});
group('package config', () {
test('empty', () {
var empty = PackageConfig([], extraData: unique);
expect(empty.version, 2);
expect(empty.packages, isEmpty);
expect(empty.extraData, same(unique));
expect(empty.resolve(pkg('a', 'b')), isNull);
});
test('single', () {
var package = Package('name', root);
var single = PackageConfig([package], extraData: unique);
expect(single.version, 2);
expect(single.packages, hasLength(1));
expect(single.extraData, same(unique));
expect(single.resolve(pkg('a', 'b')), isNull);
var resolved = single.resolve(pkg('name', 'a/b'));
expect(resolved, root.resolve('a/b'));
});
});
test('writeString', () {
var config = PackageConfig(
[
Package(
'foo',
Uri.parse('file:///pkg/foo/'),
packageUriRoot: Uri.parse('file:///pkg/foo/lib/'),
relativeRoot: false,
languageVersion: LanguageVersion(2, 4),
extraData: {'foo': 'foo!'},
),
Package(
'bar',
Uri.parse('file:///pkg/bar/'),
packageUriRoot: Uri.parse('file:///pkg/bar/lib/'),
relativeRoot: true,
extraData: {'bar': 'bar!'},
),
],
extraData: {'extra': 'data'},
);
var buffer = StringBuffer();
PackageConfig.writeString(config, buffer, Uri.parse('file:///pkg/'));
var text = buffer.toString();
var json = jsonDecode(text); // Is valid JSON.
expect(json, {
'configVersion': 2,
'packages': unorderedEquals([
{
'name': 'foo',
'rootUri': 'file:///pkg/foo/',
'packageUri': 'lib/',
'languageVersion': '2.4',
'foo': 'foo!',
},
{'name': 'bar', 'rootUri': 'bar/', 'packageUri': 'lib/', 'bar': 'bar!'},
]),
'extra': 'data',
});
});
}
final Matcher throwsPackageConfigError = throwsA(isA<PackageConfigError>());