OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library validator_test; | 5 library validator_test; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:io'; | 8 import 'dart:io'; |
9 import 'dart:json' as json; | 9 import 'dart:json' as json; |
10 import 'dart:math' as math; | 10 import 'dart:math' as math; |
11 | 11 |
12 import 'test_pub.dart'; | 12 import 'test_pub.dart'; |
13 import '../../../pkg/unittest/lib/unittest.dart'; | |
14 import '../../../pkg/http/lib/http.dart' as http; | 13 import '../../../pkg/http/lib/http.dart' as http; |
15 import '../../../pkg/http/lib/testing.dart'; | 14 import '../../../pkg/http/lib/testing.dart'; |
| 15 import '../../../pkg/path/lib/path.dart' as path; |
| 16 import '../../../pkg/unittest/lib/unittest.dart'; |
16 import '../../pub/entrypoint.dart'; | 17 import '../../pub/entrypoint.dart'; |
17 import '../../pub/io.dart'; | 18 import '../../pub/io.dart'; |
18 import '../../pub/validator.dart'; | 19 import '../../pub/validator.dart'; |
19 import '../../pub/validator/compiled_dartdoc.dart'; | 20 import '../../pub/validator/compiled_dartdoc.dart'; |
20 import '../../pub/validator/dependency.dart'; | 21 import '../../pub/validator/dependency.dart'; |
21 import '../../pub/validator/directory.dart'; | 22 import '../../pub/validator/directory.dart'; |
22 import '../../pub/validator/lib.dart'; | 23 import '../../pub/validator/lib.dart'; |
23 import '../../pub/validator/license.dart'; | 24 import '../../pub/validator/license.dart'; |
24 import '../../pub/validator/name.dart'; | 25 import '../../pub/validator/name.dart'; |
25 import '../../pub/validator/pubspec_field.dart'; | 26 import '../../pub/validator/pubspec_field.dart'; |
26 import '../../pub/validator/size.dart'; | 27 import '../../pub/validator/size.dart'; |
27 import '../../pub/validator/utf8_readme.dart'; | 28 import '../../pub/validator/utf8_readme.dart'; |
28 | 29 |
29 void expectNoValidationError(ValidatorCreator fn) { | 30 void expectNoValidationError(ValidatorCreator fn) { |
30 expectLater(schedulePackageValidation(fn), pairOf(isEmpty, isEmpty)); | 31 expectLater(schedulePackageValidation(fn), pairOf(isEmpty, isEmpty)); |
31 } | 32 } |
32 | 33 |
33 void expectValidationError(ValidatorCreator fn) { | 34 void expectValidationError(ValidatorCreator fn) { |
34 expectLater(schedulePackageValidation(fn), pairOf(isNot(isEmpty), anything)); | 35 expectLater(schedulePackageValidation(fn), pairOf(isNot(isEmpty), anything)); |
35 } | 36 } |
36 | 37 |
37 void expectValidationWarning(ValidatorCreator fn) { | 38 void expectValidationWarning(ValidatorCreator fn) { |
38 expectLater(schedulePackageValidation(fn), pairOf(isEmpty, isNot(isEmpty))); | 39 expectLater(schedulePackageValidation(fn), pairOf(isEmpty, isNot(isEmpty))); |
39 } | 40 } |
40 | 41 |
| 42 expectDependencyValidationError(String error) { |
| 43 expectLater(schedulePackageValidation(dependency), |
| 44 pairOf(someElement(contains(error)), isEmpty)); |
| 45 } |
| 46 |
| 47 expectDependencyValidationWarning(String warning) { |
| 48 expectLater(schedulePackageValidation(dependency), |
| 49 pairOf(isEmpty, someElement(contains(warning)))); |
| 50 } |
| 51 |
41 Validator compiledDartdoc(Entrypoint entrypoint) => | 52 Validator compiledDartdoc(Entrypoint entrypoint) => |
42 new CompiledDartdocValidator(entrypoint); | 53 new CompiledDartdocValidator(entrypoint); |
43 | 54 |
44 Validator dependency(Entrypoint entrypoint) => | 55 Validator dependency(Entrypoint entrypoint) => |
45 new DependencyValidator(entrypoint); | 56 new DependencyValidator(entrypoint); |
46 | 57 |
47 Validator directory(Entrypoint entrypoint) => | 58 Validator directory(Entrypoint entrypoint) => |
48 new DirectoryValidator(entrypoint); | 59 new DirectoryValidator(entrypoint); |
49 | 60 |
50 Validator lib(Entrypoint entrypoint) => new LibValidator(entrypoint); | 61 Validator lib(Entrypoint entrypoint) => new LibValidator(entrypoint); |
51 | 62 |
52 Validator license(Entrypoint entrypoint) => new LicenseValidator(entrypoint); | 63 Validator license(Entrypoint entrypoint) => new LicenseValidator(entrypoint); |
53 | 64 |
54 Validator name(Entrypoint entrypoint) => new NameValidator(entrypoint); | 65 Validator name(Entrypoint entrypoint) => new NameValidator(entrypoint); |
55 | 66 |
56 Validator pubspecField(Entrypoint entrypoint) => | 67 Validator pubspecField(Entrypoint entrypoint) => |
57 new PubspecFieldValidator(entrypoint); | 68 new PubspecFieldValidator(entrypoint); |
58 | 69 |
59 Function size(int size) { | 70 Function size(int size) { |
60 return (entrypoint) => | 71 return (entrypoint) => |
61 new SizeValidator(entrypoint, new Future.immediate(size)); | 72 new SizeValidator(entrypoint, new Future.immediate(size)); |
62 } | 73 } |
63 | 74 |
64 Validator utf8Readme(Entrypoint entrypoint) => | 75 Validator utf8Readme(Entrypoint entrypoint) => |
65 new Utf8ReadmeValidator(entrypoint); | 76 new Utf8ReadmeValidator(entrypoint); |
66 | 77 |
67 void scheduleNormalPackage() => normalPackage.scheduleCreate(); | 78 void scheduleNormalPackage() => normalPackage.scheduleCreate(); |
68 | 79 |
| 80 /// Sets up a test package with dependency [dep] and mocks a server with |
| 81 /// [hostedVersions] of the package available. |
| 82 setUpDependency(Map dep, {List<String> hostedVersions}) { |
| 83 useMockClient(new MockClient((request) { |
| 84 expect(request.method, equals("GET")); |
| 85 expect(request.url.path, equals("/packages/foo.json")); |
| 86 |
| 87 if (hostedVersions == null) { |
| 88 return new Future.immediate(new http.Response("not found", 404)); |
| 89 } else { |
| 90 return new Future.immediate(new http.Response(json.stringify({ |
| 91 "name": "foo", |
| 92 "uploaders": ["nweiz@google.com"], |
| 93 "versions": hostedVersions |
| 94 }), 200)); |
| 95 } |
| 96 })); |
| 97 |
| 98 dir(appPath, [ |
| 99 libPubspec("test_pkg", "1.0.0", deps: [dep]) |
| 100 ]).scheduleCreate(); |
| 101 } |
| 102 |
69 main() { | 103 main() { |
| 104 initConfig(); |
70 group('should consider a package valid if it', () { | 105 group('should consider a package valid if it', () { |
71 setUp(scheduleNormalPackage); | 106 setUp(scheduleNormalPackage); |
72 | 107 |
73 integration('looks normal', () { | 108 integration('looks normal', () { |
74 dir(appPath, [libPubspec("test_pkg", "1.0.0")]).scheduleCreate(); | 109 dir(appPath, [libPubspec("test_pkg", "1.0.0")]).scheduleCreate(); |
75 expectNoValidationError(dependency); | 110 expectNoValidationError(dependency); |
76 expectNoValidationError(lib); | 111 expectNoValidationError(lib); |
77 expectNoValidationError(license); | 112 expectNoValidationError(license); |
78 expectNoValidationError(name); | 113 expectNoValidationError(name); |
79 expectNoValidationError(pubspecField); | 114 expectNoValidationError(pubspecField); |
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
319 integration('has a lib directory containing only src', () { | 354 integration('has a lib directory containing only src', () { |
320 file(join(appPath, "lib", "test_pkg.dart"), '').scheduleDelete(); | 355 file(join(appPath, "lib", "test_pkg.dart"), '').scheduleDelete(); |
321 dir(appPath, [ | 356 dir(appPath, [ |
322 dir("lib", [ | 357 dir("lib", [ |
323 dir("src", [file("test_pkg.dart", "int i = 0;")]) | 358 dir("src", [file("test_pkg.dart", "int i = 0;")]) |
324 ]) | 359 ]) |
325 ]).scheduleCreate(); | 360 ]).scheduleCreate(); |
326 expectValidationError(lib); | 361 expectValidationError(lib); |
327 }); | 362 }); |
328 | 363 |
329 group('has a dependency with a non-hosted source', () { | 364 group('has a git dependency', () { |
330 group('where a hosted version of that dependency exists', () { | 365 group('where a hosted version exists', () { |
331 integration("and should suggest the hosted package's primary " | 366 integration("and should suggest the hosted primary version", () { |
332 "version", () { | 367 setUpDependency({'git': 'git://github.com/dart-lang/foo'}, |
333 useMockClient(new MockClient((request) { | 368 hostedVersions: ["3.0.0-pre", "2.0.0", "1.0.0"]); |
334 expect(request.method, equals("GET")); | 369 expectDependencyValidationWarning(' foo: ">=2.0.0 <3.0.0"'); |
335 expect(request.url.path, equals("/packages/foo.json")); | |
336 | |
337 return new Future.immediate(new http.Response(json.stringify({ | |
338 "name": "foo", | |
339 "uploaders": ["nweiz@google.com"], | |
340 "versions": ["3.0.0-pre", "2.0.0", "1.0.0"] | |
341 }), 200)); | |
342 })); | |
343 | |
344 dir(appPath, [ | |
345 libPubspec("test_pkg", "1.0.0", deps: [ | |
346 {'git': 'git://github.com/dart-lang/foo'} | |
347 ]) | |
348 ]).scheduleCreate(); | |
349 | |
350 expectLater(schedulePackageValidation(dependency), | |
351 pairOf(isEmpty, someElement(contains( | |
352 ' foo: ">=2.0.0 <3.0.0"')))); | |
353 }); | 370 }); |
354 | 371 |
355 integration("and should suggest the hosted package's prerelease " | 372 integration("and should suggest the hosted prerelease version if " |
356 "version if it's the only version available", () { | 373 "it's the only version available", () { |
357 useMockClient(new MockClient((request) { | 374 setUpDependency({'git': 'git://github.com/dart-lang/foo'}, |
358 expect(request.method, equals("GET")); | 375 hostedVersions: ["3.0.0-pre", "2.0.0-pre"]); |
359 expect(request.url.path, equals("/packages/foo.json")); | 376 expectDependencyValidationWarning(' foo: ">=3.0.0-pre <4.0.0"'); |
360 | |
361 return new Future.immediate(new http.Response(json.stringify({ | |
362 "name": "foo", | |
363 "uploaders": ["nweiz@google.com"], | |
364 "versions": ["3.0.0-pre", "2.0.0-pre"] | |
365 }), 200)); | |
366 })); | |
367 | |
368 dir(appPath, [ | |
369 libPubspec("test_pkg", "1.0.0", deps: [ | |
370 {'git': 'git://github.com/dart-lang/foo'} | |
371 ]) | |
372 ]).scheduleCreate(); | |
373 | |
374 expectLater(schedulePackageValidation(dependency), | |
375 pairOf(isEmpty, someElement(contains( | |
376 ' foo: ">=3.0.0-pre <4.0.0"')))); | |
377 }); | 377 }); |
378 | 378 |
379 integration("and should suggest a tighter constraint if the primary " | 379 integration("and should suggest a tighter constraint if primary is " |
380 "version is pre-1.0.0", () { | 380 "pre-1.0.0", () { |
381 useMockClient(new MockClient((request) { | 381 setUpDependency({'git': 'git://github.com/dart-lang/foo'}, |
382 expect(request.method, equals("GET")); | 382 hostedVersions: ["0.0.1", "0.0.2"]); |
383 expect(request.url.path, equals("/packages/foo.json")); | 383 expectDependencyValidationWarning(' foo: ">=0.0.2 <0.0.3"'); |
384 | |
385 return new Future.immediate(new http.Response(json.stringify({ | |
386 "name": "foo", | |
387 "uploaders": ["nweiz@google.com"], | |
388 "versions": ["0.0.1", "0.0.2"] | |
389 }), 200)); | |
390 })); | |
391 | |
392 dir(appPath, [ | |
393 libPubspec("test_pkg", "1.0.0", deps: [ | |
394 {'git': 'git://github.com/dart-lang/foo'} | |
395 ]) | |
396 ]).scheduleCreate(); | |
397 | |
398 expectLater(schedulePackageValidation(dependency), | |
399 pairOf(isEmpty, someElement(contains( | |
400 ' foo: ">=0.0.2 <0.0.3"')))); | |
401 }); | 384 }); |
402 }); | 385 }); |
403 | 386 |
404 group('where no hosted version of that dependency exists', () { | 387 group('where no hosted version exists', () { |
405 integration("and should use the other source's version", () { | 388 integration("and should use the other source's version", () { |
406 useMockClient(new MockClient((request) { | 389 setUpDependency({ |
407 expect(request.method, equals("GET")); | 390 'git': 'git://github.com/dart-lang/foo', |
408 expect(request.url.path, equals("/packages/foo.json")); | 391 'version': '>=1.0.0 <2.0.0' |
409 | 392 }); |
410 return new Future.immediate(new http.Response("not found", 404)); | 393 expectDependencyValidationWarning(' foo: ">=1.0.0 <2.0.0"'); |
411 })); | |
412 | |
413 dir(appPath, [ | |
414 libPubspec("test_pkg", "1.0.0", deps: [ | |
415 { | |
416 'git': {'url': 'git://github.com/dart-lang/foo'}, | |
417 'version': '>=1.0.0 <2.0.0' | |
418 } | |
419 ]) | |
420 ]).scheduleCreate(); | |
421 | |
422 expectLater(schedulePackageValidation(dependency), | |
423 pairOf(isEmpty, someElement(contains( | |
424 ' foo: ">=1.0.0 <2.0.0"')))); | |
425 }); | 394 }); |
426 | 395 |
427 integration("and should use the other source's unquoted version if " | 396 integration("and should use the other source's unquoted version if " |
428 "it's concrete", () { | 397 "concrete", () { |
429 useMockClient(new MockClient((request) { | 398 setUpDependency({ |
430 expect(request.method, equals("GET")); | 399 'git': 'git://github.com/dart-lang/foo', |
431 expect(request.url.path, equals("/packages/foo.json")); | 400 'version': '0.2.3' |
432 | 401 }); |
433 return new Future.immediate(new http.Response("not found", 404)); | 402 expectDependencyValidationWarning(' foo: 0.2.3'); |
434 })); | |
435 | |
436 dir(appPath, [ | |
437 libPubspec("test_pkg", "1.0.0", deps: [ | |
438 { | |
439 'git': {'url': 'git://github.com/dart-lang/foo'}, | |
440 'version': '0.2.3' | |
441 } | |
442 ]) | |
443 ]).scheduleCreate(); | |
444 | |
445 expectLater(schedulePackageValidation(dependency), | |
446 pairOf(isEmpty, someElement(contains(' foo: 0.2.3')))); | |
447 }); | 403 }); |
448 }); | 404 }); |
449 }); | 405 }); |
| 406 |
| 407 group('has a path dependency', () { |
| 408 group('where a hosted version exists', () { |
| 409 integration("and should suggest the hosted primary version", () { |
| 410 setUpDependency({'path': path.join(sandboxDir, 'foo')}, |
| 411 hostedVersions: ["3.0.0-pre", "2.0.0", "1.0.0"]); |
| 412 expectDependencyValidationError(' foo: ">=2.0.0 <3.0.0"'); |
| 413 }); |
| 414 |
| 415 integration("and should suggest the hosted prerelease version if " |
| 416 "it's the only version available", () { |
| 417 setUpDependency({'path': path.join(sandboxDir, 'foo')}, |
| 418 hostedVersions: ["3.0.0-pre", "2.0.0-pre"]); |
| 419 expectDependencyValidationError(' foo: ">=3.0.0-pre <4.0.0"'); |
| 420 }); |
| 421 |
| 422 integration("and should suggest a tighter constraint if primary is " |
| 423 "pre-1.0.0", () { |
| 424 setUpDependency({'path': path.join(sandboxDir, 'foo')}, |
| 425 hostedVersions: ["0.0.1", "0.0.2"]); |
| 426 expectDependencyValidationError(' foo: ">=0.0.2 <0.0.3"'); |
| 427 }); |
| 428 }); |
| 429 |
| 430 group('where no hosted version exists', () { |
| 431 integration("and should use the other source's version", () { |
| 432 setUpDependency({ |
| 433 'path': path.join(sandboxDir, 'foo'), |
| 434 'version': '>=1.0.0 <2.0.0' |
| 435 }); |
| 436 expectDependencyValidationError(' foo: ">=1.0.0 <2.0.0"'); |
| 437 }); |
| 438 |
| 439 integration("and should use the other source's unquoted version if " |
| 440 "concrete", () { |
| 441 setUpDependency({ |
| 442 'path': path.join(sandboxDir, 'foo'), |
| 443 'version': '0.2.3' |
| 444 }); |
| 445 expectDependencyValidationError(' foo: 0.2.3'); |
| 446 }); |
| 447 }); |
| 448 }); |
450 | 449 |
451 group('has an unconstrained dependency', () { | 450 group('has an unconstrained dependency', () { |
452 group('and it should not suggest a version', () { | 451 group('and it should not suggest a version', () { |
453 integration("if there's no lockfile", () { | 452 integration("if there's no lockfile", () { |
454 dir(appPath, [ | 453 dir(appPath, [ |
455 libPubspec("test_pkg", "1.0.0", deps: [ | 454 libPubspec("test_pkg", "1.0.0", deps: [ |
456 {'hosted': 'foo'} | 455 {'hosted': 'foo'} |
457 ]) | 456 ]) |
458 ]).scheduleCreate(); | 457 ]).scheduleCreate(); |
459 | 458 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
500 'source': 'hosted', | 499 'source': 'hosted', |
501 'description': { | 500 'description': { |
502 'name': 'foo', | 501 'name': 'foo', |
503 'url': 'http://pub.dartlang.org' | 502 'url': 'http://pub.dartlang.org' |
504 } | 503 } |
505 } | 504 } |
506 } | 505 } |
507 })) | 506 })) |
508 ]).scheduleCreate(); | 507 ]).scheduleCreate(); |
509 | 508 |
510 expectLater(schedulePackageValidation(dependency), | 509 expectDependencyValidationWarning(' foo: ">=1.2.3 <2.0.0"'); |
511 pairOf(isEmpty, someElement(contains( | |
512 ' foo: ">=1.2.3 <2.0.0"')))); | |
513 }); | 510 }); |
514 | 511 |
515 integration('and it should suggest a concrete constraint if the locked ' | 512 integration('and it should suggest a concrete constraint if the locked ' |
516 'version is pre-1.0.0', () { | 513 'version is pre-1.0.0', () { |
517 dir(appPath, [ | 514 dir(appPath, [ |
518 libPubspec("test_pkg", "1.0.0", deps: [ | 515 libPubspec("test_pkg", "1.0.0", deps: [ |
519 {'hosted': 'foo'} | 516 {'hosted': 'foo'} |
520 ]), | 517 ]), |
521 file("pubspec.lock", json.stringify({ | 518 file("pubspec.lock", json.stringify({ |
522 'packages': { | 519 'packages': { |
523 'foo': { | 520 'foo': { |
524 'version': '0.1.2', | 521 'version': '0.1.2', |
525 'source': 'hosted', | 522 'source': 'hosted', |
526 'description': { | 523 'description': { |
527 'name': 'foo', | 524 'name': 'foo', |
528 'url': 'http://pub.dartlang.org' | 525 'url': 'http://pub.dartlang.org' |
529 } | 526 } |
530 } | 527 } |
531 } | 528 } |
532 })) | 529 })) |
533 ]).scheduleCreate(); | 530 ]).scheduleCreate(); |
534 | 531 |
535 expectLater(schedulePackageValidation(dependency), | 532 expectDependencyValidationWarning(' foo: ">=0.1.2 <0.1.3"'); |
536 pairOf(isEmpty, someElement(contains( | |
537 ' foo: ">=0.1.2 <0.1.3"')))); | |
538 }); | 533 }); |
539 }); | 534 }); |
540 }); | 535 }); |
541 | 536 |
542 integration('has a hosted dependency on itself', () { | 537 integration('has a hosted dependency on itself', () { |
543 dir(appPath, [ | 538 dir(appPath, [ |
544 libPubspec("test_pkg", "1.0.0", deps: [ | 539 libPubspec("test_pkg", "1.0.0", deps: [ |
545 {'hosted': {'name': 'test_pkg', 'version': '>=1.0.0'}} | 540 {'hosted': {'name': 'test_pkg', 'version': '>=1.0.0'}} |
546 ]) | 541 ]) |
547 ]).scheduleCreate(); | 542 ]).scheduleCreate(); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
580 }); | 575 }); |
581 | 576 |
582 test('has a README with invalid utf-8', () { | 577 test('has a README with invalid utf-8', () { |
583 dir(appPath, [ | 578 dir(appPath, [ |
584 binaryFile("README", [192]) | 579 binaryFile("README", [192]) |
585 ]).scheduleCreate(); | 580 ]).scheduleCreate(); |
586 expectValidationWarning(utf8Readme); | 581 expectValidationWarning(utf8Readme); |
587 }); | 582 }); |
588 }); | 583 }); |
589 } | 584 } |
OLD | NEW |