From c128dca7893f3f149e644f40564e9bf820474b96 Mon Sep 17 00:00:00 2001 From: Sergio Bobillier Date: Mon, 28 Oct 2024 16:06:58 +0100 Subject: [PATCH] [ELITERT-1198] First commit for Github release Created from github-prep@0fbd4cb Change-Id: Ib698face4ce8d680956fffeb18fce49fb56909e3 --- .gitignore | 13 + .reek.yml | 15 + .rspec | 3 + .rubocop.yml | 13 + .ruby-version | 1 + .travis.yml | 6 + CHANGELOG.md | 176 +++++ Gemfile | 15 + README.md | 119 ++++ Rakefile | 8 + bin/console | 14 + bin/setup | 8 + default.reek | 7 + documentation/.gitignore | 1 + documentation/Makefile | 20 + documentation/make.bat | 35 + documentation/requirements.txt | 2 + documentation/source/appendix/fmea.rst | 184 +++++ documentation/source/appendix/glossary.rst | 58 ++ .../source/appendix/links_and_resources.rst | 48 ++ .../architecture/architecture-overview.rst | 134 ++++ .../images/architecture-overview.jpg | Bin 0 -> 59909 bytes .../source/architecture/images/use-cases.jpg | Bin 0 -> 47864 bytes .../source/architecture/input_output.rst | 67 ++ .../source/architecture/use-cases.rst | 49 ++ documentation/source/conf.py | 38 ++ .../development_guidelines/coding_style.rst | 95 +++ .../images/checkstyle.png | Bin 0 -> 8167 bytes .../images/code-typo.png | Bin 0 -> 23041 bytes .../images/inspect-code.png | Bin 0 -> 34264 bytes .../images/rubocop-logo.png | Bin 0 -> 14747 bytes .../images/rubocop-rubymine.png | Bin 0 -> 256797 bytes .../images/ruby-mine-debug-empty.png | Bin 0 -> 119466 bytes .../images/ruby-mine-debug-full.png | Bin 0 -> 172400 bytes .../images/spell-check.png | Bin 0 -> 39044 bytes documentation/source/index.rst | 56 ++ .../source/introduction/contributing.rst | 84 +++ documentation/source/requirements/index.rst | 16 + .../source/user_guidelines/introduction.rst | 196 ++++++ dragnet.gemspec | 39 ++ exe/dragnet | 9 + lib/dragnet.rb | 18 + lib/dragnet/base_repository.rb | 69 ++ lib/dragnet/cli.rb | 8 + lib/dragnet/cli/base.rb | 72 ++ lib/dragnet/cli/logger.rb | 72 ++ lib/dragnet/cli/master.rb | 173 +++++ lib/dragnet/errors.rb | 9 + lib/dragnet/errors/error.rb | 8 + lib/dragnet/errors/file_not_found_error.rb | 11 + .../errors/incompatible_repository_error.rb | 10 + .../missing_timestamp_attribute_error.rb | 11 + .../errors/no_mtr_files_found_error.rb | 11 + lib/dragnet/errors/not_a_repository_error.rb | 11 + .../errors/repo_path_not_found_error.rb | 10 + .../errors/unable_to_write_report_error.rb | 11 + .../errors/unknown_export_format_error.rb | 11 + lib/dragnet/errors/validation_error.rb | 11 + lib/dragnet/errors/yaml_format_error.rb | 9 + lib/dragnet/explorer.rb | 103 +++ lib/dragnet/exporter.rb | 130 ++++ lib/dragnet/exporters.rb | 13 + lib/dragnet/exporters/exporter.rb | 29 + lib/dragnet/exporters/html_exporter.rb | 158 +++++ lib/dragnet/exporters/id_generator.rb | 35 + lib/dragnet/exporters/json_exporter.rb | 34 + lib/dragnet/exporters/serializers.rb | 12 + .../exporters/serializers/repo_serializer.rb | 40 ++ .../serializers/test_record_serializer.rb | 101 +++ .../verification_result_serializer.rb | 34 + .../exporters/templates/template.html.erb | 518 ++++++++++++++ lib/dragnet/helpers/repository_helper.rb | 27 + lib/dragnet/multi_repository.rb | 48 ++ lib/dragnet/repo.rb | 31 + lib/dragnet/repository.rb | 77 +++ lib/dragnet/test_record.rb | 91 +++ lib/dragnet/validator.rb | 79 +++ lib/dragnet/validators.rb | 12 + lib/dragnet/validators/data_validator.rb | 75 ++ lib/dragnet/validators/entities.rb | 12 + .../validators/entities/repo_validator.rb | 31 + .../entities/test_record_validator.rb | 93 +++ lib/dragnet/validators/fields.rb | 17 + .../fields/description_validator.rb | 24 + .../validators/fields/field_validator.rb | 69 ++ .../validators/fields/files_validator.rb | 29 + lib/dragnet/validators/fields/id_validator.rb | 36 + .../fields/meta_data_field_validator.rb | 36 + .../validators/fields/path_validator.rb | 22 + .../validators/fields/repos_validator.rb | 62 ++ .../validators/fields/result_validator.rb | 33 + .../validators/fields/sha1_validator.rb | 42 ++ lib/dragnet/validators/files_validator.rb | 85 +++ lib/dragnet/validators/repos_validator.rb | 74 ++ lib/dragnet/validators/validator.rb | 20 + lib/dragnet/verification_result.rb | 125 ++++ lib/dragnet/verifier.rb | 64 ++ lib/dragnet/verifiers.rb | 8 + lib/dragnet/verifiers/changes_verifier.rb | 70 ++ lib/dragnet/verifiers/files_verifier.rb | 51 ++ lib/dragnet/verifiers/repos_verifier.rb | 92 +++ lib/dragnet/verifiers/repository_verifier.rb | 27 + lib/dragnet/verifiers/result_verifier.rb | 32 + lib/dragnet/verifiers/test_record_verifier.rb | 85 +++ lib/dragnet/verifiers/verifier.rb | 37 + lib/dragnet/version.rb | 5 + req/cli.dim | 94 +++ req/config.yml | 5 + req/explorer.dim | 26 + req/exporter.dim | 146 ++++ req/validator.dim | 254 +++++++ req/verifier.dim | 166 +++++ spec/.rubocop.yml | 13 + spec/dragnet/cli/logger_spec.rb | 131 ++++ spec/dragnet/cli/master_spec.rb | 642 ++++++++++++++++++ spec/dragnet/explorer_spec.rb | 157 +++++ spec/dragnet/exporter_spec.rb | 174 +++++ spec/dragnet/exporters/exporter_spec.rb | 35 + spec/dragnet/exporters/html_exporter_spec.rb | 74 ++ spec/dragnet/exporters/id_generator_spec.rb | 46 ++ spec/dragnet/exporters/json_exporter_spec.rb | 163 +++++ .../serializers/repo_serializer_spec.rb | 78 +++ .../test_record_serializer_spec.rb | 406 +++++++++++ .../verification_result_serializer_spec.rb | 71 ++ .../dragnet/helpers/repository_helper_spec.rb | 21 + spec/dragnet/multi_repository_spec.rb | 121 ++++ spec/dragnet/repo_spec.rb | 70 ++ spec/dragnet/repository_spec.rb | 210 ++++++ spec/dragnet/test_record_spec.rb | 275 ++++++++ spec/dragnet/validator_spec.rb | 340 ++++++++++ .../dragnet/validators/data_validator_spec.rb | 115 ++++ .../entities/repo_validator_spec.rb | 119 ++++ .../entities/test_record_validator_spec.rb | 353 ++++++++++ .../fields/description_validator_spec.rb | 78 +++ .../fields/field_validator_shared.rb | 8 + .../validators/fields/field_validator_spec.rb | 21 + .../validators/fields/files_validator_spec.rb | 59 ++ .../validators/fields/id_validator_spec.rb | 61 ++ .../fields/meta_data_field_validator_spec.rb | 85 +++ .../validators/fields/path_validator_spec.rb | 39 ++ .../validators/fields/repos_validator_spec.rb | 99 +++ .../fields/result_validator_spec.rb | 57 ++ .../validators/fields/sha1_validator_spec.rb | 69 ++ .../validators/files_validator_spec.rb | 147 ++++ .../validators/repos_validator_spec.rb | 191 ++++++ spec/dragnet/verification_result_spec.rb | 342 ++++++++++ spec/dragnet/verifier_spec.rb | 277 ++++++++ .../verifiers/changes_verifier_spec.rb | 126 ++++ spec/dragnet/verifiers/files_verifier_spec.rb | 115 ++++ spec/dragnet/verifiers/repos_verifier_spec.rb | 263 +++++++ .../dragnet/verifiers/result_verifier_spec.rb | 78 +++ .../verifiers/test_record_verifier_spec.rb | 271 ++++++++ spec/dragnet_spec.rb | 7 + spec/integration/dragnet/cli/master_spec.rb | 28 + .../dragnet/exporters/html_exporter_spec.rb | 524 ++++++++++++++ .../dragnet/exporters/json_exporter_spec.rb | 274 ++++++++ .../dragnet/exporters/test_files/repo.git | Bin 0 -> 1724 bytes spec/shared/cli_master.rb | 10 + spec/spec_helper.rb | 28 + 159 files changed, 12554 insertions(+) create mode 100644 .gitignore create mode 100644 .reek.yml create mode 100644 .rspec create mode 100644 .rubocop.yml create mode 100644 .ruby-version create mode 100644 .travis.yml create mode 100644 CHANGELOG.md create mode 100644 Gemfile create mode 100644 README.md create mode 100644 Rakefile create mode 100755 bin/console create mode 100755 bin/setup create mode 100644 default.reek create mode 100644 documentation/.gitignore create mode 100644 documentation/Makefile create mode 100644 documentation/make.bat create mode 100644 documentation/requirements.txt create mode 100644 documentation/source/appendix/fmea.rst create mode 100644 documentation/source/appendix/glossary.rst create mode 100644 documentation/source/appendix/links_and_resources.rst create mode 100644 documentation/source/architecture/architecture-overview.rst create mode 100644 documentation/source/architecture/images/architecture-overview.jpg create mode 100644 documentation/source/architecture/images/use-cases.jpg create mode 100644 documentation/source/architecture/input_output.rst create mode 100644 documentation/source/architecture/use-cases.rst create mode 100644 documentation/source/conf.py create mode 100644 documentation/source/development_guidelines/coding_style.rst create mode 100644 documentation/source/development_guidelines/images/checkstyle.png create mode 100644 documentation/source/development_guidelines/images/code-typo.png create mode 100644 documentation/source/development_guidelines/images/inspect-code.png create mode 100644 documentation/source/development_guidelines/images/rubocop-logo.png create mode 100644 documentation/source/development_guidelines/images/rubocop-rubymine.png create mode 100644 documentation/source/development_guidelines/images/ruby-mine-debug-empty.png create mode 100644 documentation/source/development_guidelines/images/ruby-mine-debug-full.png create mode 100644 documentation/source/development_guidelines/images/spell-check.png create mode 100644 documentation/source/index.rst create mode 100644 documentation/source/introduction/contributing.rst create mode 100644 documentation/source/requirements/index.rst create mode 100644 documentation/source/user_guidelines/introduction.rst create mode 100644 dragnet.gemspec create mode 100755 exe/dragnet create mode 100644 lib/dragnet.rb create mode 100644 lib/dragnet/base_repository.rb create mode 100644 lib/dragnet/cli.rb create mode 100644 lib/dragnet/cli/base.rb create mode 100644 lib/dragnet/cli/logger.rb create mode 100644 lib/dragnet/cli/master.rb create mode 100644 lib/dragnet/errors.rb create mode 100644 lib/dragnet/errors/error.rb create mode 100644 lib/dragnet/errors/file_not_found_error.rb create mode 100644 lib/dragnet/errors/incompatible_repository_error.rb create mode 100644 lib/dragnet/errors/missing_timestamp_attribute_error.rb create mode 100644 lib/dragnet/errors/no_mtr_files_found_error.rb create mode 100644 lib/dragnet/errors/not_a_repository_error.rb create mode 100644 lib/dragnet/errors/repo_path_not_found_error.rb create mode 100644 lib/dragnet/errors/unable_to_write_report_error.rb create mode 100644 lib/dragnet/errors/unknown_export_format_error.rb create mode 100644 lib/dragnet/errors/validation_error.rb create mode 100644 lib/dragnet/errors/yaml_format_error.rb create mode 100644 lib/dragnet/explorer.rb create mode 100644 lib/dragnet/exporter.rb create mode 100644 lib/dragnet/exporters.rb create mode 100644 lib/dragnet/exporters/exporter.rb create mode 100644 lib/dragnet/exporters/html_exporter.rb create mode 100644 lib/dragnet/exporters/id_generator.rb create mode 100644 lib/dragnet/exporters/json_exporter.rb create mode 100644 lib/dragnet/exporters/serializers.rb create mode 100644 lib/dragnet/exporters/serializers/repo_serializer.rb create mode 100644 lib/dragnet/exporters/serializers/test_record_serializer.rb create mode 100644 lib/dragnet/exporters/serializers/verification_result_serializer.rb create mode 100644 lib/dragnet/exporters/templates/template.html.erb create mode 100644 lib/dragnet/helpers/repository_helper.rb create mode 100644 lib/dragnet/multi_repository.rb create mode 100644 lib/dragnet/repo.rb create mode 100644 lib/dragnet/repository.rb create mode 100644 lib/dragnet/test_record.rb create mode 100644 lib/dragnet/validator.rb create mode 100644 lib/dragnet/validators.rb create mode 100644 lib/dragnet/validators/data_validator.rb create mode 100644 lib/dragnet/validators/entities.rb create mode 100644 lib/dragnet/validators/entities/repo_validator.rb create mode 100644 lib/dragnet/validators/entities/test_record_validator.rb create mode 100644 lib/dragnet/validators/fields.rb create mode 100644 lib/dragnet/validators/fields/description_validator.rb create mode 100644 lib/dragnet/validators/fields/field_validator.rb create mode 100644 lib/dragnet/validators/fields/files_validator.rb create mode 100644 lib/dragnet/validators/fields/id_validator.rb create mode 100644 lib/dragnet/validators/fields/meta_data_field_validator.rb create mode 100644 lib/dragnet/validators/fields/path_validator.rb create mode 100644 lib/dragnet/validators/fields/repos_validator.rb create mode 100644 lib/dragnet/validators/fields/result_validator.rb create mode 100644 lib/dragnet/validators/fields/sha1_validator.rb create mode 100644 lib/dragnet/validators/files_validator.rb create mode 100644 lib/dragnet/validators/repos_validator.rb create mode 100644 lib/dragnet/validators/validator.rb create mode 100644 lib/dragnet/verification_result.rb create mode 100644 lib/dragnet/verifier.rb create mode 100644 lib/dragnet/verifiers.rb create mode 100644 lib/dragnet/verifiers/changes_verifier.rb create mode 100644 lib/dragnet/verifiers/files_verifier.rb create mode 100644 lib/dragnet/verifiers/repos_verifier.rb create mode 100644 lib/dragnet/verifiers/repository_verifier.rb create mode 100644 lib/dragnet/verifiers/result_verifier.rb create mode 100644 lib/dragnet/verifiers/test_record_verifier.rb create mode 100644 lib/dragnet/verifiers/verifier.rb create mode 100644 lib/dragnet/version.rb create mode 100644 req/cli.dim create mode 100644 req/config.yml create mode 100644 req/explorer.dim create mode 100644 req/exporter.dim create mode 100644 req/validator.dim create mode 100644 req/verifier.dim create mode 100644 spec/.rubocop.yml create mode 100644 spec/dragnet/cli/logger_spec.rb create mode 100644 spec/dragnet/cli/master_spec.rb create mode 100644 spec/dragnet/explorer_spec.rb create mode 100644 spec/dragnet/exporter_spec.rb create mode 100644 spec/dragnet/exporters/exporter_spec.rb create mode 100644 spec/dragnet/exporters/html_exporter_spec.rb create mode 100644 spec/dragnet/exporters/id_generator_spec.rb create mode 100644 spec/dragnet/exporters/json_exporter_spec.rb create mode 100644 spec/dragnet/exporters/serializers/repo_serializer_spec.rb create mode 100644 spec/dragnet/exporters/serializers/test_record_serializer_spec.rb create mode 100644 spec/dragnet/exporters/serializers/verification_result_serializer_spec.rb create mode 100644 spec/dragnet/helpers/repository_helper_spec.rb create mode 100644 spec/dragnet/multi_repository_spec.rb create mode 100644 spec/dragnet/repo_spec.rb create mode 100644 spec/dragnet/repository_spec.rb create mode 100644 spec/dragnet/test_record_spec.rb create mode 100644 spec/dragnet/validator_spec.rb create mode 100644 spec/dragnet/validators/data_validator_spec.rb create mode 100644 spec/dragnet/validators/entities/repo_validator_spec.rb create mode 100644 spec/dragnet/validators/entities/test_record_validator_spec.rb create mode 100644 spec/dragnet/validators/fields/description_validator_spec.rb create mode 100644 spec/dragnet/validators/fields/field_validator_shared.rb create mode 100644 spec/dragnet/validators/fields/field_validator_spec.rb create mode 100644 spec/dragnet/validators/fields/files_validator_spec.rb create mode 100644 spec/dragnet/validators/fields/id_validator_spec.rb create mode 100644 spec/dragnet/validators/fields/meta_data_field_validator_spec.rb create mode 100644 spec/dragnet/validators/fields/path_validator_spec.rb create mode 100644 spec/dragnet/validators/fields/repos_validator_spec.rb create mode 100644 spec/dragnet/validators/fields/result_validator_spec.rb create mode 100644 spec/dragnet/validators/fields/sha1_validator_spec.rb create mode 100644 spec/dragnet/validators/files_validator_spec.rb create mode 100644 spec/dragnet/validators/repos_validator_spec.rb create mode 100644 spec/dragnet/verification_result_spec.rb create mode 100644 spec/dragnet/verifier_spec.rb create mode 100644 spec/dragnet/verifiers/changes_verifier_spec.rb create mode 100644 spec/dragnet/verifiers/files_verifier_spec.rb create mode 100644 spec/dragnet/verifiers/repos_verifier_spec.rb create mode 100644 spec/dragnet/verifiers/result_verifier_spec.rb create mode 100644 spec/dragnet/verifiers/test_record_verifier_spec.rb create mode 100644 spec/dragnet_spec.rb create mode 100644 spec/integration/dragnet/cli/master_spec.rb create mode 100644 spec/integration/dragnet/exporters/html_exporter_spec.rb create mode 100644 spec/integration/dragnet/exporters/json_exporter_spec.rb create mode 100644 spec/integration/dragnet/exporters/test_files/repo.git create mode 100644 spec/shared/cli_master.rb create mode 100644 spec/spec_helper.rb diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2a21cb8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +/.bundle/ +/.yardoc +/_yardoc/ +/coverage/ +/doc/ +/pkg/ +/spec/reports/ +/tmp/ + +# rspec failure tracking +.rspec_status + +/Gemfile.lock diff --git a/.reek.yml b/.reek.yml new file mode 100644 index 0000000..4f6ae70 --- /dev/null +++ b/.reek.yml @@ -0,0 +1,15 @@ +### Generic smell configuration + +detectors: + TooManyInstanceVariables: + max_instance_variables: 10 + TooManyStatements: + max_statements: 10 + DuplicateMethodCall: + max_calls: 3 + NestedIterators: + max_allowed_nesting: 2 + UncommunicativeVariableName: + accept: [_, e] + LongParameterList: + max_params: 5 diff --git a/.rspec b/.rspec new file mode 100644 index 0000000..34c5164 --- /dev/null +++ b/.rspec @@ -0,0 +1,3 @@ +--format documentation +--color +--require spec_helper diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..c59b9e2 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,13 @@ +AllCops: + Exclude: + - spec/spec_helper.rb +Metrics/BlockLength: + Exclude: + - spec/**/* +Metrics/LineLength: + Max: 120 +Metrics/MethodLength: + Max: 15 +Style/FrozenStringLiteralComment: + Exclude: + - bin/console diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 0000000..1f7da99 --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +2.7.7 diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..774944c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,6 @@ +--- +language: ruby +cache: bundler +rvm: + - 2.6.3 +before_install: gem install bundler -v 2.1.4 diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..be80776 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,176 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +Please mark backwards incompatible changes with an exclamation mark at the start. + +## [Unreleased] + +### Fixed +- Made the date/time format used for the `started_at` and `finished_at` + attributes in the exported JSON files stable. + +## [5.2.0] - 2024-04-16 + +### Added +- The JSON file produced when the `-e` CLI switch is given now includes: + - The `started_at`, `finished_at` and `runtime` attributes under the + `verification_result` structure. + - A copy of the `started_at` and `finished_at` attributes directly in each of + the exported objects (This is being added temporarily for + backwards-compatibility reasons and will be removed later). + +## [5.1.2] - 2023-12-11 + +### Fixed +- Fixed the rendering of array-type Test Record IDs in the HTML report. They are + no longer directly rendered with the extra characters added by Ruby's default + `#to_s` method. +- Fixed a `NoMethodError` that appeared after the release of ActiveSupport 7.1. + +## [5.1.1] - 2023-07-14 + +### Fixed +- Fixed an issue that caused the validation to fail when the listed files or + glob patterns had a `/` at the beginning. + +## [5.1.0] - 2023-07-13 + +### Added +- The `Explorer` class will now log all the found MTR files. + +## [5.0.1] - 2023-06-05 + +### Fixed +- Fixed a bug where the validated and transformed meta-data did not get assigned + to the TestRecord. This, in turn, caused issues when rendering the HTML report + since it assumes that these attributes will be arrays. + +## [5.0.0] - 2023-05-26 + +### Changed +- ! Updated `activesupport` from `~> 6` to `~> 7` +- ! Set the minimum Ruby version for the project to `2.7.0` + +## [4.0.0] - 2023-05-24 + +### Changed +- The "Tester name" attribute will only be visible in the HTML report when the + MTR has a value in the `name` field. +- The `name` attribute of the MTRs will now be validated, only strings and + arrays of strings are allowed now. + +### Added +- Added the `test_method` and `tc_derivation_method` fields to the JSON and + HTML exports. +- Added the `MetaDataFieldValidator` class. +- Added the `test_method` and `tc_derivation_method` attributes to the + `TestRecord` class. +- Added validation for the `test_method` and `tc_derivation_method` attributes + of the MTRs, they can only have strings or arrays of strings. + +## [3.0.0] - 2023-04-05 + +### Added +- Added the `Exporters::IDGenerator` class. +- Added the `DescriptionValidator` class. + +### Changed +- Changed the `JSONExporter` class. It now makes use of the `IDGenerator` class + to attach a unique ID to each of the exported MTRs. +- Added validation for the `descriptionn` field of the MTRs. Only Strings are + allowed now. + +## [2.3.0] - 2023-03-31 + +### Added +- Added a `rescue` to the `software_branches` method in the `HTMLExporter` class + to keep it from crashing when it cannot read the branches from one of the + repositories. + +## [2.2.0] - 2023-03-08 + +### Changed +- Moved the `repo_base` and `relative_to_repo` methods from the `HTMLExporter` + class to the `RepositoryHelper` module. +- Moved the `initialize` method from the `HTMLExporter` class down to the parent + `Exporter` class. +- Changed the `Exporter` class to allow it to export results to JSON format. + +## [2.1.2] - 2023-01-12 + +### Fixed +- Fixed a bug that caused the verification to pass in multi-repo set-ups even + when there were changes in the listed files when `.` was given as a path to + the `check` command. + +## [2.1.1] - 2022-12-22 + +### Fixed +- Fixed an issue with how the file names were being displayed in the HTML report + when the repository's path was the current working directory: (`.`). + +## [2.1.0] - 2022-12-19 + +### Added +- Added the `--multi-repo` command line switch. This switch tells Dragnet that + it is running in a multi-repo environment and will prevent it from assuming + that the given path is a Git repository. +- Dragnet can now recognize and validate MTR files that include the `repos` + attribute (to reference files from multiple repositories). +- Added the `branches_with` and `branches_with_head` methods to the `Repository` + class. + +## [2.0.0] - 2022-09-13 + +### Changed +- Updated `activesupport` to version 6.x +- Updated `jay_api` to version 15.x +- Changed the minimum Ruby version requirement for the gem to 2.5.0 + +## [1.0.0] - 2021-07-02 + +### Changed + - Two new entity objects were introduced `Dragnet::TestRecord` and + `Dragnet::VerificationResult` these will be used instead of the previously + used Hashes. This allows the logic of validation and value evaluation to be + centralized. + - The validation code for the Test Records was moved from + `Dragnet::Validators::DataValidator` to the + `Dragnet::Validators::Entities::TestRecordValidator` class and to a series of + field validation classes inside the `Dragnet::Validators::Fields` module. + +### Added + - Introduced the `Dragnet::Exporter` class which handles exporting the results + of the verification process to different formats (for the moment only HTML is + available, via `Dragnet::Exporters::HTMLExporter`) + - Changed the CLI to receive the `--export` option. (Which can be given + multiple times). + - Added the `Repository` class. A thin wrapper around the Git class. It just + houses some utilitarian methods. + +## [0.1.1] - 2021-06-10 + +### Removed + - Removed a stray "require 'pry'" from a file. + +### Added + - Added "require 'colorize'" for validator and verifier classes. + +## [0.1.0] - 2021-05-27 + +### Added + - Basic structure of the gem + - Added the basic classes for the Gem's CLI + - Added the `Explorer` class. The class searches for Manual Test Record files + on a given path with a set of glob patterns. + - Added the `check` command to the CLI. + - Implemented the `Validator` class. + - Added `jay_api` to the development dependencies in order to be able to use + the `TestDataCollector` class. + - Adds configuration for the `TestDataCollector` class. + - Enables the collection of Test Data for releases. + - Added the `Verifier` class. The class verifies the actual test records and + checks if there have been any changes since the commit specified in the MTR. diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..27bc1cf --- /dev/null +++ b/Gemfile @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +source 'https://rubygems.org' + +# Specify your gem's dependencies in dragnet.gemspec +gemspec + +gem 'pry', '~>0' +gem 'rake', '~> 12.0' +gem 'reek', '~> 6' +gem 'rspec', '~> 3.0' +gem 'rubocop', '~> 1' +gem 'rubocop-rspec', '2' +gem 'simplecov', '~> 0.17.0' +gem 'yard', '~> 0' diff --git a/README.md b/README.md new file mode 100644 index 0000000..08f5b00 --- /dev/null +++ b/README.md @@ -0,0 +1,119 @@ +# Dragnet + +A gem to verify, validate and analyze MTR (Manual Test Record) files. + +Provides a command line tool to perform different types of validations +on MTR files. These files are YAML files that contain information about +the performed test and the revision (commit) for which the test was +performed. + +## Why and how? + +When testing software you strive to automate as much as you can. However not +everything can be tested with automated tests. Sometimes there is no way to +automate the test, in other cases the effort required to automate the test +vastly exceeds the benefits, or the automated test has a very narrow scope. + +In these cases manual tests are a good alternative. But, how do you know when +you need to execute manual tests again? Do you execute them for every release? +That is certainly possible but probably not very efficient. This is where +Dragnet can help. + +This is how it works: + +1. You create a Manual Test Record (MTR). In it you describe what needs to be + tested and how. +2. You list the source files that are involved in the feature the MTR refers to. + (You can list individual files or use glob patterns). +3. You state the SHA1 of the revision you used to perform your test last time. + + *Whenever there are changes to these files Dragnet will detect them and* + *remind you that the manual test needs to be performed again.* + +4. You perform the manual test again and update the SHA1 in the MTR. + +> 💡 Dragnet finishes with specific exit codes allowing you to integrate it in +> your CI pipelines. + +## Dragnet needs very little to work + +Dragnet only needs Ruby and Git to work. Git is probably already part of your +toolchain and Ruby is a very flexible language. You can install it easily in +any platform or use one of the official Docker images. + +## Requirements + +* Ruby >= 2.7.0 (MRI) +* Bundler >= 2.4.0 +* Git >= 2.0.0 + +## Setup + +Clone the repository and install the dependencies by running: + +```shell +bundle install +``` + +## Running Tests + +You can run the tests just by executing RSpec. + +```shell +bundle exec rspec +``` + +To generate a Coverage report: + +```shell +export COVERAGE=true +rspec +``` + +*The coverage report will be written to the `/coverage` path* + +## Generating Documentation + +```shell +bundle exec yard +``` + +*The documentation will be generated in the `/doc` path* + +## Contributing + +* This project uses [Semantic Versioning](https://semver.org/) +* This project uses a `CHANGELOG.md` file to keep track of the changes. + +1. Add your feature. +2. While editing your code keep an eye out for Rubocop and Reek suggestions + try to keep both linters happy. 😉 +3. Write unit and integration *(desirably but not required)* tests for it. +4. Run the tests with the coverage report generation enabled (Check the *Running + Tests section)*. +5. Make sure your Unit Test coverage is at least 90% +6. Run the `yard` command to generate documentation and make sure your + documentation coverage is 100% (everything should be documented) +7. Add your features to the `CHANGELOG.md` file under the *Unreleased* section. + (Check the `CHANGELOG.md`) file for info on how to properly add the changes + there. +8. Push your changes for code review + +### Releases + +After your changes have been reviewed, approved and merged to master you need to +create a Release Pull Request + +1. Decide which type of version increase is the right one for the changes listed + in the *Unreleased* section of the `CHANGELOG.md` file. (Not only your + changes but all the changes listed there). Use the criteria outlined in the + [Semantic Versioning](https://semver.org/) documentation. +2. Increase the version accordingly in the `lib/dragnet/version.rb` file. +3. Create a new section in the `CHANGELOG.md` file for the version and move + the changes on the *Unreleased* section there. +4. Create a new Pull Request for the release. Make sure to follow the following + convention for the commit message. + + ``` + [RELEASE] Version x.y.z + ``` diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..82bb534 --- /dev/null +++ b/Rakefile @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +require 'bundler/gem_tasks' +require 'rspec/core/rake_task' + +RSpec::Core::RakeTask.new(:spec) + +task default: :spec diff --git a/bin/console b/bin/console new file mode 100755 index 0000000..9e5d635 --- /dev/null +++ b/bin/console @@ -0,0 +1,14 @@ +#!/usr/bin/env ruby + +require 'bundler/setup' +require 'dragnet' + +# You can add fixtures and/or initialization code here to make experimenting +# with your gem easier. You can also use a different console, if you like. + +# (If you use this, don't forget to add pry to your Gemfile!) +# require "pry" +# Pry.start + +require 'pry' +Pry.start diff --git a/bin/setup b/bin/setup new file mode 100755 index 0000000..dce67d8 --- /dev/null +++ b/bin/setup @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -euo pipefail +IFS=$'\n\t' +set -vx + +bundle install + +# Do any other automated setup that you need to do here diff --git a/default.reek b/default.reek new file mode 100644 index 0000000..1419419 --- /dev/null +++ b/default.reek @@ -0,0 +1,7 @@ +--- +TooManyStatements: + max_statements: 15 +UncommunicativeVariableName: + accept: [_, e] +DuplicateMethodCall: + max_calls: 3 diff --git a/documentation/.gitignore b/documentation/.gitignore new file mode 100644 index 0000000..d163863 --- /dev/null +++ b/documentation/.gitignore @@ -0,0 +1 @@ +build/ \ No newline at end of file diff --git a/documentation/Makefile b/documentation/Makefile new file mode 100644 index 0000000..d0c3cbf --- /dev/null +++ b/documentation/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/documentation/make.bat b/documentation/make.bat new file mode 100644 index 0000000..dc1312a --- /dev/null +++ b/documentation/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "" goto help + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/documentation/requirements.txt b/documentation/requirements.txt new file mode 100644 index 0000000..a478ad9 --- /dev/null +++ b/documentation/requirements.txt @@ -0,0 +1,2 @@ +Sphinx==7.2.6 +sphinx-material==0.0.35 diff --git a/documentation/source/appendix/fmea.rst b/documentation/source/appendix/fmea.rst new file mode 100644 index 0000000..4c8f620 --- /dev/null +++ b/documentation/source/appendix/fmea.rst @@ -0,0 +1,184 @@ +FMEA +==== + +The FMEA is done at the "General" and "Use-Case" level of the library architecture. +The "Use cases" chapter was analyzed over: + +* Explore to find MTRs +* Validate the MTRs syntax +* Verify the MTRs status with history +* Export the verifications results + +Fault Model +----------- + +The following model is based on the “SWA Fault Model” for activity diagrams +currently used for embedded software. + ++------------------+----------+----------------------------------------------------------------+ +| Element Type | Error ID | Generic Error Description | ++==================+==========+================================================================+ +| **Data storage** | DS1 | Stored data changed before read operation | ++------------------+----------+----------------------------------------------------------------+ +| | DS2 | New data not stored / keeps old data / stuck at specific value | ++------------------+----------+----------------------------------------------------------------+ +| **Data flow** | DF1 | Transferred data changed | ++------------------+----------+----------------------------------------------------------------+ +| | DF2 | Transferred data lost | ++------------------+----------+----------------------------------------------------------------+ +| | DF3 | Data stored at / read from wrong location in data store | ++------------------+----------+----------------------------------------------------------------+ +| | DF4 | Data transferred to wrong data store | ++------------------+----------+----------------------------------------------------------------+ +| **Processing** | PR1 | Calculates wrong results | ++------------------+----------+----------------------------------------------------------------+ +| | PR2 | Processing is skipped | ++------------------+----------+----------------------------------------------------------------+ +| | PR3 | Processing too slow / fast | ++------------------+----------+----------------------------------------------------------------+ +| **Control flow** | CF1 | Control flow stops | ++------------------+----------+----------------------------------------------------------------+ +| | CF2 | Control flow proceeds to wrong process | ++------------------+----------+----------------------------------------------------------------+ + +If more than one error is identified for the same element with the same error +ID, a counter is added, e.g. DF1.1, DF1.2, etc. + +Generalized Errors +------------------ + +The following errors are analyzed generically and not on architectural element +level. + +.. list-table:: + :widths: 10 20 45 45 + :header-rows: 1 + + * - Error ID + - Affected Elements + - General Error Description + - Measures + * - DF2 + - Data flow from / to shell and internal data storage. + - Internal buffers data lost + - Single thread library + * - PR3 + - Processing + - Timing issue on slow execution leading to timeouts expiration, low efficiency in execution time + - Coding style / Code review + * Reduced cyclomatic complexity + * Sleep in the code not normally allowed + * Minimum strictly needed inclusions are used + * - CF1 + - Control flow + - Blocking methods without timeout coverage, Ruby VM stuck on non retuning forks leading to execution stuck, + low efficency in execution time + - Coding style / Code review + * Cover blocking calls with timeouts + +Explore to find MTRs +-------------------- + +The analysis for this section was done based on the ``Explore`` part of the :ref:`use cases diagram ` +in the use cases session + +.. list-table:: + :widths: 12 8 30 25 25 + :header-rows: 1 + + * - Element + - Error ID + - Specific Error Description + - Measures + - References + * - Explorer + - DS2 / DF3 / DF4 + - User configuration (``.dragnet.yaml``) is malformed / not supported encoding leading to parsing error or wrong + initial configuration. + i.e. the configuration may be generated or transferred leading to loss of integrity. + - Assumption for the library user on performing integrity check over user configuration before using in the + library. The integrity has to be granted also in the case the configuration file is generated or given to + the Library by any script. Code Testing grant coverage over exceptions handling + - + +Validate the MTRs syntax +------------------------ + +The analysis for this section was done based on the ``Validate`` part of the +:ref:`use cases diagram ` in the use cases session + +.. list-table:: + :widths: 10 10 30 25 25 + :header-rows: 1 + + * - Element + - Error ID + - Specific Error Description + - Measures + - References + * - Validator + - DS2 / DF3 / DF4 + - MTRs configurations content is malformed / not supported encoding leading to parsing error or wrong + initial configuration. + i.e. the configuration may be generated or transferred leading to loss of integrity. + - Assumption for the library user on performing integrity check over user configuration before using in the + library. The integrity has to be granted also in the case the configuration file is generated or given to + the Library by any script. Code Testing grant coverage over exceptions handling + - + +Verify the MTRs status with history +----------------------------------- + +The analysis for this section was done based on the ``Verify`` part of the +:ref:`use cases diagram ` in the use cases session + +.. list-table:: + :widths: 10 10 30 25 25 + :header-rows: 1 + + * - Element + - Error ID + - Specific Error Description + - Measures + - References + * - Verifier, ChangesVerifier, Repository + - PR1 + - Library to Git passed parameters wrong / malformed leading to wrong behaviour + - Code review + - + * - Master + - PR1.1 + - Library fails to handle internal exceptions leading to wrong behaviour + - Code review, unit / integration testing + - + * - Verifier, ChangesVerifier, Repository + - PR2 + - Git connection loss leading to wrong behaviour + - Code review over exception coverage + - + * - Logger + - PR1 + - Library to CLI passed data is wrong / malformed leading to wrong behaviour + - Code review + - + +Export the verifications results +-------------------------------- + +The analysis for this section was done based on the ``Export`` part of the +:ref:`use cases diagram ` in the use cases session + +.. list-table:: + :widths: 10 10 30 25 25 + :header-rows: 1 + + * - Element + - Error ID + - Specific Error Description + - Measures + - References + * - Exporter, HTMLExporter, JSONExporter + - PR1 + - Library to JSON/HTML export data passed is wrong / malformed leading to wrong behaviour + - Code review + - \ No newline at end of file diff --git a/documentation/source/appendix/glossary.rst b/documentation/source/appendix/glossary.rst new file mode 100644 index 0000000..c2818c0 --- /dev/null +++ b/documentation/source/appendix/glossary.rst @@ -0,0 +1,58 @@ +Glossary +======== + +Manual Test: + A software test that is executed manually, either because it cannot be easily + automated or because it needs physical probing (for example, with an + oscilloscope). Manual tests are performed against a specific revision of the + software, normally defined by the SHA1 of the corresponding revision. + +MTR - Manual Test Record: + A file that records the execution of a manual test. It needs to have at the + very least the ID of the requirement it is testing, the SHA1 of the revision + used when the test was run and a result: either passed or failed. + + MTRs are stored in YAML format. + +Requirement: + One of the requirements defined for the software being tested. Normally + (although not necessarily) managed with DIM_. Each requirement has a unique + ID, which is also used as ID for the MTR. + +Repository: + Refers to a source code repository managed with Git_. + +SHA1: + Is the name of a hashing algorithm. In Dragnet's context it refers to the ID + of an individual software revision. Git generates a SHA1 Hash for every change + (commit_) made to a source code repository under its control. + +Glob Pattern: + Refers to a particular set of symbols used to reference multiple files in a + file system. In dragnet this refers to: + + * The patterns used to locate MTR files inside the repository. + * The patterns used to reference files inside an MTR. + + Form more information check the :doc:`../user_guidelines/introduction`. + +Exploration + In this step of the process Dragnet searches for MTR files. + +Validation + In this step of the process Dragnet validates that the MTR files found during + the exploration phase are valid. This means: No syntax errors, all required + attributes are present and have valid values. + +Verification + Here Dragnet actually checks the MTRs against the repository. Dragnet checks + if there have been any changes to the repository between the revision + annotated in the MTR and the current commit. + +Exporting + Here Dragnet exports the results of the above steps to the specified format. + The exported data varies with the selected format. + +.. _DIM: https://docs.int.esrlabs.com/dim/index.html +.. _Git: https://git-scm.com/ +.. _commit: https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository#_committing_changes diff --git a/documentation/source/appendix/links_and_resources.rst b/documentation/source/appendix/links_and_resources.rst new file mode 100644 index 0000000..0813b0a --- /dev/null +++ b/documentation/source/appendix/links_and_resources.rst @@ -0,0 +1,48 @@ +Links and Resources +=================== + +This page contains a list of important resources and links: + +Source Code +----------- + +* `Dragnet's Source Code Repository `_ + +Module Documentation +-------------------- + +* `Source code documentation for Dragnet (generated automatically by YARD) <../yard/index.html>`_ + +.. _`Build Infrastructure`: + +Build Infrastructure +-------------------- + +* `Verifier and Builder `_ +* `Docs Builder `_ +* `Style-checker (linters) `_ + +Test Results +------------ + +* `Tests Results `_ + +Static Code Analysis +-------------------- + +* `Rubocop Report `_ + +Code Coverage +------------- + +* `Code Coverage Report `_ + +Requirements Coverage +--------------------- + +* `Requirements Coverage Report `_ + +Issue Tracker +------------- + +* `Dragnet's Issue Tracker `_ diff --git a/documentation/source/architecture/architecture-overview.rst b/documentation/source/architecture/architecture-overview.rst new file mode 100644 index 0000000..f04bb39 --- /dev/null +++ b/documentation/source/architecture/architecture-overview.rst @@ -0,0 +1,134 @@ +.. _`architecture-overview`: + +Architecture +============ + +The following diagram offers an overview of all the interactions between the main tool classes: + +.. image:: images/architecture-overview.jpg + :target: ../_images/architecture-overview.jpg + :align: center + +Dragnet +------- + +``Dragnet`` is the main module that includes all the classes. + +Master +------ + +``Master`` is the entry point class for the Dragnet CLI, includes all the commands and +sub-commands of the CLI. The class structure uses helpers to perform the Use-cases steps. +:ref:`use case diagram ` + +Base +---- + +``Base`` is the base class for all CLI classes. + +Logger +------ + +``Logger`` class is a logger for the CLI. It uses the ``say`` method in Thor's ``Shell`` class to print the messages to +the output, honoring the status of the ``quiet`` command line switch. + +Explorer +-------- +The ``Explorer`` class' purpose is to search for Manual Test Record files inside a given path by using the given Glob +patterns. + +The class performs the search for MTR files and returns an array with the found files. + +Validator +--------- + +The ``Validator`` class' purpose is to validate a set of Manual Test Record files content. +Every MTR must be readable, have a valid YAML syntax, have the expected keys and those keys should have sensible +values. + +Validators +^^^^^^^^^^ + +The ``Validators`` module is a namespace for ``Validator`` classes. +The classes contained in the ``Validators`` module are support classes for the validate phase. +:ref:`use case diagram ` + +Verifier +-------- + +The ``Verifier`` class executes the verification process on the given Test Records. Runs the verify process +and returns, for each Test Record, the result of the verification process. + +Verifiers +^^^^^^^^^ + +The ``Verifiers`` module is a namespace for ``Verifier`` classes. +The classes contained in ``Verifiers`` module are support classes for the verify phase. +:ref:`use case diagram ` + +Exporter +-------- + +The ``Exporter`` class' objective is to export the results to specified file. +The class receives an array of test records, an array of errors and an array of file names and exports the results +to the given files deducing the format from file names. + +Exporters +^^^^^^^^^ + +The ``Exporters`` module is a namespace for the ``Exporter`` classes. +The classes contained in ``Exporters`` module are support classes for the export phase. +:ref:`use case diagram ` + +BaseRepository +-------------- + +The ``BaseRepository`` class is the base class for Dragnet's repository classes. + +Repository +---------- + +The ``Repository`` class is a small wrapper around a Git Repository object. It provides some useful methods needed +during the verify process as well as for reporting. + +MultiRepository +--------------- + +The ``MultiRepository`` class is a dummy class that acts as a placeholder when Dragnet is executed on a multi-repo +set-up. + +Since there is no Git repository in the directory where git-repo runs git commands cannot be executed there only in +the inner repositories. + +This class's job is to raise a particular error when a git operation is attempted directly on this directory so that +Dragnet can recognize the cause of the error and display it correctly. + +It also acts as a collection of repositories. It stores a collection of ``Dragnet::Repository`` objects, which point to +the actual repositories. + +Repo +---- + +The ``Repo`` class represents a repository, for MTRs which reference multiple repositories in a multi-repo project, +often managed with git-repo. + + +RepositoryHelper +---------------- + +The ``RepositoryHelper`` class contains some helper methods to use when working with repositories. + +Error +----- + +The ``Error`` class is the base class for all errors raised by the gem. + +Errors +^^^^^^ + +The ``Errors`` module contains all the errors classes that the gem raises. + +Version +------- + +The ``Version`` contains information about the tool version. diff --git a/documentation/source/architecture/images/architecture-overview.jpg b/documentation/source/architecture/images/architecture-overview.jpg new file mode 100644 index 0000000000000000000000000000000000000000..b5a343c76c27c733364eda9943fbdca0f9f9accf GIT binary patch literal 59909 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 literal 0 HcmV?d00001 diff --git a/documentation/source/architecture/images/use-cases.jpg b/documentation/source/architecture/images/use-cases.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7a561243b88d170421ebe89fdc60b5244c467ddd GIT binary patch literal 47864 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В+m2?EaIyg=zP4j=dUM@zIqPwk@(0 zV8RWqJ+*&jb|##iJKea37bJCWCX*Dd0Bj; z%q?w9O%v-uJ>91SGLASPa+*CQoqv49SpEJ```C2clhZX4kKtF4K2@kQQ{b0mfX1XV z2EQUFb5v6x&lWAB?jU0cl)ZBH-Z-EA`r_&*p^Qic$LNEA^zbOLx=l?zFaqZJVRVU6 zOCpcKV0+$wY2n>&_*Xu|FOi*Jy1}3O{*$ivpS$_r2@Cv#Sm%G;aZe0W*`?QN|9i7m z_FA_OWOe_l`ArCANN+Gl295DAVly_bh2?7 z-~Kak?fh!1NkZdBy7iLE_vVIY3Rj0n!1n+pb^?3KsU<( zD!<{3-u%~#`ZspC)388I%J=j9r(#-<*WG?J6?kx>2LcHWS&1ulfOTBxjr)L;C{~Ny`QR literal 0 HcmV?d00001 diff --git a/documentation/source/architecture/input_output.rst b/documentation/source/architecture/input_output.rst new file mode 100644 index 0000000..b659bcf --- /dev/null +++ b/documentation/source/architecture/input_output.rst @@ -0,0 +1,67 @@ +Inputs and Outputs +================== + +This section provides the user a description of the inputs and outputs to and from the Dragnet Gem. + +Inputs +------ + +1. **CLI Arguments** that are passed to the Dragnet gem via CLI during initializzation: + + 1. Dragnet configuration and execution folder + 2. Multi-repo enable option + +2. **Dragnet configuration files** + + 1. configuration file ``.dragnet.yaml`` is expected to be in the execution folder but an alternative path can be + given via the CLI. It contains the configuration for dragnet, for example the glob patterns used to locate + MTR files, among other things. + +Outputs +------- + +1. **CLI Logs** of the executed commands +2. **JSON/HTMl report export** of the check results on user request +3. **Exit Code** + +.. _`exit-codes`: + +Possible Exit Codes ++++++++++++++++++++ + ++-----------+-----------------------------------------------------------------------------+ +| Exit Code | Meaning | ++===========+=============================================================================+ +| 0 | Success: MTR files were loaded successfully and their verification passed. | ++-----------+-----------------------------------------------------------------------------+ +| **Unrecoverable (the execution will be aborted, export can be incomplete)** | ++-----------+-----------------------------------------------------------------------------+ +| 2 | The given path (CLI argument) or the glob patterns in the | +| | configuration file are invalid or malformed | ++-----------+-----------------------------------------------------------------------------+ +| 3 | Dragnet couldn't find any MTR files using the given glob patterns | ++-----------+-----------------------------------------------------------------------------+ +| 4 | Dragnet was unable to open the specified path (or the current working | +| | directory, if no path was given) as a Git repository. | ++-----------+-----------------------------------------------------------------------------+ +| 5 | Dragnet was unable to write to one or more of the files specified to export | +| | the data after the analysis (for example the HTML report). | ++-----------+-----------------------------------------------------------------------------+ +| 6 | Signals that a git operation was attempted on a repository with an | +| | incompatible type. This happens, for example, if the ``--multi-repo`` | +| | command line switch is given but the repository being checked is not a | +| | multi-repository (managed with `git-repo`_), or the other way around. | ++-----------+-----------------------------------------------------------------------------+ +| **Recoverable (the execution will finish, data will be exported)** | ++-----------+-----------------------------------------------------------------------------+ +| 16 | Signals that Dragnet was unable to load one or more of the MTR files | +| | because of a format error, for example: a YAML syntax error, missing | +| | attributes, incompatible types, etc. | ++-----------+-----------------------------------------------------------------------------+ +| 32 | Signals that one or more of the MTRs failed (``result`` is ``failed``) or | +| | were skipped (changes were detected in the repository) | ++-----------+-----------------------------------------------------------------------------+ +| 48 | (Bitwise OR of 16 and 32) Signals that both the above conditions happened. | ++-----------+-----------------------------------------------------------------------------+ + +.. _`git-repo`: https://gerrit.googlesource.com/git-repo diff --git a/documentation/source/architecture/use-cases.rst b/documentation/source/architecture/use-cases.rst new file mode 100644 index 0000000..61ba4d5 --- /dev/null +++ b/documentation/source/architecture/use-cases.rst @@ -0,0 +1,49 @@ +Use Cases +========= + +Dragnet allows the validation of Manual Test Records against the changes in the repository between the revision listed +in the MTR and the current commit. + +The gem has to be configured and uses git to detect changes in target files. + +The Dragnet use-case can be described as a set of phases: + +1. ``Explore``: the gem searches for all the MTRs file given in the Configuration file. +2. ``Validate``: the gem validates the informations contained in each MTR file. +3. ``Verify``: the gem checks in the target repository if there are any changes to the repository or the files listed + in the MTRs since the specified commit. +4. ``Export``: if enabled, the gem exports the results to JSON or HTML format. + +.. _`use-cases`: + +Diagram: +++++++++ + +.. image:: images/use-cases.jpg + :align: center + :target: ../_images/use-cases.jpg + +Explore ++++++++ + +The gem analyses the Configuration file and lists all the MTR files. + +If the configuration file has missing or malformed parameters an error is raised. + +Validate +++++++++ + +The gem validates each of the MTRs from the ``Explore`` phase, if the files are not comnplete or +malformed an error is raised. + +Verify +++++++ + +The gem checks for each valid MTR file the history of the repository or the specified files using ``git`` in the target +repository. The gem then print in CLI the results of the checks to the user. + +Export +++++++ + +If the gem is configured via CLI parameter to export the ``Verify`` phase results, a report is created in +JSON format or via HTML navigable page. \ No newline at end of file diff --git a/documentation/source/conf.py b/documentation/source/conf.py new file mode 100644 index 0000000..d93f5db --- /dev/null +++ b/documentation/source/conf.py @@ -0,0 +1,38 @@ +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information + +project = 'Dragnet' +copyright = '2023, ESR Labs GmbH' +author = 'ESR Labs GmbH' + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +extensions = [] + +templates_path = ['_templates'] +exclude_patterns = [] + + + +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output + +html_theme = 'sphinx_material' + +html_theme_options = { + # Set the color and the accent color + 'color_primary': 'green', + 'color_accent': 'light-green', + 'globaltoc_depth': 3 +} + +html_sidebars = { + '**': ['globaltoc.html', 'localtoc.html', 'relations.html', 'sourcelink.html', 'searchbox.html'] +} + diff --git a/documentation/source/development_guidelines/coding_style.rst b/documentation/source/development_guidelines/coding_style.rst new file mode 100644 index 0000000..5a41c13 --- /dev/null +++ b/documentation/source/development_guidelines/coding_style.rst @@ -0,0 +1,95 @@ +Coding Style +============ + +Please be sure to follow the following code-style guidelines when developing +inside the tool. + +Style-Guide +----------- + +Dragnet is following `RuboCop's Style Guide`_ and +`RuboCop's style guide for RSpec`_ + +Make sure your code follows the principles and practices outlined in those +guides. + +RuboCop ++++++++ + +.. image:: images/rubocop-logo.png + :align: center + +The project is using RuboCop_ as an inspector / static analysis tool. Dragnet +Unit Tests job is configured to run RuboCop on every patchset and present a +report with the findings: + + +.. image:: images/checkstyle.png + :align: center + +RuboCop's Configuration +~~~~~~~~~~~~~~~~~~~~~~~ + +The Configuration for RubCop is stored in the following files: + +/.rubocop.yml + Linter configuration for Dragnet core classes. + +Configure the Linter in your IDE +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The best would be to configure your IDE to run RuboCop by default as you write +code, this way you'd be able to see the issues as you write the code and you'll +have to do less changes during code-review. + +To enable RuboCop in RubyMine follow these steps: + +1. Open RubyMine's preferences (``⌘+,`` on mac) +2. Go to **Editor** -> **Inspections** +3. Scroll down to **Ruby** and inside select **Gems and gems management** +4. Make sure the checkbox to the right of **RuboCop** is ticked. +5. (Optional) Adjust the warning types and colors so that you can clearly see the + warnings in your code. + +.. image:: images/rubocop-rubymine.png + :align: center + +Running RuboCop explicitly +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can run RuboCop explicitly on a file by right clicking on it and selecting +**Inspect Code** from the menu: + +.. image:: images/inspect-code.png + :align: center + +Optionally you can run RuboCop from the command line with:: + + $ bundle exec rubocop + +Typos and Spelling Mistakes +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Writing good code is not only about following the Style Guide's rule or getting +rid of the Linter's warnings. You should also be in the lookout for typos and +spelling mistakes. RubyMine offers spell checking for comments, and strings: + +.. image:: images/spell-check.png + :align: center + +The same feature can detect typos in code: + +.. image:: images/code-typo.png + :align: center + +Use this tool to improve the quality of your code and documentation. + + "If we are not able to take care about the typos, how can we then take care + about the quality of our test cases!?" + + Julian Schneider, 2018 Testers Paradise + +.. _RuboCop: https://github.com/rubocop/rubocop +.. _RuboCop's Style Guide: https://github.com/rubocop/ruby-style-guide/blob/master/README.adoc +.. _RuboCop's style guide for RSpec: https://github.com/rubocop/rspec-style-guide + diff --git a/documentation/source/development_guidelines/images/checkstyle.png b/documentation/source/development_guidelines/images/checkstyle.png new file mode 100644 index 0000000000000000000000000000000000000000..86faec65ef334acdcd60a4034df0c0e26440f176 GIT binary patch literal 8167 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

M|3Rk^Es#e@ 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 literal 0 HcmV?d00001 diff --git a/documentation/source/development_guidelines/images/code-typo.png b/documentation/source/development_guidelines/images/code-typo.png new file mode 100644 index 0000000000000000000000000000000000000000..30e5f5e6b67567b75edc88aaa19f045ede4efd77 GIT binary patch literal 23041 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 H4Fdl^u4udy literal 0 HcmV?d00001 diff --git a/documentation/source/development_guidelines/images/rubocop-logo.png b/documentation/source/development_guidelines/images/rubocop-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..ea22f508d80573bcc6de6d0fffa3d48c48517c2e GIT binary patch literal 14747 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%0Ai-h~~p;-fH1B@4aRT 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 U3x4_40Q&LV>%FIB*Qr1M4{${l_W%F@ literal 0 HcmV?d00001 diff --git a/documentation/source/development_guidelines/images/ruby-mine-debug-empty.png b/documentation/source/development_guidelines/images/ruby-mine-debug-empty.png new file mode 100644 index 0000000000000000000000000000000000000000..04152db233ca6b736c748031bfb1b0a3e8d3e88b GIT binary patch literal 119466 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 literal 0 HcmV?d00001 diff --git a/documentation/source/development_guidelines/images/ruby-mine-debug-full.png b/documentation/source/development_guidelines/images/ruby-mine-debug-full.png new file mode 100644 index 0000000000000000000000000000000000000000..c29da8d73d42ad01152958dacd96b74ca56e7683 GIT binary patch literal 172400 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�wR;K2;dbNITO$LEXI(>s2m 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%0D((sbbA+dM<*bq?Ms2}#arQiwI66`2Bc%P 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 z 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

9E+! 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 WrFhoJgn!zBD=Iwt-KNmw3;zJ-S*r&C literal 0 HcmV?d00001 diff --git a/documentation/source/development_guidelines/images/spell-check.png b/documentation/source/development_guidelines/images/spell-check.png new file mode 100644 index 0000000000000000000000000000000000000000..2418cb2ab7fe813b8623ad778e328a6bfdb80412 GIT binary patch literal 39044 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 +4. Add unit and integration tests for your feature and link the requirements + you added/modified in Step 2 to your tests. Follow the `Test documentation`_ + guide. +5. Document your changes in the ``CHANGELOG.md`` file. Follow the schema + described in the `Keep a Changelog`_ page. Mark backwards incompatible + changes with a ``!`` at the beginning. +6. Commit your changes. Follow + `ESR Labs's guidelines for writing commit messages`_. Reference a the issue + number (if there is one). +7. Push your changes for review, create a Pull Request. +8. Take care of any linter issues raised by the linters. +9. Once your changes are approved by peer review and verified by the CI + infrastructure your changes will be merged to the ``master`` branch. + +Releasing Changes +----------------- + +To make merged changes available for the projects it is necessary to release a +new version of the gem. To do so: + +1. Open the ``CHANGELOG.md`` file. +2. Check all the changes in the ``Unreleased`` section. Decide what type of + version increment should be made. For this use the `Semantic Versioning`_ + guidelines. +3. Under the ``Unreleased`` section add a new header for the version you want to + release and the date when the changes will be released. +4. Open the ``lib/dragnet/version.rb`` file and adjust the version number + accordingly. +5. Commit your changes. The commit message for release commits should follow + this pattern: + + ``[RELEASE] Version X.Y.Z`` + +6. Create a Pull Request for the release. +7. Get your changes reviewed and approved by your peers. +8. The changes should **ONLY** be merged on the date you specified in the + ``CHANGELOG.md`` file. If the changes weren't approved on time update the + date and push the changes for review again. + +.. _`Dragnet's Issue Tracker`: https://github.com/esrlabs/dragnet/issues +.. _`Dragnet's Repository`: https://github.com/esrlabs/dragnet +.. _DIM: https://docs.int.esrlabs.com/dim/index.html +.. _`Test documentation`: https://docs.int.esrlabs.com/guidelines/general/testing/test_documentation.html +.. _`Keep a Changelog`: https://keepachangelog.com/en/1.0.0/ +.. _`ESR Labs's guidelines for writing commit messages`: https://docs.int.esrlabs.com/guidelines/general/scm/commit_message.html +.. _`Semantic Versioning`: https://semver.org/spec/v2.0.0.html diff --git a/documentation/source/requirements/index.rst b/documentation/source/requirements/index.rst new file mode 100644 index 0000000..0acecc1 --- /dev/null +++ b/documentation/source/requirements/index.rst @@ -0,0 +1,16 @@ +Requirements +============ + +This section should list all the requirements of the project. Normally they +are generated dynamically out of DIM_'s requirements in the ``req`` directory. + +If you are seeing this page it means that the requirements haven't been +generated yet. To generate the requirements run the following command: + +.. code-block:: none + + bundler exec dim_to_rst req/config.yaml documentation/source/requirements + +And then generate the Sphinx documentation again. + +.. _DIM: https://docs.int.esrlabs.com/dim/index.html diff --git a/documentation/source/user_guidelines/introduction.rst b/documentation/source/user_guidelines/introduction.rst new file mode 100644 index 0000000..748408d --- /dev/null +++ b/documentation/source/user_guidelines/introduction.rst @@ -0,0 +1,196 @@ +User guidelines +=============== + +Here is a quick user introduction to Dragnet. + +Requirements +------------ + +**Ruby 2.7.0 or greater**: + Recommended Ruby (MRI) < 3.0 + +**RubyGems 3.0.0 or greater**: + Normally installed by default with Ruby. + +**Git 2.0.0 or greater**: + Must be installed in the system and the ``git`` executable should be in the + ``PATH``. + +**unix-like operating system**: + The tool can run in all systems (provided that the Ruby interpreter is + available) but to avoid issues with paths and file names a \*nix (ex. Linux, + Macintosh, BSD, etc) operating system is recommended. + +Installation +------------ + +Dragnet is a Ruby Gem. After installing the gem +you can use the CLI to execute the tool. + +To install dragnet tool:: + + gem install -s https://gems.int.esrlabs.com dragnet + +Needed configuration +-------------------- + +Dragnet needs a configuration to run, the configuration has to contain the path(s) where the MTRs are located. + +Example of configuration file content: + +.. code-block:: yaml + + # .dragnet.yaml + + glob_patterns: + - manual/*.yaml + +The MTR files have to contain the information regarding each specific MTR: + +.. list-table:: MTR Attributes + :widths: 10 30 35 50 20 + :header-rows: 1 + + * - # + - Parameter + - Key + - Value + - Required + * - 1 + - ID + - ``id`` + - The ID of the MTR + - Yes + * - 2 + - Result + - ``result`` + - The result of the Manual Test. + - Yes + * - 3 + - SHA1 + - ``sha1`` + - The SHA1 of the commit in which the Manual Test was performed. + - Yes + * - 4 + - Name + - ``name`` + - The name of the person who performed the Manual Test. + - + * - 5 + - Description + - ``description`` + - The description of the Manual Test, normally which actions were performed and what it was mean to test. + - + * - 6 + - Files + - ``files`` + - The files involved in the MTR, these are the files which will be checked for changes when evaluating the + validity of the MTR. + - Either ``files`` or ``repos`` should be present, not both. + * - 7 + - Repositories + - ``repos`` + - An array of Hashes with the information about the repositories that are involved in the MTR, these + repositories will be checked for changes during the evaluation of the MTR. + - Either ``files`` or ``repos`` should be present, not both. + * - 8 + - Review Status + - ``review_status`` + - The review status of the MTR. (Normally changed when someone other than the tester verifies the result + of the Manual Test) + - + * - 9 + - Review comments + - ``review_comments`` + - The comments left by the person who performed the review of the Manual Test. + - + * - 10 + - Findings + - ``findings`` + - The findings that the reviewer collected during the review process (if any). + - + * - 11 + - Test method + - ``test_method`` + - The method(s) used to carry out the test. + - + * - 12 + - Test case derivation mathod + - ``tc_derivation_method`` + - The method(s) used to derive the test case, note either files or repos should be present, not both. + - + +The **repo** array structure: + +.. list-table:: + :widths: 5 35 15 45 20 + :header-rows: 1 + + * - # + - Parameter + - Key + - Value + - Required + * - 1 + - Path + - ``path`` + - The path where the repository is stored. + - Yes + * - 2 + - SHA1 + - ``sha1`` + - The SHA1 the repository had when the MTR was created. + - Yes + * - 3 + - files + - ``files`` + - The file or array of files covered by the MTR. + - + + +Dragnet tool usage +------------------ + +To use Dragnet use the CLI to launch the tool, the tool accepts the following arguments: + +**Commands** + +dragnet --version + Prints the current version of the Gem + +dragnet --help [COMMAND] + Describes available commands or one specific **COMMAND** + +dragnet check [OPTIONS] [PATH] + Executes the verify procedure on the given **PATH**. If **PATH** is not + present, this defaults to the value of the ``path`` key in the configuration + file or the current working directory if the later is also missing. + +**Options** + +--export If given, the results of the verification procedure will be exported to the given file. The format + of the export will be deducted from the given file's name. (HTML and JSON formats are currently supported) + The switch can be used multiple times to produce multiple output files. +--multi-repo Enables the multi-repo compatibility mode. This prevents Dragnet from assuming that [PATH] refers + to a Git repository allowing it to run even if that is not the case. + + Using this option will cause Dragnet to raise an error if it finds a MTR which doesn't have a ``repos`` + attribute. +--quiet Suppresses the log messages (except errors). + +**Example of usage:** + +``dragnet check --export dragnet.html .`` + +**Output:** + +Dragnet will produce the following output: + +* A log of the executed operations and abnormal conditions. The logs will always + go to the Standard Output. (Logs can be suppressed with the ``--quiet`` + command line switch). +* When the ``--export`` command line switch is used, Dragnet exports the results + of the execution to the given format. +* Dragnet's process will finish with a particular exit code, which reflects the + result of the execution. The list of :ref:`Possible exit codes ` + can be found here. diff --git a/dragnet.gemspec b/dragnet.gemspec new file mode 100644 index 0000000..cd3703d --- /dev/null +++ b/dragnet.gemspec @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +require_relative 'lib/dragnet/version' + +Gem::Specification.new do |spec| + spec.name = 'dragnet' + spec.version = Dragnet::VERSION + spec.authors = ['ESR Labs GmbH'] + spec.email = ['info@esrlabs.com'] + + spec.summary = 'A gem to verify, validate and analyse MTR (Manual Test Record) files.' + spec.description = 'Provides a command line tool to perform different types of validations '\ + 'on MTR files. These files are YAML files that contain information about '\ + 'the performed test and the revision (commit) for which the test was '\ + 'performed.' + spec.homepage = 'https://github.com/esrlabs/dragnet' + spec.license = 'MIT' + spec.required_ruby_version = Gem::Requirement.new('>= 2.7.0') + + spec.metadata['allowed_push_host'] = 'https://gems.int.esrlabs.com' + + spec.metadata['homepage_uri'] = spec.homepage + spec.metadata['source_code_uri'] = spec.homepage + spec.metadata['changelog_uri'] = 'https://github.com/esrlabs/dragnet/blob/master/CHANGELOG.md' + + spec.add_runtime_dependency 'activesupport', '~> 7' + spec.add_runtime_dependency 'colorize', '~> 0.8' + spec.add_runtime_dependency 'git', '~> 1.8' + spec.add_runtime_dependency 'thor', '~> 1.1' + + # Specify which files should be added to the gem when it is released. + # The `git ls-files -z` loads the files in the RubyGem that have been added into git. + spec.files = Dir.chdir(File.expand_path(__dir__)) do + `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(documentation|req|spec)/}) } + end + spec.bindir = 'exe' + spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } + spec.require_paths = ['lib'] +end diff --git a/exe/dragnet b/exe/dragnet new file mode 100755 index 0000000..e2f74c5 --- /dev/null +++ b/exe/dragnet @@ -0,0 +1,9 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +$LOAD_PATH.unshift File.join(__dir__, '..', 'lib') + +require 'bundler/setup' +require 'dragnet/cli/master' + +Dragnet::CLI::Master.start(ARGV) diff --git a/lib/dragnet.rb b/lib/dragnet.rb new file mode 100644 index 0000000..5e4964f --- /dev/null +++ b/lib/dragnet.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +require 'dragnet/version' + +require_relative 'dragnet/cli' +require_relative 'dragnet/errors' +require_relative 'dragnet/explorer' +require_relative 'dragnet/exporter' +require_relative 'dragnet/exporters' +require_relative 'dragnet/multi_repository' +require_relative 'dragnet/repo' +require_relative 'dragnet/validator' +require_relative 'dragnet/validators' +require_relative 'dragnet/verifiers' + +# Main namespace for the gem +module Dragnet +end diff --git a/lib/dragnet/base_repository.rb b/lib/dragnet/base_repository.rb new file mode 100644 index 0000000..23e487d --- /dev/null +++ b/lib/dragnet/base_repository.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +require_relative 'errors/incompatible_repository_error' + +module Dragnet + # Base class for Dragnet's repository classes. + class BaseRepository + attr_reader :path + + # @param [Pathname] path The path were the repository is located. + def initialize(path:) + @path = path + end + + # @raise [Dragnet::Errors::IncompatibleRepositoryError] Is always raised + def git + incompatible_repository(__method__) + end + + # @raise [Dragnet::Errors::IncompatibleRepositoryError] Is always raised + def branch + incompatible_repository(__method__) + end + + # @raise [Dragnet::Errors::IncompatibleRepositoryError] Is always raised + def branches + incompatible_repository(__method__) + end + + # @raise [Dragnet::Errors::IncompatibleRepositoryError] Is always raised + def diff + incompatible_repository(__method__) + end + + # @raise [Dragnet::Errors::IncompatibleRepositoryError] Is always raised + def head + incompatible_repository(__method__) + end + + # @raise [Dragnet::Errors::IncompatibleRepositoryError] Is always raised + def remote_uri_path + incompatible_repository(__method__) + end + + # @raise [Dragnet::Errors::IncompatibleRepositoryError] Is always raised + def repositories + incompatible_repository(__method__) + end + + # @raise [Dragnet::Errors::IncompatibleRepositoryError] Is always raised + def branches_with(_commit) + incompatible_repository(__method__) + end + + # @raise [Dragnet::Errors::IncompatibleRepositoryError] Is always raised + def branches_with_head + incompatible_repository(__method__) + end + + private + + # @param [String] message The message for the raised error. + # @raise [Dragnet::Errors::IncompatibleRepositoryError] Is always raised + # with the given message. + def incompatible_repository(message) + raise Dragnet::Errors::IncompatibleRepositoryError, message + end + end +end diff --git a/lib/dragnet/cli.rb b/lib/dragnet/cli.rb new file mode 100644 index 0000000..f8c0d02 --- /dev/null +++ b/lib/dragnet/cli.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +require_relative 'cli/master.rb' + +module Dragnet + # Namespace for the Gem's CLI + module CLI; end +end diff --git a/lib/dragnet/cli/base.rb b/lib/dragnet/cli/base.rb new file mode 100644 index 0000000..a813003 --- /dev/null +++ b/lib/dragnet/cli/base.rb @@ -0,0 +1,72 @@ +# frozen_string_literal: true + +require 'active_support' +require 'active_support/core_ext/hash' +require 'colorize' +require 'thor' +require 'yaml' + +require_relative 'logger' + +module Dragnet + module CLI + # Base class for all CLI classes. + class Base < Thor + include Thor::Actions + + # Exit status codes + E_CONFIG_LOAD_ERROR = 1 + + attr_reader :configuration, :logger + + class_option :configuration, aliases: :c, desc: 'Configuration file', + default: '.dragnet.yaml', required: true + + class_option :quiet, aliases: :q, default: false, type: :boolean, + desc: 'Suppresses all terminal output (except for critical errors)' + + # Tells Thor to return an unsuccessful return code (different from 0) if + # an error is raised. + def self.exit_on_failure? + true + end + + # Creates a new instance of the class. Called by Thor when a command is + # executed. Creates a logger for the class passing Thor's shell to it + # (Thor's shell handles the output to the console) + def initialize(*args) + super + @logger = Dragnet::CLI::Logger.new(shell) + end + + private + + # @return [String] Returns the name of the configuration file (passed via + # the -c command line switch). + def configuration_file + @configuration_file ||= options[:configuration] + end + + # Loads the configuration from the given configuration file. (This is a + # dumb loader, it basically loads the whole YAML file into a hash, no + # parsing, validation or checking takes place) + def load_configuration + logger.info "Loading configuration file #{configuration_file}..." + @configuration = YAML.safe_load(File.read(configuration_file)).deep_symbolize_keys + rescue StandardError => e + fatal_error("Unable to load the given configuration file: '#{configuration_file}'", e, E_CONFIG_LOAD_ERROR) + end + + # Prints the given message alongside the message of the given exception + # and then terminates the process with the given exit code. + # @param [String] message The error message. + # @param [Exception] exception The exception that caused the fatal error. + # @param [exit_code] exit_code The exit code. + def fatal_error(message, exception, exit_code) + puts 'Error: '.colorize(:light_red) + message + puts " #{exception.message}" + exit(exit_code) + end + end + end +end diff --git a/lib/dragnet/cli/logger.rb b/lib/dragnet/cli/logger.rb new file mode 100644 index 0000000..130cd61 --- /dev/null +++ b/lib/dragnet/cli/logger.rb @@ -0,0 +1,72 @@ +# frozen_string_literal: true + +require 'colorize' + +module Dragnet + module CLI + # A logger for the CLI. It uses the +say+ method in Thor's +Shell+ class to + # print the messages to the output, honoring the status of the +quiet+ + # command line switch. + class Logger + attr_reader :shell, :log_level + + LEVELS = { debug: 0, info: 1, warn: 2, error: 3 }.freeze + DEFAULT_LOG_LEVEL = :info + PADDING_STRING = ' ' + PADDING_WIDTH = 7 + + # Creates a new instance of the class. + # @param [Thor::Shell::Basic] shell A reference to Thor's +Shell+ this + # will be used to send the output to the terminal in which Thor was + # started. + # @param [Symbol] log_level The log level for the logger. The higher the + # level the less output will be printed. + # @see LEVELS + def initialize(shell, log_level = DEFAULT_LOG_LEVEL) + raise ArgumentError, "Unknown logger level: #{log_level}" unless LEVELS.keys.include?(log_level) + + @log_level = LEVELS[log_level] + @shell = shell + end + + # Prints a message with log level +debug+ + # @param [String] message The message to print + def debug(message) + output(:debug, :green, message) + end + + # Prints a message with log level +info+ + # @param [String] message The message to print + def info(message) + output(:info, :blue, message) + end + + # Prints a message with log level +warn+ + # @param [String] message The message to print + def warn(message) + output(:warn, :yellow, message) + end + + # Prints a message with log level +error+ + # @param [String] message The message to print + def error(message) + output(:error, :red, message) + end + + private + + # Prints the given message with the given level and text color (only the + # name of the level will be colored). + # @param [Symbol] level The log level + # @param [Symbol] color The color to use. One of the colors available for + # the +#colorize+ method. + # @param [String] message The message to print. + # @see Colorize::InstanceMethods#colorize + def output(level, color, message) + return unless log_level <= LEVELS[level] + + shell.say "#{level.to_s.capitalize}:".ljust(PADDING_WIDTH, PADDING_STRING).colorize(color) + message + end + end + end +end diff --git a/lib/dragnet/cli/master.rb b/lib/dragnet/cli/master.rb new file mode 100644 index 0000000..39c1879 --- /dev/null +++ b/lib/dragnet/cli/master.rb @@ -0,0 +1,173 @@ +# frozen_string_literal: true + +require_relative '../explorer' +require_relative '../exporter' +require_relative '../multi_repository' +require_relative '../repository' +require_relative '../validator' +require_relative '../verifier' +require_relative '../version' +require_relative 'base' + +module Dragnet + module CLI + # Entry point class for the Dragnet CLI. Includes all the commands and + # sub-commands of the CLI. + # + # The class should not contain any logic, everything should be delegated to + # helper classes as soon as possible. Only exceptions are error handling and + # message printing. + class Master < Dragnet::CLI::Base + E_MISSING_PARAMETER_ERROR = 2 + E_NO_MTR_FILES_FOUND = 3 + E_GIT_ERROR = 4 + E_EXPORT_ERROR = 5 + E_INCOMPATIBLE_REPOSITORY = 6 + + E_ERRORS_DETECTED = 16 + E_FAILED_TESTS = 32 + + map %w[--version -v] => :version + + desc '--version', 'Prints the current version of the Gem' + def version + say "Dragnet #{Dragnet::VERSION}" + say "Copyright (c) #{Time.now.year} ESR Labs GmbH esrlabs.com" + end + + desc 'check [PATH]', 'Executes the verification procedure. '\ + 'Loads the given configuration file and executes the verify procedure on the given path '\ + '(defaults to the value of the "path" key in the configuration file or the current '\ + 'working directory if none of them is given)' + method_option :export, + aliases: 'e', type: :string, repeatable: true, + desc: 'If given, the results of the verification procedure will be exported to'\ + ' the given file. The format of the export will be deducted from the given'\ + " file's name" + method_option :'multi-repo', + aliases: '-m', type: :boolean, default: false, + desc: 'Enables the multi-repo compatibility mode. This prevents Dragnet from assuming'\ + ' that [PATH] refers to a Git repository allowing it to run even if that is not the case.'\ + " Using this option will cause Dragnet to raise an error if it finds a MTR which doesn't"\ + " have a 'repos' attribute" + def check(path = nil) + load_configuration + self.path = path + + files = explore + test_records, errors = validate(files) + verify(test_records) + + export(test_records, errors) if options[:export] + + exit_code = 0 + exit_code |= E_ERRORS_DETECTED if errors.any? + exit_code |= E_FAILED_TESTS unless test_records.all? { |test_record| test_record.verification_result.passed? } + + exit(exit_code) if exit_code.positive? # doing exit(0) will stop RSpec execution. + end + + private + + # Runs the explorer on the given path. + # @return [Array] The array of found MTR files. + def explore + glob_patterns = configuration[:glob_patterns] + + begin + explorer = Dragnet::Explorer.new(path: path, glob_patterns: glob_patterns, logger: logger) + explorer.files + rescue ArgumentError => e + fatal_error('Initialization error. Missing or malformed parameter.', e, E_MISSING_PARAMETER_ERROR) + rescue Dragnet::Errors::NoMTRFilesFoundError => e + fatal_error('No MTR Files found.', e, E_NO_MTR_FILES_FOUND) + end + end + + # Executes the validator on the given MTR files. + # @param [Array] files The files to run the validator on. + # @return [Array (Array, Array)] An array. + # - The first element is an array of +TestRecord+s with the MTR data. + # One for each valid MTR file. + # - The second element contains the errors occurred during the + # validation process. Can be an empty array. + def validate(files) + validator = Dragnet::Validator.new(files: files, path: path, logger: logger) + [validator.validate, validator.errors] + end + + # Executes the verification on the given MTRs + # @param [Array] test_records The array of MTRs on + # which the verification should be executed. + def verify(test_records) + verifier = Dragnet::Verifier.new(test_records: test_records, repository: repository, logger: logger) + verifier.verify + rescue ArgumentError => e + fatal_error("Could not open the specified path: #{path} as a Git Repository", e, E_GIT_ERROR) + rescue Dragnet::Errors::IncompatibleRepositoryError => e + incompatible_repository_error(e) + end + + # Executes the export process. + # @param [Array] test_records The validated and + # verified test records. + # @param [Array] errors The array of Hashes with the MTR files + # that didn't pass the validation process. + def export(test_records, errors) + exporter = Dragnet::Exporter.new( + test_records: test_records, errors: errors, repository: repository, targets: options[:export], logger: logger + ) + + exporter.export + rescue Dragnet::Errors::UnknownExportFormatError, Dragnet::Errors::UnableToWriteReportError => e + fatal_error('Export failed', e, E_EXPORT_ERROR) + rescue Dragnet::Errors::IncompatibleRepositoryError => e + incompatible_repository_error(e) + end + + # @return [Pathname] The path of the directory where the verification + # process should be executed. + def path + @path || set_fallback_path + end + + # @param [Pathname, String] path The path of the directory where the + # verification process should be executed. + def path=(path) + @path = path ? Pathname.new(path) : nil + end + + # @raise [ArgumentError] If the given path is not a valid git repository. + # @return [Dragnet::Repository, Dragnet::MultiRepository] One of the + # possible Repository objects. + def repository + @repository ||= create_repository + end + + # Creates the appropriate Repository object in accordance to the status of + # the +multi-repo+ command line option. + # @return [Dragnet::MultiRepository] If +multi-repo+ was set to +true+ + # @return [Dragnet::Repository] If +multi_repo+ was set to +false+ + def create_repository + options[:'multi-repo'] ? Dragnet::MultiRepository.new(path: path) : Dragnet::Repository.new(path: path) + end + + # Prints a message and exits with the proper error code when a + # +Dragnet::Errors::IncompatibleRepositoryError+ is raised. + # @param [Dragnet::Errors::IncompatibleRepositoryError] error The raised + # error. + def incompatible_repository_error(error) + fatal_error('Incompatible git operation:', error, E_INCOMPATIBLE_REPOSITORY) + end + + # Called when no path has been given by the user explicitly. The method + # uses the configured path or the current working directory as a fallback. + # @return [Pathname] The constructed fallback path. + def set_fallback_path + # The && causes Ruby to return the value of +@path+ AFTER it has been + # assigned (converted to a Pathname) + (self.path = configuration[:path] || Dir.pwd) && @path + end + end + end +end diff --git a/lib/dragnet/errors.rb b/lib/dragnet/errors.rb new file mode 100644 index 0000000..a6938df --- /dev/null +++ b/lib/dragnet/errors.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +require_relative 'errors/not_a_repository_error' +require_relative 'errors/repo_path_not_found_error' + +module Dragnet + # Namespace to house all the error classes for the gem. + module Errors; end +end diff --git a/lib/dragnet/errors/error.rb b/lib/dragnet/errors/error.rb new file mode 100644 index 0000000..1b7d04f --- /dev/null +++ b/lib/dragnet/errors/error.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +module Dragnet + module Errors + # Base class for all errors raised by the gem. + class Error < StandardError; end + end +end diff --git a/lib/dragnet/errors/file_not_found_error.rb b/lib/dragnet/errors/file_not_found_error.rb new file mode 100644 index 0000000..fec048a --- /dev/null +++ b/lib/dragnet/errors/file_not_found_error.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require_relative 'error' + +module Dragnet + module Errors + # An error to be raised when one of the files referenced by a MTR File + # doesn't exist in the repository. + class FileNotFoundError < Dragnet::Errors::Error; end + end +end diff --git a/lib/dragnet/errors/incompatible_repository_error.rb b/lib/dragnet/errors/incompatible_repository_error.rb new file mode 100644 index 0000000..843a8c3 --- /dev/null +++ b/lib/dragnet/errors/incompatible_repository_error.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +module Dragnet + module Errors + # An error to be raised when an attempt is made to perform an action on a + # multi-repo set-up which can only be performed on a single-repo set-up. + # For example, trying to perform a +diff+ operation on the multi-repo root. + class IncompatibleRepositoryError < Dragnet::Errors::Error; end + end +end diff --git a/lib/dragnet/errors/missing_timestamp_attribute_error.rb b/lib/dragnet/errors/missing_timestamp_attribute_error.rb new file mode 100644 index 0000000..379e524 --- /dev/null +++ b/lib/dragnet/errors/missing_timestamp_attribute_error.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require_relative 'error' + +module Dragnet + module Errors + # An error to be raised when an attempt is made to retrieve the runtime + # when one or more timestamp attributes are missing. + class MissingTimestampAttributeError < Dragnet::Errors::Error; end + end +end diff --git a/lib/dragnet/errors/no_mtr_files_found_error.rb b/lib/dragnet/errors/no_mtr_files_found_error.rb new file mode 100644 index 0000000..fb896bb --- /dev/null +++ b/lib/dragnet/errors/no_mtr_files_found_error.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require_relative 'error' + +module Dragnet + module Errors + # An error to be raised when the +Explorer+ is unable to locate MTR files + # with the given glob patterns inside the specified path. + class NoMTRFilesFoundError < Dragnet::Errors::Error; end + end +end diff --git a/lib/dragnet/errors/not_a_repository_error.rb b/lib/dragnet/errors/not_a_repository_error.rb new file mode 100644 index 0000000..57127dd --- /dev/null +++ b/lib/dragnet/errors/not_a_repository_error.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require_relative 'error' + +module Dragnet + module Errors + # An error to be raised when the path of a repository entry in a MTR with + # multiple repositories doesn't point to an actual git repository. + class NotARepositoryError < Dragnet::Errors::Error; end + end +end diff --git a/lib/dragnet/errors/repo_path_not_found_error.rb b/lib/dragnet/errors/repo_path_not_found_error.rb new file mode 100644 index 0000000..4587aca --- /dev/null +++ b/lib/dragnet/errors/repo_path_not_found_error.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +require_relative 'error' + +module Dragnet + module Errors + # An error to raise when the +path+ given for a +repos+ entry cannot be found. + class RepoPathNotFoundError < Dragnet::Errors::Error; end + end +end diff --git a/lib/dragnet/errors/unable_to_write_report_error.rb b/lib/dragnet/errors/unable_to_write_report_error.rb new file mode 100644 index 0000000..070a2db --- /dev/null +++ b/lib/dragnet/errors/unable_to_write_report_error.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require_relative 'error' + +module Dragnet + module Errors + # An error to be raised when Dragnet cannot write to one of the given export + # files. + class UnableToWriteReportError < Dragnet::Errors::Error; end + end +end diff --git a/lib/dragnet/errors/unknown_export_format_error.rb b/lib/dragnet/errors/unknown_export_format_error.rb new file mode 100644 index 0000000..b020ad3 --- /dev/null +++ b/lib/dragnet/errors/unknown_export_format_error.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require_relative 'error' + +module Dragnet + module Errors + # An error to be raised when an export target file is given for which the + # format is unknown (cannot be deduced from its extension). + class UnknownExportFormatError < Dragnet::Errors::Error; end + end +end diff --git a/lib/dragnet/errors/validation_error.rb b/lib/dragnet/errors/validation_error.rb new file mode 100644 index 0000000..0309d44 --- /dev/null +++ b/lib/dragnet/errors/validation_error.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require_relative 'error' + +module Dragnet + module Errors + # An error to be raised when an attempt is made to create an entity with + # invalid data. + class ValidationError < Dragnet::Errors::Error; end + end +end diff --git a/lib/dragnet/errors/yaml_format_error.rb b/lib/dragnet/errors/yaml_format_error.rb new file mode 100644 index 0000000..3b09df2 --- /dev/null +++ b/lib/dragnet/errors/yaml_format_error.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +module Dragnet + module Errors + # An error to be raised when there is a formatting problem with a YAML file. + # For example a missing key. (This error doesn't cover Syntax Errors) + class YAMLFormatError < Dragnet::Errors::Error; end + end +end diff --git a/lib/dragnet/explorer.rb b/lib/dragnet/explorer.rb new file mode 100644 index 0000000..9257eac --- /dev/null +++ b/lib/dragnet/explorer.rb @@ -0,0 +1,103 @@ +# frozen_string_literal: true + +require_relative 'errors/no_mtr_files_found_error' + +module Dragnet + # This class searches for Manual Test Record files inside a given path by + # using the given Glob patterns. + class Explorer + attr_reader :path, :glob_patterns, :logger + + # Creates a new instance of the class. + # @param [Pathname] path The path that should be explored. + # @param [String, Array] glob_patterns The glob pattern or glob + # patterns to use when exploring the specified path. + # @param [#info] logger A logger object to use for output. + # @raise [ArgumentError] If +path+ or +glob_patterns+ are +nil+ or if they + # don't have one of the expected types. + def initialize(path:, glob_patterns:, logger:) + validate_path(path) + validate_patterns(glob_patterns) + + @path = path + @glob_patterns = *glob_patterns + @logger = logger + end + + # Performs the search for MTR files and returns an array with the found + # files. + # @return [Array] The array of found MTR files. + # @raise [Dragnet::Errors::NoMTRFilesFoundError] If no MTR files are found. + def files + @files ||= find_files + end + + private + + # Raises an +ArgumentError+ with the appropriate message. + # @param [String] name The name of the missing parameter. + # @raise [ArgumentError] Is always raised with the appropriate message. + def missing_parameter(name) + raise ArgumentError, "Missing required parameter #{name}" + end + + # Raises an +ArgumentError+ with the appropriate message. + # @param [String] name The name of the parameter with an incompatible type. + # @param [String, Class] expected The expected parameter type. + # @param [String, Class] given The given parameter type. + # @raise [ArgumentError] Is always raised with the appropriate message. + def incompatible_parameter(name, expected, given) + raise ArgumentError, "Incompatible parameter type #{name}. Expected: #{expected}, given: #{given}" + end + + # Validates the given path + # @param [Object] path The path to validate + # @raise [ArgumentError] If the given path is nil or is not a +Pathname+. + def validate_path(path) + missing_parameter('path') unless path + return if path.is_a?(Pathname) + + incompatible_parameter('path', Pathname, path.class) + end + + # Validates the given glob patterns + # @param [String, Array] glob_patterns The glob patterns + # @raise [ArgumentError] If +glob_patterns+ is +nil+ or it isn't an array + # of strings. + def validate_patterns(glob_patterns) + missing_parameter('glob_patterns') unless glob_patterns + + return if glob_patterns.is_a?(String) + return if glob_patterns.is_a?(Array) && glob_patterns.all? { |value| value.is_a?(String) } + + incompatible_parameter('glob_patterns', 'String or Array', glob_patterns.class) + end + + # Logs the MTR files that were found. + # @param [Array] files The found MTR files. + # @return [Array] The same array given in +files+. + def log_found_files(files) + files.each { |file| logger.info("Found MTR file: #{file}") } + end + + # Searches the +path+ for MTR files using the +glob_patterns+ + # @return [Array] The array of found MTR files. + # @raise [Dragnet::Errors::NoMTRFilesFoundError] If no MTR files are found. + def find_files + logger.info 'Searching for Manual Test Records...' + + files = [] + + glob_patterns.each do |glob_pattern| + logger.info "Globbing #{path} with #{glob_pattern}..." + + files += log_found_files(path.glob(glob_pattern)) + end + + return files if files.any? + + raise Dragnet::Errors::NoMTRFilesFoundError, + "No MTR Files found in #{path} with the following glob patterns: #{glob_patterns.join(', ')}" + end + end +end diff --git a/lib/dragnet/exporter.rb b/lib/dragnet/exporter.rb new file mode 100644 index 0000000..6c2984d --- /dev/null +++ b/lib/dragnet/exporter.rb @@ -0,0 +1,130 @@ +# frozen_string_literal: true + +require_relative 'errors/unable_to_write_report_error' +require_relative 'errors/unknown_export_format_error' +require_relative 'exporters/html_exporter' +require_relative 'exporters/json_exporter' + +module Dragnet + # The base exporter class, receives an array of test records, an array of + # errors and an array of file names and exports the results to the given + # files. (For each file the format is deduced from its file name). + class Exporter + KNOWN_FORMATS = { + 'HTML' => { extensions: %w[.html .htm], exporter: Dragnet::Exporters::HTMLExporter }, + 'JSON' => { extensions: %w[.json], exporter: Dragnet::Exporters::JSONExporter } + }.freeze + + attr_reader :test_records, :errors, :repository, :targets, :logger + + # Creates a new instance of the class. + # @param [Array] test_records The array of MTRs that + # should be included in the reports. + # @param [Array] errors An array of Hashes with the data of the MTR + # files that did not pass the validation process. + # @param [Dragnet::Repository, Dragnet::MultiRepository] repository The + # repository where the MTR files and the source code are stored. + # @param [Array] targets The array of target files. For each of them + # the format of the export will be deduced from the file's extension. + # @param [#info, #debug] logger A logger object to use for output. + def initialize(test_records:, errors:, repository:, targets:, logger:) + @test_records = test_records + @errors = errors + @repository = repository + @targets = targets + @logger = logger + end + + # Starts the export process. + # @raise [Dragnet::Errors::UnableToWriteReportError] If one of the target + # files cannot be created, opened, or if the output cannot be written to + # it. + def export + logger.info 'Starting export process...' + log_target_files + + formats.each do |format, targets| + exporter = KNOWN_FORMATS.dig(format, :exporter).new( + test_records: test_records, errors: errors, repository: repository, logger: logger + ) + + text = exporter.export + write_output(text, format, targets) + end + end + + private + + # Writes the given text output with the given format to the given targets. + # @param [String] text The text output to write. + # @param [String] format The format of the target file. + # @param [Array] targets The paths of the target files the output + # should be written to. + # @raise [Dragnet::Errors::UnableToWriteReportError] If one of the target + # files cannot be created, opened, or if the output cannot be written to + # it. + def write_output(text, format, targets) + targets.each do |target| + logger.info "Writing #{format} output to #{target}..." + + begin + start = Time.now + bytes = File.write(target, text) + elapsed = Time.now - start + + logger.debug("Ok (#{bytes} bytes written in #{elapsed} seconds)") + rescue SystemCallError => e + raise Dragnet::Errors::UnableToWriteReportError, + "Unable to write report output to #{target}: #{e.message}" + end + end + end + + # Writes a log entry with the files that will be written as a result of the + # export process (each with its corresponding format). + def log_target_files + files_with_formats = formats.flat_map do |format, targets| + targets.map { |target| "\t * #{target} as #{format}" } + end + + logger.debug "Target files are:\n#{files_with_formats.join("\n")}" + end + + # @return [Hash] A hash whose keys are known formats and whose values are + # arrays of target files. + def formats + @formats ||= deduce_formats + end + + # Deduces the format of each target file (given its extension) and relates + # them to their corresponding formats. + # @return [Hash] A hash whose keys are known formats and whose values are + # arrays of target files. + def deduce_formats + formats = {} + + targets.each do |target| + extension = File.extname(target).downcase + format, = KNOWN_FORMATS.find { |_name, config| config[:extensions].include?(extension) } + unknown_format_error(extension) unless format + + formats[format] ||= [] + formats[format] << target + end + + formats + end + + # Raises a +Dragnet::Errors::UnknownExportFormatError+ with the proper error + # message. + # @param [String] extension The extension of the given target file. + # @raise [Dragnet::Errors::UnknownExportFormatError] is always raised. + def unknown_format_error(extension) + allowed_extensions = KNOWN_FORMATS.flat_map { |_format, config| config[:extensions] } + + raise Dragnet::Errors::UnknownExportFormatError, + "Unknown export format: '#{extension}'. Valid export formats are: "\ + "#{allowed_extensions.join(', ')}" + end + end +end diff --git a/lib/dragnet/exporters.rb b/lib/dragnet/exporters.rb new file mode 100644 index 0000000..299ef07 --- /dev/null +++ b/lib/dragnet/exporters.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +require_relative 'exporters/exporter' +require_relative 'exporters/html_exporter' +require_relative 'exporters/id_generator' +require_relative 'exporters/json_exporter' +require_relative 'exporters/serializers' + +module Dragnet + # Namespace for the exporters: classes that produce files, or reports out of + # the results of the Manual Test Record verification execution. + module Exporters; end +end diff --git a/lib/dragnet/exporters/exporter.rb b/lib/dragnet/exporters/exporter.rb new file mode 100644 index 0000000..b3fa01f --- /dev/null +++ b/lib/dragnet/exporters/exporter.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +module Dragnet + module Exporters + # Base class for all exporter classes. + class Exporter + attr_reader :test_records, :errors, :repository, :logger + + # @param [Array] test_records The array of test records. + # @param [Array] errors The array of errors. + # @param [Dragnet::Repository, Dragnet::MultiRepository] repository The + # repository where the MTR files and the source code are stored. + # @param [#info] logger A logger object to use for output. + def initialize(test_records:, errors:, repository:, logger:) + @test_records = test_records + @errors = errors + @repository = repository + @logger = logger + end + + # @raise [NotImplementedError] Is always raised. Subclasses are expected + # to override this method. + def export + raise NotImplementedError, + "'export' method not implemented for class #{self.class}" + end + end + end +end diff --git a/lib/dragnet/exporters/html_exporter.rb b/lib/dragnet/exporters/html_exporter.rb new file mode 100644 index 0000000..f72b577 --- /dev/null +++ b/lib/dragnet/exporters/html_exporter.rb @@ -0,0 +1,158 @@ +# frozen_string_literal: true + +require 'erb' + +require_relative '../helpers/repository_helper' +require_relative 'exporter' + +module Dragnet + module Exporters + # Creates an HTML report from the given Test Records and Errors data. + class HTMLExporter < Dragnet::Exporters::Exporter + include Dragnet::Helpers::RepositoryHelper + + TEMPLATE = File.join(__dir__, 'templates', 'template.html.erb').freeze + + # Generates the report and returns it as a string. + # @return [String] The generated HTML report. + def export + logger.info "Generating HTML report from template: #{TEMPLATE}..." + ERB.new(File.read(TEMPLATE)).result(binding) + end + + private + + # Returns the percentage that +num1+ represents with respect to +num2+ + # @param [Integer, Float] num1 A number. + # @param [Integer, Float] num2 A number. + # @return [Integer, Float] The percentage that +num1+ represents with + # respect to +num2+ rounded to two decimal places. + def percentage(num1, num2) + return 0.0 if num1.zero? || num2.zero? + + ((num1.to_f / num2) * 100).round(2) + end + + # @param [Dragnet::Repository] repository The repository whose branches + # should be retrieved. + # @return [Array] An array with the names of the branches that + # "contain" the current head of the repository (may be empty). + def software_branches(repository) + # (uniq needed because of remote/local branches) + repository.branches_with_head.map(&:name).uniq + rescue Git::GitExecuteError => e + logger.warn "Failed to read branches information from the repository at #{repository.path}" + logger.warn e.message + [] + end + + # Method used to memoize the output of the +group_by_requirement+ method. + # @see #group_by_requirement + # @return [Hash] A hash whose keys are the requirement IDs and whose + # values are arrays of MTRs + def test_records_by_requirement + @test_records_by_requirement ||= group_by_requirement + end + + # Groups the MTRs by the requirement(s) they are covering, if a MTR covers + # more than one requirement it will be added to all of them, if a + # requirement is covered by more than one MTR the requirement will end up + # with more than one MTR, example: + # + # { + # 'ESR_REQ_9675' => [MTR1], + # 'ESR_REQ_1879' => [MTR2, MTR3] + # 'ESR_REQ_4714' => [MTR3] + # } + # + # @return [Hash] A hash whose keys are the requirement IDs and whose + # values are arrays of MTRs + def group_by_requirement + tests_by_requirement = {} + + test_records.each do |test_record| + ids = *test_record.id + ids.each do |id| + tests_by_requirement[id] ||= [] + tests_by_requirement[id] << test_record + end + end + + tests_by_requirement + end + + # Returns the HTML code needed to render the Review Status of a MTR as a + # badge. + # @param [Dragnet::TestRecord] test_record The Test Record. + # @return [String] The HTML code to display the Test Record's review + # status as a badge. + def review_status_badge(test_record) + if test_record.review_status + color = test_record.reviewed? ? 'green' : 'red' + review_status = test_record.review_status.capitalize + else + color = 'gray' + review_status = '(unknown)' + end + + badge_html(color, review_status) + end + + # Returns the HTML code needed to display the verification result of a MTR + # (the color and the text inside the badge are picked in accordance to the + # given result). + # @param [Dragnet::VerificationResult] verification_result The result of + # the verification for a given +TestRecord+ + # @return [String] The HTML code needed to display the result as a badge. + def verification_result_badge(verification_result) + badge_html( + verification_result_color(verification_result), + verification_result.status.capitalize + ) + end + + # Returns a color that depends on the verification result for a Test + # Record. To be used on HTML elements. + # @param [Dragnet::VerificationResult] verification_result The + # +VerificationResult+ object. + # @return [String] The corresponding color (depends on the +status+ field + # of the +VerificationResult+ object). + def verification_result_color(verification_result) + case verification_result.status + when :passed + 'green' + when :skipped + 'yellow' + else + 'red' + end + end + + # Returns the color that should be used for the highlight line on the left + # of the card given the result of the MTR's verification. + # @param [Dragnet::VerificationResult] verification_result The + # +VerificationResult+ object associated with the +TestRecord+ being + # rendered on the card. + def card_color(verification_result) + verification_result_color(verification_result) + end + + # Returns the HTML string to produce a Badge + # @param [String] color The color of the badge. + # @param [String] text The text that goes inside the badge. + # @return [String] The HTML code to produce a badge with the given color + # and text. + def badge_html(color, text) + "#{text}" + end + + # Converts the ID (+String+) or IDs (+Array+) of a +TestRecord+ + # object into a string that can be safely rendered in the HTML report. + # @param [Dragnet::TestRecord] test_record The +TestRecord+ object. + # @return [String] A string with the ID or IDs of the +TestRecord+ object. + def test_record_id_to_string(test_record) + Array(test_record.id).join(', ') + end + end + end +end diff --git a/lib/dragnet/exporters/id_generator.rb b/lib/dragnet/exporters/id_generator.rb new file mode 100644 index 0000000..cace9c3 --- /dev/null +++ b/lib/dragnet/exporters/id_generator.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +require 'digest' + +require_relative '../helpers/repository_helper' + +module Dragnet + module Exporters + # Generates unique IDs for the Manual Test Records by hashing some of their + # properties into a hexadecimal SHA1. + class IDGenerator + include Dragnet::Helpers::RepositoryHelper + + attr_reader :repository + + # @param [Dragnet::Repository] repository The repository where the MTR + # files are located. This allows the SHA1 to be calculated with relative + # paths to the MTRs' files. + def initialize(repository) + @repository = repository + end + + # Calculates the ID of the given MTR + # @param [Dragnet::TestRecord] test_record The record for which the ID + # should be calculated. + # @return [String] The ID for the given +TestRecord+. + # :reek:FeatureEnvy (Cannot be done in the TestRecord itself because it needs the Repository) + def id_for(test_record) + string = "#{relative_to_repo(test_record.source_file)}#{test_record.id}" + # noinspection RubyMismatchedReturnType (This is never nil) + Digest::SHA1.hexdigest(string)[0...16] + end + end + end +end diff --git a/lib/dragnet/exporters/json_exporter.rb b/lib/dragnet/exporters/json_exporter.rb new file mode 100644 index 0000000..1a61da6 --- /dev/null +++ b/lib/dragnet/exporters/json_exporter.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +require 'json' + +require_relative 'exporter' +require_relative 'id_generator' +require_relative 'serializers/test_record_serializer' + +module Dragnet + module Exporters + # Exports the results for the Manual Test Record verification to a JSON + # string. + class JSONExporter < ::Dragnet::Exporters::Exporter + # @return [String] A JSON string containing an array of objects, one for + # each Test Record. + def export + logger.info 'Exporting data to JSON' + test_records.map do |test_record| + ::Dragnet::Exporters::Serializers::TestRecordSerializer + .new(test_record, repository).serialize + .merge(id: id_generator.id_for(test_record)) + end.to_json + end + + private + + # @return [Dragnet::Exporters::IDGenerator] An instance of the IDGenerator + # class that can be used to calculate the ID for the exported MTRs. + def id_generator + @id_generator ||= ::Dragnet::Exporters::IDGenerator.new(repository) + end + end + end +end diff --git a/lib/dragnet/exporters/serializers.rb b/lib/dragnet/exporters/serializers.rb new file mode 100644 index 0000000..7c7be0a --- /dev/null +++ b/lib/dragnet/exporters/serializers.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +require_relative 'serializers/repo_serializer' +require_relative 'serializers/test_record_serializer' +require_relative 'serializers/verification_result_serializer' + +module Dragnet + module Exporters + # Namespace for the serializer classes used by the exporters. + module Serializers; end + end +end diff --git a/lib/dragnet/exporters/serializers/repo_serializer.rb b/lib/dragnet/exporters/serializers/repo_serializer.rb new file mode 100644 index 0000000..7f567c3 --- /dev/null +++ b/lib/dragnet/exporters/serializers/repo_serializer.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +require 'active_support' +require 'active_support/core_ext/object/blank' + +module Dragnet + module Exporters + module Serializers + # Serializes a +Repo+ object into a +Hash+ + class RepoSerializer + attr_reader :repo + + # @param [Dragnet::Repo] repo The +Repo+ object to serialize. + def initialize(repo) + @repo = repo + end + + # Serializes the given +Repo+ object. + # @return [Hash] A +Hash+ representing the given +Repo+ object. + def serialize + { + path: repo.path, + sha1: repo.sha1 + }.tap do |hash| + hash[:files] = serialize_files if repo.files.present? + end + end + + private + + # Serializes the array of files attached to the +Repo+ + # @return [Array] The array of file names (without the path to + # the repository). + def serialize_files + repo.files.map { |file| file.to_s.gsub("#{repo.path}/", '') } + end + end + end + end +end diff --git a/lib/dragnet/exporters/serializers/test_record_serializer.rb b/lib/dragnet/exporters/serializers/test_record_serializer.rb new file mode 100644 index 0000000..ded17f5 --- /dev/null +++ b/lib/dragnet/exporters/serializers/test_record_serializer.rb @@ -0,0 +1,101 @@ +# frozen_string_literal: true + +require 'active_support' +require 'active_support/core_ext/object/blank' + +require_relative '../../helpers/repository_helper' +require_relative 'repo_serializer' +require_relative 'verification_result_serializer' + +module Dragnet + module Exporters + module Serializers + # Serializes a +TestRecord+ object into a +Hash+. + class TestRecordSerializer + include ::Dragnet::Helpers::RepositoryHelper + + attr_reader :test_record, :repository + + # @param [Dragnet::TestRecord] test_record The +TestRecord+ object to + # serialize. + # @param [Dragnet::RepositoryBase] repository The +Repository+ object + # associated with the +TestRecord+. Used to render file paths relative + # to the repository instead of as absolute paths. + def initialize(test_record, repository) + @test_record = test_record + @repository = repository + end + + # rubocop:disable Metrics/AbcSize (because of the Hash) + # rubocop:disable Metrics/CyclomaticComplexity (because of the conditionals) + # rubocop:disable Metrics/PerceivedComplexity (because of the conditionals) + # rubocop:disable Metrics/MethodLength (because of he Hash) + + # @return [Hash] A +Hash+ representing the given +TestRecord+ object. + def serialize + { + refs: Array(test_record.id), + result: test_record.result, + review_status: render_review_status, + verification_result: serialized_verification_result, + + # TODO: Remove the started_at and finished_at attributes after solving + # https://esrlabs.atlassian.net/browse/JAY-493 + started_at: serialized_verification_result[:started_at], + finished_at: serialized_verification_result[:finished_at] + }.tap do |hash| + hash[:sha1] = test_record.sha1 if test_record.sha1.present? + hash[:owner] = Array(test_record.name).join(', ') if test_record.name.present? + hash[:description] = test_record.description if test_record.description.present? + hash[:test_method] = Array(test_record.test_method) if test_record.test_method.present? + + if test_record.tc_derivation_method.present? + hash[:tc_derivation_method] = Array(test_record.tc_derivation_method) + end + + hash[:review_comments] = test_record.review_comments if test_record.review_comments.present? + hash[:findings] = test_record.findings if test_record.findings? + hash[:files] = serialize_files if test_record.files.present? + hash[:repos] = serialize_repos if test_record.repos.present? + end + end + + # rubocop:enable Metrics/AbcSize + # rubocop:enable Metrics/CyclomaticComplexity + # rubocop:enable Metrics/PerceivedComplexity + # rubocop:enable Metrics/MethodLength + + private + + # Renders the +TestRecord+'s review status + # @return [String] The review status, either +'not_reviewed'+ or +'reviewed'+ + def render_review_status + "#{test_record.reviewed? ? nil : 'not_'}reviewed" + end + + # Serializes the files listed in the given +TestRecord+ + # @return [Array] An array of strings, one for each listed file. + def serialize_files + test_record.files.map { |file| relative_to_repo(file).to_s } + end + + # Serializes the +Repo+ objects attached to the +TestRecord+ + # @return [Array] An array of +Hash+es representing each of the + # +Repo+ objects associated with the +TestRecord+ + def serialize_repos + test_record.repos.map { |repo| ::Dragnet::Exporters::Serializers::RepoSerializer.new(repo).serialize } + end + + # Serializes the +VerificationResult+ object attached to the given + # +TestRecord+ + # @return [Hash] A +Hash+ representation of the +VerificationResult+ + # object. + def serialized_verification_result + @serialized_verification_result ||= ::Dragnet::Exporters::Serializers::VerificationResultSerializer.new( + test_record.verification_result + ).serialize + end + end + end + end +end diff --git a/lib/dragnet/exporters/serializers/verification_result_serializer.rb b/lib/dragnet/exporters/serializers/verification_result_serializer.rb new file mode 100644 index 0000000..b17327d --- /dev/null +++ b/lib/dragnet/exporters/serializers/verification_result_serializer.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +module Dragnet + module Exporters + module Serializers + # Serializes a +VerificationResult+ object into a +Hash+. + class VerificationResultSerializer + attr_reader :verification_result + + # Format used to serialize the +VerificationResult+'s date/time attributes. + DATE_FORMAT = '%F %T %z' + + # @param [Dragnet::VerificationResult] verification_result The + # +VerificationResult+ object to serialize. + def initialize(verification_result) + @verification_result = verification_result + end + + # @return [Hash] The +Hash+ representation of the given + # +VerificationResult+ object. + def serialize + { + status: verification_result.status, + started_at: verification_result.started_at.strftime(DATE_FORMAT), + finished_at: verification_result.finished_at.strftime(DATE_FORMAT), + runtime: verification_result.runtime + }.tap do |hash| + hash[:reason] = verification_result.reason if verification_result.reason + end + end + end + end + end +end diff --git a/lib/dragnet/exporters/templates/template.html.erb b/lib/dragnet/exporters/templates/template.html.erb new file mode 100644 index 0000000..0d32211 --- /dev/null +++ b/lib/dragnet/exporters/templates/template.html.erb @@ -0,0 +1,518 @@ + + + + Dragnet Report for <%= repository.multi? ? "Multiple Repositories" : shorten_sha1(repository.head.sha) %> + + + + +

+ +
+
+
+ + +
+
+
+
+

Configuration

+
+
+ + <% if repository.multi? %> + +
+ + + + + + + + + + <% repository.repositories.each do |repository_path, repository| %> + + + + + + + <% end %> + + +
RepositoryConfiguration
<%= repository_path %> +
+
Remote:
+
<%= repository.remote_uri_path %>
+
Software branch(es):
+
<%= software_branches(repository).join(', ') %>
+
Git sha1:
+
<%= repository.head.sha %>
+
Build:
+
-- Not implemented --
+
+
+
+ + <% else %> + +
+
Repository:
+
<%= repository.remote_uri_path %>
+
Software branch(es):
+
<%= software_branches(repository).join(', ') %>
+
Git sha1:
+
<%= repository.head.sha %>
+
Build:
+
-- Not implemented --
+
+ + <% end %> + +
+
+
+
+ +
+ + <% if test_records_by_requirement.any? %> + +
+
+
+
+
Requirements
+
+ + <% total_requirements = test_records_by_requirement.size %> + +
<%= total_requirements %>
+ + <% + requirements_by_status = test_records_by_requirement.group_by do |_requirement, test_records| + if test_records.all? { |test_record| test_record.verification_result.passed? } + :passed + elsif test_records.any? { |test_record| test_record.verification_result.failed? } + :failed + else + :skipped + end + end + + total_passed = requirements_by_status[:passed]&.size || 0 + total_skipped = requirements_by_status[:skipped]&.size || 0 + total_failed = requirements_by_status[:failed]&.size || 0 + passed_percent = percentage(total_passed, total_requirements) + skipped_percent = percentage(total_skipped, total_requirements) + failed_percent = percentage(total_failed, total_requirements) + %> + +
+
+
+
+
+
+
+ + Passed + <%= total_passed %> (<%= passed_percent %>%) +
+
+ + Failed + <%= total_failed %> (<%= failed_percent %>%) +
+
+ + Skipped + <%= total_skipped %> (<%= skipped_percent %>%) +
+
+
+
+
+ + <% end %> + +
+
+
+
+
Test cases
+
+ + <% total_test_records = test_records.size %> + +
<%= total_test_records %>
+
+ + <% + test_records_by_status = test_records.group_by do |test_record| + if test_record.reviewed? + test_record.findings? ? :skipped : :passed + else + :failed + end + end + + total_passed = test_records_by_status[:passed]&.size || 0 + total_skipped = test_records_by_status[:skipped]&.size || 0 + total_failed = test_records_by_status[:failed]&.size || 0 + passed_percent = percentage(total_passed, total_test_records) + skipped_percent = percentage(total_skipped, total_test_records) + failed_percent = percentage(total_failed, total_test_records) + %> + +
+
+
+
+
+
+ + Reviewed + <%= total_passed %> (<%= passed_percent %>%) +
+
+ + Not reviewed + <%= total_failed %> (<%= failed_percent %>%) +
+
+ + Findings + <%= total_skipped %> (<%= skipped_percent %>%) +
+
+
+
+
+
+ +
+

MTR Files

+
+
+
+

Overview

+
+
+ + + + + + + + + + + <% errors.each do |error| %> + + + + + + + + <% end %> + + <% test_records.each do |test_record| %> + + + + + + + + <% end %> + + +
FileStatusReason
<%= relative_to_repo(error[:file]) %>Failed<%= error[:message] %>
<%= error[:exception].message %>
<%= relative_to_repo(test_record.source_file) %>Successfully Loaded-
+
+
+
+ +

Test results

+ +
+
+
+
+

Overview

+
+
+ + + + + + + + + + + + + + + <% test_records.each_with_index do |test_record, index| %> + + + + + + + + + + + + <% end %> + + +
#Requirement IDSHA1FilesReview StatusTest ResultDetails
<%= index + 1 %><%= test_record_id_to_string(test_record) %><%= test_record.sha1 ? shorten_sha1(test_record.sha1) : '(None)' %> + + <% if test_record.files&.any? %> + + <%= test_record.files.map { |file| relative_to_repo(file) }.join('
') %> + + <% else %> + + (None) + + <% end %> + +
<%= review_status_badge(test_record) %><%= verification_result_badge(test_record.verification_result) %> + + + + + +
+
+
+
+
+ + <% test_records.each_with_index do |test_record, index| %> + +
+
+
+
+
+

<%= test_record_id_to_string(test_record) %>

+
+
+
+
MTR file:
+
<%= relative_to_repo(test_record.source_file) %>
+ + <% if test_record.name.present? %> + +
Tester name:
+
<%= test_record.name.join(', ') %>
+ + <% end %> + + <% if test_record.test_method.present? %> + +
Test method:
+
<%= test_record.test_method.join(', ') %>
+ + <% end %> + + <% if test_record.tc_derivation_method.present? %> + +
Derivation method:
+
<%= test_record.tc_derivation_method.join(', ') %>
+ + <% end %> + + <% if test_record.repos %> + +
Repositories:
+
+
    + + <% test_record.repos.each do |repo| %> + +
  • + + <%= repo.path %>
    + <%= repo.sha1 %>
    + + <% repo.files&.each do |file| %> + +
      + +
    • <%= relative_to_repo(file).sub("#{repo.path}/", '') %>
    • + +
    + + <% end %> + +
  • + + <% end %> + +
+
+ + <% else %> + +
SHA1:
+
<%= test_record.sha1 %>
+
Files:
+
+ + <% if test_record.files&.any? %> + + <%= test_record.files.map { |file| relative_to_repo(file) }.join('
') %> + + <% else %> + + (None) + + <% end %> + +
+ + <% end %> + +
ASIL:
+
-- Not implemented --
+
SECL:
+
-- Not implemented --
+
Description:
+
+ <%= test_record.description %> +
+
Test Result:
+
<%= verification_result_badge(test_record.verification_result) %>
+ + <% unless test_record.verification_result.passed? %> + +
Reason:
+
<%= test_record.verification_result.reason %>
+ + <% end %> + +
Review Status:
+
<%= review_status_badge(test_record) %>
+
Review Comments:
+
<%= test_record.review_comments || '(None)' %>
+
+
+
+
+
+ + <% end %> + +
+
+
+ +
+
+ + diff --git a/lib/dragnet/helpers/repository_helper.rb b/lib/dragnet/helpers/repository_helper.rb new file mode 100644 index 0000000..b38070c --- /dev/null +++ b/lib/dragnet/helpers/repository_helper.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +module Dragnet + module Helpers + # Some helper methods to use when working with repositories. + module RepositoryHelper + # @return [String] The first 10 characters of the given string (normally + # used to shorten SHA1s when building messages). + def shorten_sha1(sha1) + sha1[0...10] + end + + # @return [Pathname] The base path of the repository where the MTR and the + # source files are located. Used to present relative paths. + def repo_base + @repo_base ||= repository.path + end + + # Transforms the given path into a path relative to the repository's root + # @param [Pathname] path The absolute path. + # @return [Pathname] A path relative to the repository's root. + def relative_to_repo(path) + path.relative_path_from(repo_base) + end + end + end +end diff --git a/lib/dragnet/multi_repository.rb b/lib/dragnet/multi_repository.rb new file mode 100644 index 0000000..defa1d7 --- /dev/null +++ b/lib/dragnet/multi_repository.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +require_relative 'base_repository' + +module Dragnet + # This is a dummy class that acts as a placeholder when Dragnet is executed + # on a multi-repo set-up. Since there is no Git repository in the directory + # where git-repo runs git commands cannot be executed there only in the inner + # repositories. + # + # This class's job is to raise a particular error when a git operation is + # attempted directly on this directory so that Dragnet can recognize the cause + # of the error and display it correctly. + # + # It also acts as a collection of repositories. It stores a collection of + # +Dragnet::Repository+ objects, which point to the actual repositories (this + # is just so that the same repository isn't initialized multiple times). + class MultiRepository < Dragnet::BaseRepository + attr_reader :repositories + + # @param [Pathname] path Path to the directory where the inner repositories + # reside. + def initialize(path:) + super + @repositories = {} + end + + # @return [TrueClass] It always returns true + def multi? + true + end + + private + + # @param [Symbol] method_name The name of the method that was invoked. + # @raise [Dragnet::Errors::IncompatibleRepositoryError] Is always raised + # with a description of the method that was invoked and a possible cause + # for the failure. + def incompatible_repository(method_name) + super( + "Failed to perform the action '#{method_name}' on '#{path}'."\ + " There isn't a git repository there. If you are running with the"\ + ' --multi-repo command line switch make sure that all of your MTRs'\ + " contain a valid 'repos' attribute." + ) + end + end +end diff --git a/lib/dragnet/repo.rb b/lib/dragnet/repo.rb new file mode 100644 index 0000000..1f8143a --- /dev/null +++ b/lib/dragnet/repo.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +require_relative 'validators/entities/repo_validator' + +module Dragnet + # Represents a repository, (for MTRs which reference multiple repositories in + # a multi-repo project, often managed with git-repo) + class Repo + attr_accessor :path, :sha1, :files + + # @param [Hash] args The data for the Repo + # @option args [String] :path The path where the repository is stored. + # @option args [String] :sha1 The SHA1 the repository had when the MTR was + # created. + # @option args [String, Array, nil] :files The file or array of + # files covered by the MTR. + def initialize(args) + @path = args[:path] + @sha1 = args[:sha1] + @files = args[:files] + end + + # Validates the +Repo+ instance (by checking each of its attributes). + # @raise [Dragnet::Errors::ValidationError] If any of the attributes of the + # +Repo+ object is invalid. + # @see Dragnet::Validators::Entities::RepoValidator#validate + def validate + Dragnet::Validators::Entities::RepoValidator.new(self).validate + end + end +end diff --git a/lib/dragnet/repository.rb b/lib/dragnet/repository.rb new file mode 100644 index 0000000..318889d --- /dev/null +++ b/lib/dragnet/repository.rb @@ -0,0 +1,77 @@ +# frozen_string_literal: true + +require 'forwardable' + +require_relative 'base_repository' + +module Dragnet + # A small wrapper around a Git Repository object. It provides some useful + # methods needed during the verify process as well as for reporting. + class Repository < Dragnet::BaseRepository + extend Forwardable + + attr_reader :git + + def_delegators :@git, :branch, :branches, :diff + + # Creates a new instance of the class. Tries to open the given path as a Git + # repository. + # @param [Pathname] path The path where the root of the repository is located. + # @raise [ArgumentError] If the given path is not a valid git repository. + def initialize(path:) + super + @git = Git.open(path) + end + + # @return [Git::Object::Commit] The +Commit+ object at the +HEAD+ of the + # repository. + def head + @head ||= git.object('HEAD') + end + + # Returns the URI path of the repository (extracted from its first remote + # [assumed to be the origin]). Example: + # + # ssh://jenkins@gerrit.int.esrlabs.com:29418/tools/dragnet -> /tools/dragnet + # + # @return [String] The URI path of the repository + def remote_uri_path + URI.parse(git.remotes.first.url).path + end + + # @return [FalseClass] It always returns false + def multi? + false + end + + # Returns an array of all the branches that include the given commit. + # @param [String] commit The SHA1 of the commit to look for. + # @return [Array] An array with all the branches that contain + # the given commit. + def branches_with(commit) + branches.select { |branch| branch.contains?(commit) } + end + + # Returns an array of all the branches that include the current HEAD. + # @return [Array] An array with all the branches that contain + # the current HEAD. + def branches_with_head + @branches_with_head ||= branches_with(head.sha) + end + + private + + # @param [Symbol] method_name The name of the method that was invoked. + # @raise [Dragnet::Errors::IncompatibleRepositoryError] Is always raised + # with a description of the method that was invoked and a possible cause + # for the failure. + def incompatible_repository(method_name) + super( + "Failed to perform the action '#{method_name}' on '#{path}'."\ + ' The path was not set-up as a multi-repo path. If you are running'\ + ' without the --multi-repo command line switch make sure that none of'\ + " your MTRs have a 'repos' attribute or run with the --multi-repo switch" + ) + end + end +end diff --git a/lib/dragnet/test_record.rb b/lib/dragnet/test_record.rb new file mode 100644 index 0000000..4337a03 --- /dev/null +++ b/lib/dragnet/test_record.rb @@ -0,0 +1,91 @@ +# frozen_string_literal: true + +require_relative 'validators/entities/test_record_validator' + +module Dragnet + # Represents a Manual Test Record loaded from a MTR file. + class TestRecord + PASSED_RESULT = 'passed' + REVIEWED_STATUS = 'reviewed' + NO_FINDINGS = 'no findings' + + # :reek:Attribute (This is an entity class) + + attr_accessor :id, :result, :sha1, :name, :description, :files, :repos, + :review_status, :review_comments, :findings, :test_method, + :tc_derivation_method, :source_file, :verification_result + + # rubocop:disable Metrics/AbcSize (There isn't much that can be done here, + # those are the attributes an MTR has). + # :reek:FeatureEnvy (Refers to args as much as it refers to itself) + + # Creates a new instance of the class. + # @param [Hash] args The data for the Manual Test Record + # @option args [String] :id The ID of the MTR + # @option args [String] :result The result of the Manual Test. + # @option args [String] :sha1 The SHA1 of the commit in which the Manual + # Test was performed. + # @option args [String, Array, nil] :name The name of the person who + # performed the Manual Test. + # @option args [String, nil] :description The description of the Manual + # Test, normally which actions were performed and what it was mean to + # test. + # @option args [String, Array, nil] :files The files involved in the + # MTR, these are the files which will be checked for changes when + # evaluating the validity of the MTR. + # @option args [Array, nil] :repos An array of +Hash+es with the + # information about the repositories that are involved in the MTR, these + # repositories will be checked for changes during the evaluation of the + # MTR. + # @option args [String, nil] :review_status or :reviewstatus The review + # status of the MTR. (Normally changed when someone other than the tester + # verifies the result of the Manual Test) + # @option args [String, nil] :review_comments or :reviewcomments The + # comments left by the person who performed the review of the Manual Test. + # @option args [String, nil] :findings The findings that the reviewer + # collected during the review process (if any). + # @option args [String, Array, nil] :test_method The method(s) used + # to carry out the test. + # @option args [String, Array, nil] :tc_derivation_method: The + # method(s) used to derive the test case, + # @note Either +:files+ or +:repos+ should be present, not both. + def initialize(args) + @id = args[:id] + @result = args[:result] + @sha1 = args[:sha1] + @name = args[:name] + @description = args[:description] + @files = args[:files] + @repos = args[:repos] + @review_status = args[:review_status] || args[:reviewstatus] + @review_comments = args[:review_comments] || args[:reviewcomments] + @findings = args[:findings] + @test_method = args[:test_method] + @tc_derivation_method = args[:tc_derivation_method] + end + # rubocop:enable Metrics/AbcSize + + # Validates the MTR's fields + # @raise [Dragnet::Errors::ValidationError] If the validation fails. + def validate + Dragnet::Validators::Entities::TestRecordValidator.new(self).validate + end + + # @return [Boolean] True if the Manual Test passed, false otherwise. + def passed? + result == PASSED_RESULT + end + + # @return [Boolean] True if the Manual Test Record has been reviewed, false + # otherwise. + def reviewed? + review_status == REVIEWED_STATUS + end + + # @return [Boolean] True if the Manual Test Record has findings (problems + # annotated during the review), false otherwise. + def findings? + !(findings.nil? || findings.strip.empty? || findings.downcase == NO_FINDINGS) + end + end +end diff --git a/lib/dragnet/validator.rb b/lib/dragnet/validator.rb new file mode 100644 index 0000000..1775a2f --- /dev/null +++ b/lib/dragnet/validator.rb @@ -0,0 +1,79 @@ +# frozen_string_literal: true + +require 'colorize' + +require_relative 'validators/data_validator' +require_relative 'validators/files_validator' +require_relative 'validators/repos_validator' + +module Dragnet + # Validates a set of Manual Test Record files. That means, checking that they + # can be read, that they are valid YAML files, that they have the expected + # keys and that these keys have sensible values. + class Validator + attr_reader :files, :path, :logger, :errors, :valid_files + + # Creates a new instance of the class. + # @param [Array] files An array with the MTR files to validate. + # @param [Pathname] path The path where the MTR files are located. + # @param [#info, #error] logger A logger object to use for output. + def initialize(files:, path:, logger:) + @files = files + @path = path + @logger = logger + end + + # Validates the given files. + # @return [Array] An array of +TestRecord+s, one for + # each valid MTR file (invalid files will be added to the +errors+ array). + # The returned hash has the following structure: + def validate + logger.info('Validating MTR Files...') + + @errors = [] + @valid_files = files.map { |file| validate_file(file) }.compact + end + + private + + # Validates the given file + # @param [Pathname] file The file to be validated. + # @return [Dragnet::TestRecord, nil] A +TestRecord+ object or +nil+ if the + # file is invalid. + # rubocop:disable Metrics/AbcSize (because of logging). + def validate_file(file) + logger.info "Validating #{file}..." + data = YAML.safe_load(File.read(file)) + test_record = Dragnet::Validators::DataValidator.new(data, file).validate + Dragnet::Validators::FilesValidator.new(test_record, path).validate + Dragnet::Validators::ReposValidator.new(test_record, path).validate + + logger.info "#{'✔ SUCCESS'.colorize(:light_green)} #{file} Successfully loaded" + test_record + rescue SystemCallError => e + push_error(file, 'IO Error: Cannot read the specified file', e) + rescue Psych::Exception => e + push_error(file, 'YAML Parsing Error', e) + rescue Dragnet::Errors::YAMLFormatError => e + push_error(file, 'YAML Formatting Error', e) + rescue Dragnet::Errors::FileNotFoundError => e + push_error(file, 'Referenced file not found in repository', e) + rescue Dragnet::Errors::RepoPathNotFoundError => e + push_error(file, 'Referenced repository not found', e) + end + # rubocop:enable Metrics/AbcSize + + # Pushes an entry into the +errors+ array. + # @param [Pathname] file The file that contains the error. + # @param [String] message A general description of the message. + # @param [Exception] exception The raised exception (through which the file + # was branded invalid) + # @return [nil] Returns nil so that +validate_file+ can return nil for + # invalid files. + def push_error(file, message, exception) + errors << { file: file, message: message, exception: exception } + logger.error "#{'✘ FAILED'.colorize(:light_red)} #{file} Failed: #{message} - #{exception.message}" + nil + end + end +end diff --git a/lib/dragnet/validators.rb b/lib/dragnet/validators.rb new file mode 100644 index 0000000..25c4990 --- /dev/null +++ b/lib/dragnet/validators.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +require_relative 'validators/data_validator' +require_relative 'validators/entities' +require_relative 'validators/fields' +require_relative 'validators/files_validator' +require_relative 'validators/validator' + +module Dragnet + # Namespace for Validator classes. + module Validators; end +end diff --git a/lib/dragnet/validators/data_validator.rb b/lib/dragnet/validators/data_validator.rb new file mode 100644 index 0000000..c5e951b --- /dev/null +++ b/lib/dragnet/validators/data_validator.rb @@ -0,0 +1,75 @@ +# frozen_string_literal: true + +require 'active_support' +require 'active_support/core_ext/hash/keys' + +require_relative '../test_record' +require_relative 'validator' + +module Dragnet + module Validators + # Validates the data (key-value pairs) inside an MTR file. Verifies the + # structure, the required keys and their types. + class DataValidator < Dragnet::Validators::Validator + attr_reader :data, :source_file + + # Creates a new instance of the class + # @param [Hash] data The data inside the YAML (after parsing) + # @param [Pathname] source_file The path to the file from which the MTR + # data was loaded. + def initialize(data, source_file) + @data = data + @source_file = source_file + end + + # Validates the given data + # @return [Dragnet::TestRecord] A +TestRecord+ object created + # from the given data (if the data was valid). + # @raise [Dragnet::Errors::YAMLFormatError] If the data is invalid. The + # raised exceptions contains a message specifying why the data is + # invalid. + def validate + yaml_format_error("Incompatible data structure. Expecting a Hash, got a #{data.class}") unless data.is_a?(Hash) + data.deep_symbolize_keys! + + # A call to chomp for strings is needed because the following YAML + # syntax: + # + # findings: > + # no findings + # + # causes the string values to end with a newline ("\n"): + data.transform_values! { |value| value.is_a?(String) ? value.chomp : value } + test_record = create_mtr(data) + validate_mtr(test_record) + end + + private + + # @param [Hash] data A hash with the data for the +TestRecord+ + # @see Dragnet::TestRecord#initialize + def create_mtr(data) + Dragnet::TestRecord.new(data).tap do |test_record| + test_record.source_file = source_file + end + end + + # Creates a +Dragnet::TestRecord+ with the given data and runs its + # validation. If the validation is successful the +TestRecord+ + # object is returned, if the validation fails an error is raised. + # @param [Dragnet::TestRecord] test_record The +TestRecord+ object to + # validate. + # @return [Dragnet::TestRecord] The given +TestRecord+ object if the + # validation passed. + # @raise [Dragnet::Errors::YAMLFormatError] If the data is invalid. The + # raised exceptions contains a message specifying why the data is + # invalid. + def validate_mtr(test_record) + test_record.validate + test_record + rescue Dragnet::Errors::ValidationError => e + yaml_format_error(e.message) + end + end + end +end diff --git a/lib/dragnet/validators/entities.rb b/lib/dragnet/validators/entities.rb new file mode 100644 index 0000000..4a4a015 --- /dev/null +++ b/lib/dragnet/validators/entities.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +require_relative 'entities/repo_validator' +require_relative 'entities/test_record_validator' + +module Dragnet + module Validators + # Namespace for Dragnet's Entity Validators (validators that deal with data + # objects / models). + module Entities; end + end +end diff --git a/lib/dragnet/validators/entities/repo_validator.rb b/lib/dragnet/validators/entities/repo_validator.rb new file mode 100644 index 0000000..9d6b71b --- /dev/null +++ b/lib/dragnet/validators/entities/repo_validator.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +require_relative '../fields/sha1_validator' +require_relative '../fields/files_validator' +require_relative '../fields/path_validator' + +module Dragnet + module Validators + module Entities + # Validates a +Dragnet::Repo+ object, by checking its attributes. + class RepoValidator + attr_reader :repo + + # @param [Dragnet::Repo] repo An instance of +Dragnet::Repo+ to validate. + def initialize(repo) + @repo = repo + end + + # Validates the instance of the +Dragnet::Repo+ object by checking each + # of its attributes. + # @raise [Dragnet::Errors::ValidationError] If any of the fields in the + # given +Dragnet::Repo+ object fails the validation. + def validate + Dragnet::Validators::Fields::SHA1Validator.new.validate('repos[sha1]', repo.sha1) + Dragnet::Validators::Fields::PathValidator.new.validate('repos[path]', repo.path) + repo.files = Dragnet::Validators::Fields::FilesValidator.new.validate('repos[files]', repo.files) + end + end + end + end +end diff --git a/lib/dragnet/validators/entities/test_record_validator.rb b/lib/dragnet/validators/entities/test_record_validator.rb new file mode 100644 index 0000000..25269e4 --- /dev/null +++ b/lib/dragnet/validators/entities/test_record_validator.rb @@ -0,0 +1,93 @@ +# frozen_string_literal: true + +require_relative '../fields/description_validator' +require_relative '../fields/files_validator' +require_relative '../fields/id_validator' +require_relative '../fields/meta_data_field_validator' +require_relative '../fields/repos_validator' +require_relative '../fields/result_validator' +require_relative '../fields/sha1_validator' + +require_relative '../../errors/validation_error' + +module Dragnet + module Validators + module Entities + # Validates a MTR object + class TestRecordValidator + attr_reader :test_record + + # Creates a new instance of the class. + # @param [Dragnet::TestRecord] test_record The test record to validate. + def initialize(test_record) + @test_record = test_record + end + + # Validates the given test record + # @raise [Dragnet::Errors::ValidationError] If the validation fails. + def validate + repos_xor_files + repos_xor_sha1 + + Dragnet::Validators::Fields::IDValidator.new.validate('id', test_record.id) + Dragnet::Validators::Fields::DescriptionValidator.new.validate('description', test_record.description) + validate_meta_data_fields + + test_record.files = Dragnet::Validators::Fields::FilesValidator.new.validate('files', test_record.files) + test_record.result = Dragnet::Validators::Fields::ResultValidator.new.validate('result', test_record.result) + end + + private + + # @raise [Dragnet::Errors::ValidationError] If the MTR has both a + # +files+ and a +repos+ attribute. + def repos_xor_files + return unless test_record.files && test_record.repos + + raise Dragnet::Errors::ValidationError, + "Invalid MTR: #{test_record.id}. Either 'files' or 'repos' should be provided, not both" + end + + # Executes the validation over the +repos+ attribute and then verifies + # if the +sha1+ attribute was also given. If it was, an error is + # raised. If +repos+ is not present, then the +sha1+ attribute is + # validated. + # + # This happens in this order to leverage the fact that the + # +ReposValidator+ returns +nil+ for empty +Array+s. So if +repos+ is + # given as en empty +Array+ the MTR will still be considered valid + # (provided it has a SHA1). + # + # @raise [Dragnet::Errors::ValidationError] If the validation of the + # +repos+ attribute fails, if both +repos+ and +sha1+ are present or + # if the validation of the +sha1+ attribute fails. + def repos_xor_sha1 + test_record.repos = Dragnet::Validators::Fields::ReposValidator.new.validate('repos', test_record.repos) + + unless test_record.repos + Dragnet::Validators::Fields::SHA1Validator.new.validate('sha1', test_record.sha1) + return + end + + return unless test_record.sha1 + + raise Dragnet::Errors::ValidationError, + "Invalid MTR: #{test_record.id}. Either 'repos' or 'sha1' should be provided, not both" + end + + # Validates the meta-data fields of the Test Record. + # @raise [Dragnet::Errors::ValidationError] If any of the meta-data + # fields fail the validation. + def validate_meta_data_fields + meta_data_validator = Dragnet::Validators::Fields::MetaDataFieldValidator.new + + test_record.name = meta_data_validator.validate('name', test_record.name) + test_record.test_method = meta_data_validator.validate('test_method', test_record.test_method) + test_record.tc_derivation_method = meta_data_validator.validate( + 'tc_derivation_method', test_record.tc_derivation_method + ) + end + end + end + end +end diff --git a/lib/dragnet/validators/fields.rb b/lib/dragnet/validators/fields.rb new file mode 100644 index 0000000..29b5c81 --- /dev/null +++ b/lib/dragnet/validators/fields.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require_relative 'fields/description_validator' +require_relative 'fields/files_validator' +require_relative 'fields/id_validator' +require_relative 'fields/meta_data_field_validator' +require_relative 'fields/path_validator' +require_relative 'fields/repos_validator' +require_relative 'fields/result_validator' +require_relative 'fields/sha1_validator' + +module Dragnet + module Validators + # Namespace module for entity fields validators. + module Fields; end + end +end diff --git a/lib/dragnet/validators/fields/description_validator.rb b/lib/dragnet/validators/fields/description_validator.rb new file mode 100644 index 0000000..3308fb1 --- /dev/null +++ b/lib/dragnet/validators/fields/description_validator.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +require_relative 'field_validator' + +module Dragnet + module Validators + module Fields + # Validates the +description+ field for a MTR. + class DescriptionValidator < Dragnet::Validators::Fields::FieldValidator + # Validates a MTR's description + # @param [String] key The name of the key + # @param [Object] value The value of the key + # @raise [Dragnet::Errors::ValidationError] If the description contains + # anything but a +String+ or +nil+. + # :reek:NilCheck (Only +nil+ is allowed, +false+ should be considered invalid). + def validate(key, value) + return if value.nil? + + validate_type(key, value, String) + end + end + end + end +end diff --git a/lib/dragnet/validators/fields/field_validator.rb b/lib/dragnet/validators/fields/field_validator.rb new file mode 100644 index 0000000..152e89a --- /dev/null +++ b/lib/dragnet/validators/fields/field_validator.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +require_relative '../../errors/validation_error' + +module Dragnet + module Validators + module Fields + # Base class for all the validators used to validate individual fields + # inside entities. + class FieldValidator + def validate(_key, _value) + raise NotImplementedError, "#validate method not implemented in #{self.class}" + end + + private + + # Validates the presence of a value + # @param [String, Symbol] key The key associated with the value. + # @param [Object] value The value to validate. + # @raise [Dragnet::Errors::ValidationError] If the given value is not + # present (i.e. is +nil+) + def validate_presence(key, value) + validation_error("Missing required key: #{key}") if value.nil? + end + + # Validates the type of the given value. + # @param [String, Symbol] key The key associated with the value. + # @param [Object] value The value to validate. + # @param [Array] expected_types The allowed types for the given + # value. + # @raise [Dragnet::Errors::ValidationError] If the given value has a type + # which is not in the given array of expected types. + def validate_type(key, value, *expected_types) + return if expected_types.include?(value.class) + + validation_error( + "Incompatible type for key #{key}: "\ + "Expected #{expected_types.join(', ')} got #{value.class} instead" + ) + end + + # Raises a +Dragnet::Errors::ValidationError+ with the given message. + # @param [String] message The message for the error. + # @raise [Dragnet::Errors::ValidationError] Is always raised. + def validation_error(message) + raise Dragnet::Errors::ValidationError, message + end + + # Validates that all elements inside the given array are of the + # expected type + # @param [String, Symbol] key The key associated with the array. + # @param [Array] array The array whose types should be checked. + # @param [Class] expected_type The type the elements inside the array + # should have. + # @raise [Dragnet::Errors::ValidationError] If any of the elements inside + # the given array is of a different type. + def validate_array_types(key, array, expected_type) + incompatible_value = array.find { |val| !val.is_a?(expected_type) } + return unless incompatible_value + + validation_error( + "Incompatible type for key #{key}: Expected a Array<#{expected_type}>. "\ + "Found a(n) #{incompatible_value.class} inside the array" + ) + end + end + end + end +end diff --git a/lib/dragnet/validators/fields/files_validator.rb b/lib/dragnet/validators/fields/files_validator.rb new file mode 100644 index 0000000..121e206 --- /dev/null +++ b/lib/dragnet/validators/fields/files_validator.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +require_relative 'field_validator' + +module Dragnet + module Validators + module Fields + # Validates the files field on a Manual Test Record + class FilesValidator < Dragnet::Validators::Fields::FieldValidator + # Validates the MTR's +files+ array. + # @param [String] key The name of the key + # @param [Object] value The value of the key + # @return [Array, nil] If +files+ is an Array or a String then + # an array is returned, if +files+ is +nil+ then +nil+ is returned. + # @raise [Dragnet::Errors::ValidationError] If the +files+ key is not a + # +String+ or an +Array+ of +String+s. + def validate(key, value) + return unless value + + validate_type(key, value, String, Array) + value = *value + validate_array_types(key, value, String) + + value + end + end + end + end +end diff --git a/lib/dragnet/validators/fields/id_validator.rb b/lib/dragnet/validators/fields/id_validator.rb new file mode 100644 index 0000000..f71ad44 --- /dev/null +++ b/lib/dragnet/validators/fields/id_validator.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +require_relative 'field_validator' + +module Dragnet + module Validators + module Fields + # Validates the ID Field for Manual Test Records + class IDValidator < Dragnet::Validators::Fields::FieldValidator + # Validates the Requirement ID(s) of the MTR + # @param [String] key The name of the key + # @param [Object] value The value of the key + # @raise [Dragnet::Errors::ValidationError] If the Requirement ID(s) are + # missing, they are not a String or an Array of Strings if they contain + # a disallowed character or (in the case of an Array) any of its + # elements is not a String. + def validate(key, value) + validate_presence(key, value) + validate_type(key, value, String, Array) + + if value.is_a?(String) + match = value.match(/,|\s/) + return unless match + + validation_error( + "Disallowed character '#{match}' found in the value for key #{key}. "\ + 'To use multiple requirement IDs please put them into an array' + ) + else + validate_array_types(key, value, String) + end + end + end + end + end +end diff --git a/lib/dragnet/validators/fields/meta_data_field_validator.rb b/lib/dragnet/validators/fields/meta_data_field_validator.rb new file mode 100644 index 0000000..5416fb0 --- /dev/null +++ b/lib/dragnet/validators/fields/meta_data_field_validator.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +require_relative 'field_validator' +require_relative '../../errors/validation_error' + +module Dragnet + module Validators + module Fields + # Base class to validate the fields that are part of the meta-data group. + # This means: Either +String+ +Array+ or +nil+ as value. + class MetaDataFieldValidator < Dragnet::Validators::Fields::FieldValidator + # Validates the specified attribute as a meta-data field. + # @param [String] key The name of the key + # @param [Object] value The value of the key + # @raise [Dragnet::Errors::ValidationError] If the attribute fails the + # validation. + # @return [nil] If +value+ is +nil+ or an empty array. + # @return [Array] If +value+ is a +String+ or an +Arry+ + def validate(key, value) + return unless value + + validate_type(key, value, String, Array) + + if value.is_a?(Array) + return if value.empty? + + validate_array_types(key, value, String) + value + else + [value] + end + end + end + end + end +end diff --git a/lib/dragnet/validators/fields/path_validator.rb b/lib/dragnet/validators/fields/path_validator.rb new file mode 100644 index 0000000..645cfde --- /dev/null +++ b/lib/dragnet/validators/fields/path_validator.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +require_relative 'field_validator' + +module Dragnet + module Validators + module Fields + # Validates the +path+ attribute of a +Repo+ object. + class PathValidator < Dragnet::Validators::Fields::FieldValidator + # Validates the Path of the repository. + # @param [String] key The name of the key + # @param [Object] value The value of the key + # @raise [Dragnet::Errors::ValidationError] If the path is missing, or + # it isn't a String. + def validate(key, value) + validate_presence(key, value) + validate_type(key, value, String) + end + end + end + end +end diff --git a/lib/dragnet/validators/fields/repos_validator.rb b/lib/dragnet/validators/fields/repos_validator.rb new file mode 100644 index 0000000..fa55904 --- /dev/null +++ b/lib/dragnet/validators/fields/repos_validator.rb @@ -0,0 +1,62 @@ +# frozen_string_literal: true + +require_relative '../../repo' +require_relative 'field_validator' + +module Dragnet + module Validators + module Fields + # Validates that the +repos+ attribute in an MTR is valid. This means: + # * It is either a +Hash+ or an +Array+ of +Hash+es. + # * The attributes inside each of the +Hash+es are also valid. + class ReposValidator < Dragnet::Validators::Fields::FieldValidator + # Validates the MTR's +repos+ field. + # @param [String] key The name of the key (usually +'repos'+) + # @param [Object] value The value associated to the attribute. + # @return [Array, nil] If +value+ is a valid +Hash+ or a + # valid +Array+ of +Hash+es an +Array+ of +Dragnet::Repo+ objects is + # returned. If +value+ is +nil+, +nil+ is returned. + # @raise [Dragnet::Errors::ValidationError] If +value+ is not a +Hash+ + # or an +Array+ of +Hash+es or the attributes inside the +Hash+es are + # invalid. + # @see Dragnet::Repo#validate + def validate(key, value) + return unless value + + validate_type(key, value, Hash, Array) + + if value.is_a?(Array) + return if value.empty? + + validate_array_types(key, value, Hash) + else + # This is needed because trying to apply the splat operator over a + # Hash will result in an Array of Arrays (one for each of the Hash's + # key pairs). + value = [value] + end + + create_repos(value) + end + + private + + # @param [Array] hashes The array of +Hash+es from which the Repo + # objects shall be created. + # @return [Array] The array of +Dragnet::Repo+ objects + # that result from using each of the given +Hash+es as parameters for + # the constructor. + # @raise [Dragnet::Errors::ValidationError] If the attributes inside the + # +Hash+es are invalid. + # @see Dragnet::Repo#validate + def create_repos(hashes) + hashes.map do |hash| + repo = Dragnet::Repo.new(**hash) + repo.validate + repo + end + end + end + end + end +end diff --git a/lib/dragnet/validators/fields/result_validator.rb b/lib/dragnet/validators/fields/result_validator.rb new file mode 100644 index 0000000..783d31c --- /dev/null +++ b/lib/dragnet/validators/fields/result_validator.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require_relative 'field_validator' + +module Dragnet + module Validators + module Fields + # Validates the result field of an MTR Record + class ResultValidator < Dragnet::Validators::Fields::FieldValidator + VALID_RESULTS = %w[passed failed].freeze + + # Validates the MTR's result + # @param [String] key The name of the key + # @param [Object] value The value of the key + # @return [String] The downcase version of the result field. + # @raise [Dragnet::Errors::ValidationError] If the result is missing, if + # it isn't a String or is not one of the allowed values for the field. + def validate(key, value) + validate_presence(key, value) + validate_type(key, value, String) + + value = value.downcase + return value if VALID_RESULTS.include?(value) + + validation_error( + "Invalid value for key result: '#{value}'. "\ + "Valid values are #{VALID_RESULTS.join(', ')}" + ) + end + end + end + end +end diff --git a/lib/dragnet/validators/fields/sha1_validator.rb b/lib/dragnet/validators/fields/sha1_validator.rb new file mode 100644 index 0000000..3883000 --- /dev/null +++ b/lib/dragnet/validators/fields/sha1_validator.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +require_relative 'field_validator' + +module Dragnet + module Validators + module Fields + # Validates the SHA1 field of a Manual Test Record + class SHA1Validator < Dragnet::Validators::Fields::FieldValidator + SHA1_MIN_LENGTH = 7 + SHA1_MAX_LENGTH = 40 + SHA1_REGEX = /\A[0-9a-f]+\Z/.freeze + + # Validates the SHA1 of the MTR + # @param [String] key The name of the key + # @param [Object] value The value of the key + # @raise [Dragnet::Errors::ValidationError] If the SHA1 is missing, is not + # and string, is too short or too long or is not a valid hexadecimal + # string. + def validate(key, value) + validate_presence(key, value) + validate_type(key, value, String) + + length = value.length + unless length >= SHA1_MIN_LENGTH && length <= SHA1_MAX_LENGTH + validation_error( + "Invalid value for key #{key}: '#{value}'. Expected a string between "\ + "#{SHA1_MIN_LENGTH} and #{SHA1_MAX_LENGTH} characters" + ) + end + + return if value.match(SHA1_REGEX) + + validation_error( + "Invalid value for key #{key}: '#{value}'. "\ + "Doesn't seem to be a valid hexadecimal string" + ) + end + end + end + end +end diff --git a/lib/dragnet/validators/files_validator.rb b/lib/dragnet/validators/files_validator.rb new file mode 100644 index 0000000..e5f8d96 --- /dev/null +++ b/lib/dragnet/validators/files_validator.rb @@ -0,0 +1,85 @@ +# frozen_string_literal: true + +require_relative '../errors/file_not_found_error' +require_relative 'validator' + +module Dragnet + module Validators + # Validates the +files+ key in the given Manual Test Record object. + # Validates: + # - That the listed file(s) glob pattern(s) match at least one file in the + # repository. + class FilesValidator < Dragnet::Validators::Validator + attr_reader :test_record, :path + + # Creates a new instance of the class. + # @param [Dragnet::TestRecord] test_record The +TestRecord+ object whose + # files should be validated. + # @param [Pathname] path The path to the repository where the files are + # supposed to be located. + def initialize(test_record, path) + @test_record = test_record + @files = test_record.files + @path = path + end + + # Validates the +files+ key in the given data. + # Updates the +file+ key in the given +data+ to the actual files found in + # the repository. + # @raise [Dragnet::Errors::FileNotFoundError] If any of the listed files + # cannot be found in the given repository path or if a glob pattern + # doesn't match any files there. + def validate + return unless files + + test_record.files = translate_paths && force_relative_paths && resolve_files + end + + private + + attr_reader :files + + # Forces all the file paths to be relative by removing the +/+ at the + # start (if they have one). This is done to ensure that files are always + # considered relative to the path being checked. + def force_relative_paths + @files = files.map do |file| + file.sub(%r{^/}, '') + end + end + + # Translate the file paths from windows style paths (with \ as path + # separator) to Unix style paths (with / as path separator). + # This is done so that the git commands work in all systems. + def translate_paths + @files = files.map do |file| + file.tr('\\', '/') + end + end + + # Resolve the given files by checking for matches in the given repository. + # Glob patterns are resolved an translated into individual files. + # @return [Array] The resolved file paths. + # @raise [Dragnet::Errors::FileNotFoundError] If any of the listed files + # cannot be found in the given repository path or if a glob pattern + # doesn't match any files there. + def resolve_files + resolved_files = [] + + files.each do |file| + # Files can be defined as glob patterns + matched_files = path.glob(file) + + if matched_files.empty? + raise Dragnet::Errors::FileNotFoundError, + "Could not find any files matching #{file} in #{path}" + end + + resolved_files += matched_files + end + + resolved_files + end + end + end +end diff --git a/lib/dragnet/validators/repos_validator.rb b/lib/dragnet/validators/repos_validator.rb new file mode 100644 index 0000000..a5dffdb --- /dev/null +++ b/lib/dragnet/validators/repos_validator.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: true + +require_relative '../errors/repo_path_not_found_error' +require_relative 'files_validator' + +module Dragnet + module Validators + # Validates the +Repo+ objects attached to the given +TestRecord+ + class ReposValidator < Dragnet::Validators::Validator + attr_reader :test_record, :repos, :path + + # @param [Dragnet::TestRecord] test_record The Test Record to validate. + # @param [Pathname] path The path where the repositories are supposed to + # be located. + def initialize(test_record, path) + @test_record = test_record + @path = path + @repos = test_record.repos + end + + # Validates the +Repo+ objects inside the given +TestCase+ + def validate + return unless repos + + validate_paths + end + + private + + # Validates the +paths+ of the +Repo+ objects (makes sure the paths + # exist). Knowing that these paths exist, the +files+ attribute of the + # +Repo+ object can be validated as well. + # @raise [Dragnet::Errors::RepoPathNotFoundError] If one or more of the + # paths cannot be found. + # @raise [Dragnet::Errors::FileNotFoundError] If any of the files listed + # in the +files+ attribute do not exist inside the given +path+. + def validate_paths + repos.each do |repo| + repo_path = repo.path = repo.path.gsub('\\', '/') + repo_path = Pathname.new(repo_path) + + complete_path = repo_path.absolute? ? repo_path : path / repo_path + + if complete_path.exist? + validate_files(repo, complete_path) + next + end + + repo_path_not_found(repo_path) + end + end + + # Validates the existence of the files listed in the +files+ attributes + # inside the +Repo+ object inside the +Repo+'s +path+. + # @param [Dragnet::Repo] repo The +Repo+ whose files should be validated. + # @param [Pathname] complete_path The path to the repository. + def validate_files(repo, complete_path) + return unless repo.files + + Dragnet::Validators::FilesValidator.new(repo, complete_path).validate + end + + # Raises a Dragnet::Errors::RepoPathNotFoundError with the appropriate + # message (which depends on whether the path is absolute or relative). + # @param [Pathname] repo_path The path that couldn't be found. + # @raise [Dragnet::Errors::RepoPathNotFoundError] is always raised. + def repo_path_not_found(repo_path) + message = "Cannot find the repository path #{repo_path}" + message += " inside #{path}" if repo_path.relative? + raise Dragnet::Errors::RepoPathNotFoundError, message + end + end + end +end diff --git a/lib/dragnet/validators/validator.rb b/lib/dragnet/validators/validator.rb new file mode 100644 index 0000000..14b15d3 --- /dev/null +++ b/lib/dragnet/validators/validator.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +require_relative '../errors/yaml_format_error' + +module Dragnet + module Validators + # Base class for all validators. + class Validator + private + + # Raises a +Dragnet::Errors::YAMLFormatError+ with the given message. + # @param [String] message The message for the exception. + # @raise [Dragnet::Errors::YAMLFormatError] Is always raised with the + # given message. + def yaml_format_error(message) + raise Dragnet::Errors::YAMLFormatError, message + end + end + end +end diff --git a/lib/dragnet/verification_result.rb b/lib/dragnet/verification_result.rb new file mode 100644 index 0000000..d5155a9 --- /dev/null +++ b/lib/dragnet/verification_result.rb @@ -0,0 +1,125 @@ +# frozen_string_literal: true + +require 'colorize' + +require_relative 'errors/missing_timestamp_attribute_error' + +module Dragnet + # Holds the verification result of a Manual Test Record + class VerificationResult + VALID_STATUSES = %i[passed skipped failed].freeze + + attr_reader :status, :reason, :started_at, :finished_at + + # Creates a new instance of the class. + # @param [Symbol] status The status + # @param [String] reason + def initialize(status:, reason: nil) + self.status = status + @reason = reason + end + + def passed? + status == :passed + end + + def skipped? + status == :skipped + end + + def failed? + status == :failed + end + + # Assigns the given status + # @param [Symbol] status The status + # @raise [ArgumentError] If the given status is not one of the accepted + # valid statuses. + def status=(status) + unless VALID_STATUSES.include?(status) + raise ArgumentError, "Invalid status #{status}."\ + " Valid statuses are: #{VALID_STATUSES.join(', ')}" + end + + @status = status + end + + # Sets the verification's start time. + # @param [Time] time The verification's start time. + # @raise [ArgumentError] If the given +time+ is not an instance of +Time+. + # @raise [ArgumentError] If +finished_at+ is set and the given +time+ is + # bigger than or equal to it. + def started_at=(time) + validate_time(time) + raise ArgumentError, 'started_at must be smaller than finished_at' if finished_at && time >= finished_at + + @runtime = nil + @started_at = time + end + + # Sets the verification's finish time + # @param [Time] time The verification's finish time. + # @raise [TypeError] Is an attempt is made to set +finished_at+ before + # setting +started_at+. + # @raise [ArgumentError] If the given +time+ is not an instance of +Time+. + # @raise [ArgumentError] If +started_at+ is set and the given +time+ is + # smaller than or equal to it. + def finished_at=(time) + validate_time(time) + raise ArgumentError, 'finished_at must be greater than started_at' if started_at && time <= started_at + + @runtime = nil + @finished_at = time + end + + # @return [Float, nil] The runtime calculated from the started_at and + # finished_at attributes, if any of them is missing +nil+ is returned + # instead. + def runtime + runtime! + rescue Dragnet::Errors::MissingTimestampAttributeError + nil + end + + # @return [Float] The runtime calculated from the started_at and finished_at + # timestamp attributes. + # @raise [TypeError] If either of these attributes is +nil+ + def runtime! + @runtime ||= calculate_runtime + end + + # @return [String] A string representation of the receiver that can be used + # to log the result of a verification. + def log_message + if passed? + '✔ PASSED '.colorize(:light_green) + elsif skipped? + "#{'⚠ SKIPPED'.colorize(:light_yellow)} #{reason}" + else + "#{'✘ FAILED '.colorize(:light_red)} #{reason || 'Unknown reason'}" + end + end + + private + + # Checks if the given object is a +Time+ and raises an +ArgumentError+ if it + # isn't. + # @param [Object] time The object to check. + # @raise [ArgumentError] If the given object is not a +Time+ object. + def validate_time(time) + raise ArgumentError, "Expected a Time object, got #{time.class}" unless time.is_a?(Time) + end + + # @return [Float] The runtime calculated from the started_at and finished_at + # timestamp attributes. + # @raise [TypeError] If either of these attributes is +nil+ + def calculate_runtime + if started_at.nil? || finished_at.nil? + raise Dragnet::Errors::MissingTimestampAttributeError, + 'Both started_at and finished_at must be set in order to calculate the runtime' + end + + finished_at - started_at + end + end +end diff --git a/lib/dragnet/verifier.rb b/lib/dragnet/verifier.rb new file mode 100644 index 0000000..60a3247 --- /dev/null +++ b/lib/dragnet/verifier.rb @@ -0,0 +1,64 @@ +# frozen_string_literal: true + +require 'git' + +require_relative 'verifiers/test_record_verifier' + +module Dragnet + # Executes the verification process on the given Test Records + class Verifier + attr_reader :test_records, :path, :logger + + # Creates a new instance of the class. + # @param [Array] test_records An array with the test records. + # @param [Dragnet::Repository] repository The repository where the MTR and + # the source files are stored. + # @param [#info] logger The logger object to use for output. + def initialize(test_records:, repository:, logger:) + @test_records = test_records + @repository = repository + @logger = logger + end + + # Runs the verify process + # After the execution of this method each Test Record will get a +:result+ + # key with the result of the verification process. This key contains a hash + # like the following: + # + # result: { + # status: :passed, # Either :passed, :failed or :skipped + # reason: 'String' # The reason for the failure (for :failed and :skipped) + # } + def verify + logger.info 'Verifying MTR files...' + test_records.each do |test_record| + logger.info "Verifying #{test_record.source_file}" + verify_mtr(test_record) + end + end + + private + + attr_reader :repository + + # Verifies the given Manual Test Record + # Runs the given test record through all the verifiers. If no verifier adds + # a +result+ key to the Test Record then the method adds one with passed + # status. + # @param [Dragnet::TestRecord] test_record The Test Record to verify. + def verify_mtr(test_record) + started_at = Time.now.utc + + verification_result = Dragnet::Verifiers::TestRecordVerifier.new( + test_record: test_record, repository: repository, test_records: test_records + ).verify + + finished_at = Time.now.utc + verification_result.started_at = started_at + verification_result.finished_at = finished_at + test_record.verification_result = verification_result + + logger.info(verification_result.log_message) + end + end +end diff --git a/lib/dragnet/verifiers.rb b/lib/dragnet/verifiers.rb new file mode 100644 index 0000000..2af53c7 --- /dev/null +++ b/lib/dragnet/verifiers.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +require_relative 'verifiers/repos_verifier' + +module Dragnet + # Namespace for the Verifier classes. + module Verifiers; end +end diff --git a/lib/dragnet/verifiers/changes_verifier.rb b/lib/dragnet/verifiers/changes_verifier.rb new file mode 100644 index 0000000..d9f3dc1 --- /dev/null +++ b/lib/dragnet/verifiers/changes_verifier.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +require_relative '../verification_result' +require_relative 'repository_verifier' + +module Dragnet + module Verifiers + # Checks for changes in the repository since the creation of the MTR Record + class ChangesVerifier < Dragnet::Verifiers::RepositoryVerifier + attr_reader :test_records + + # @param [Dragnet::TestRecord] test_record The +TestRecord+ object to + # verify. + # @param [Dragnet::Repository] repository A +Dragnet::Repository+ object + # linked to the repository where the verification should be executed. + # @param [Array] test_records The hash of all the test records. This + # is used to determine if the changes in the repository are only in the + # Test Record Files, in which case the Test Records will still be + # considered valid. + def initialize(test_record:, repository:, test_records:) + super(test_record: test_record, repository: repository) + @test_records = test_records + end + + # Runs the verification process. Checks the changes on the repository + # between the Commit with the SHA1 registered in the MTR and the current + # HEAD. + # @return [Dragnet::VerificationResult, nil] A +VerificationResult+ with + # the details of the changes found in the repository or +nil+ if no + # changes were found. + def verify + diff = repository.diff(sha1, 'HEAD') + return unless diff.size.positive? + + find_changes(diff) + end + + private + + # Scans the given diff for changes. If changes are detected then a + # +:result+ key will be added to the +test_record+. Changes to the MTR + # files themselves are ignored. + # @return [Dragnet::VerificationResult, nil] A +VerificationResult+ with + # the details of the changes found in the repository, or +nil+ if no + # changes were found. + def find_changes(diff) + diff.stats[:files].each do |file, _changes| + next if mtr_files.include?(file) # Changes to MTR files are ignored. + + return Dragnet::VerificationResult.new( + status: :skipped, + reason: "Changes detected in the repository: #{shorten_sha1(sha1)}..#{shorten_sha1(repository.head.sha)}"\ + " # -- #{file}" + ) + end + + nil + end + + # @return [Array] An array of strings with the paths to all the + # known MTR files. These will be excluded when checking from changes in + # the repository. + def mtr_files + @mtr_files ||= test_records.map do |test_record| + test_record.source_file.relative_path_from(path).to_s + end + end + end + end +end diff --git a/lib/dragnet/verifiers/files_verifier.rb b/lib/dragnet/verifiers/files_verifier.rb new file mode 100644 index 0000000..c02393f --- /dev/null +++ b/lib/dragnet/verifiers/files_verifier.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +require_relative '../verification_result' +require_relative 'repository_verifier' + +module Dragnet + module Verifiers + # Checks if any of the files listed in the MTR have changed since the MTR + # was created. + class FilesVerifier < Dragnet::Verifiers::RepositoryVerifier + # Executes the verification process. + # Checks the changes in the repository. If a change in one of the files + # is detected a +:result+ key is added to the MTR, including the detected + # change. + # @return [Dragnet::VerificationResult, nil] A +VerificationResult+ object + # with the detected changes to the listed files or +nil+ if no changes + # are found. + def verify + changes = [] + + files.each do |file| + diff = repository.diff(sha1, 'HEAD').path(file.to_s) + next unless diff.size.positive? + + changes << file + end + + result_from(changes) if changes.any? + end + + private + + # @return [Array] The paths to the files listed in the MTR file. + def files + @files ||= test_record.files.map do |file| + file.relative_path_from(path) + end + end + + # Stores the detected changes on the Test Record + # @param [Array] changes The array of changed files. + def result_from(changes) + Dragnet::VerificationResult.new( + status: :skipped, + reason: "Changes detected in listed file(s): #{shorten_sha1(sha1)}..#{shorten_sha1(repository.head.sha)}"\ + " -- #{changes.join(' ')}" + ) + end + end + end +end diff --git a/lib/dragnet/verifiers/repos_verifier.rb b/lib/dragnet/verifiers/repos_verifier.rb new file mode 100644 index 0000000..7dbafa6 --- /dev/null +++ b/lib/dragnet/verifiers/repos_verifier.rb @@ -0,0 +1,92 @@ +# frozen_string_literal: true + +require_relative '../errors/not_a_repository_error' +require_relative '../test_record' +require_relative 'changes_verifier' +require_relative 'files_verifier' +require_relative 'verifier' + +module Dragnet + module Verifiers + # Verifies the +Repo+ objects attached to a +TestRecord+ + class ReposVerifier < Dragnet::Verifiers::Verifier + attr_reader :multi_repository + + # @param [Dragnet::TestRecord] test_record The +TestRecord+ object to + # verify. + # @param [Dragnet::MultiRepository] multi_repository The +MultiRepository+ + # object that is supposed to contain the actual repositories inside. + def initialize(test_record:, multi_repository:) + super(test_record: test_record) + @multi_repository = multi_repository + end + + # Carries out the verification of the +Repo+ objects. + # @return [Dragnet::VerificationResult, nil] A +VerificationResult+ object + # when the verification of any of the listed repositories fails and + # +nil+ when all of them pass the verification. + def verify + return unless test_record.repos&.any? + + test_record.repos.each do |repo| + repository = fetch_repository(repo.path, multi_repository) + verification_result = verify_repo(repo, repository) + + return verification_result if verification_result + end + rescue Dragnet::Errors::NotARepositoryError => e + Dragnet::VerificationResult.new(status: :failed, reason: e.message) + end + + private + + # Verifies the given +Repo+ object using the given +Dragnet::Repository+ + # object and a Proxy TestRecord object. + # @param [Dragnet::Repo] repo +Repo+ the +Repo+ object to verify. + # @param [Dragnet::Repository] repository The +Repository+ object that + # actually contains the source the +Repo+ object is referring to. + # @return [Dragnet::VerificationResult, nil] A +VerificationResult+ object + # when the verification fails or +nil+ when the verification passes. + def verify_repo(repo, repository) + # The Proxy TestRecord object allows the use of the +FilesVerifier+ and + # the +ChangesVerifier+ since they expect a +TestRecord+ and not a + # +Repo+ object. + proxy_test_record = Dragnet::TestRecord.new(files: repo.files, sha1: repo.sha1) + + if repo.files + Dragnet::Verifiers::FilesVerifier + .new(test_record: proxy_test_record, repository: repository).verify + else + Dragnet::Verifiers::ChangesVerifier + .new(test_record: proxy_test_record, repository: repository, test_records: []).verify + end + end + + # Fetches the +Repository+ object associated with the given path from the + # given +MultiRepository+ object. + # @param [Pathname] path The path of the repository. + # @param [Dragnet::MultiRepository] multi_repository The +MultiRepository+ + # object that contains the repository to be fetched. + # @return [Dragnet::Repository] The +Repository+ object associated with + # the given path. + def fetch_repository(path, multi_repository) + multi_repository.repositories[path] ||= create_repository(multi_repository, path) + end + + # Creates a new repository with the given path. + # @param [Dragnet::MultiRepository] multi_repository The +MultiRepository+ + # object in which the individual repository should be created. + # @param [Pathname] path The path for the +Repository+ object. + # @return [Dragnet::Repository] The resulting +Repository+ object. + # @raise [Dragnet::Errors::NotARepositoryError] If the given path doesn't + # lead to a valid git repository or the repository cannot be opened. + def create_repository(multi_repository, path) + repository_path = multi_repository.path / path + Dragnet::Repository.new(path: repository_path) + rescue ArgumentError + raise Dragnet::Errors::NotARepositoryError, + "The path '#{path}' does not contain a valid git repository." + end + end + end +end diff --git a/lib/dragnet/verifiers/repository_verifier.rb b/lib/dragnet/verifiers/repository_verifier.rb new file mode 100644 index 0000000..fd82170 --- /dev/null +++ b/lib/dragnet/verifiers/repository_verifier.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +require_relative 'verifier' + +module Dragnet + module Verifiers + # Base class for the Verifiers that need access to the repository to perform + # the validation. + class RepositoryVerifier < Dragnet::Verifiers::Verifier + attr_reader :repository + + # @param [Dragnet::Repository] repository A +Dragnet::Repository+ object + # linked to the repository where the sources and MTR files are located + def initialize(test_record:, repository:) + super(test_record: test_record) + @repository = repository + end + + private + + # @return [String] The path to the repository. + def path + @path ||= repository.path + end + end + end +end diff --git a/lib/dragnet/verifiers/result_verifier.rb b/lib/dragnet/verifiers/result_verifier.rb new file mode 100644 index 0000000..27e8327 --- /dev/null +++ b/lib/dragnet/verifiers/result_verifier.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +require_relative 'verifier' +require_relative '../verification_result' + +module Dragnet + module Verifiers + # Verifies the +result+ field on the given MTR record. + class ResultVerifier < Dragnet::Verifiers::Verifier + # Performs the verification. If the +result+ field contains the "failed" + # text then a +result+ key will be added to the Test Record explaining + # the reason for the failure. + # @return [Dragnet::VerificationResult, nil] A +VerificationResult+ object + # when the verification fails and +nil+ when the verification passes. + def verify + return if test_record.passed? + + Dragnet::VerificationResult.new( + status: :failed, + reason: "'result' field has the status '#{result}'" + ) + end + + private + + # @return [String] The value for the +result+ key on the MTR file. + def result + @result ||= test_record.result + end + end + end +end diff --git a/lib/dragnet/verifiers/test_record_verifier.rb b/lib/dragnet/verifiers/test_record_verifier.rb new file mode 100644 index 0000000..3712a29 --- /dev/null +++ b/lib/dragnet/verifiers/test_record_verifier.rb @@ -0,0 +1,85 @@ +# frozen_string_literal: true + +require_relative 'changes_verifier' +require_relative 'files_verifier' +require_relative 'repos_verifier' +require_relative 'result_verifier' +require_relative 'verifier' + +module Dragnet + module Verifiers + # Performs the verification process over a single TestRecord object. + class TestRecordVerifier < Dragnet::Verifiers::Verifier + attr_reader :repository, :test_records + + # @param [Dragnet::TestRecord] test_record The +TestRecord+ object to + # verify. + # @param [Dragnet::BaseRepository] repository An object representing the + # repository the test record is referring to. + # @param [Array] test_records An array with all the + # +TestRecord+ objects found in the +Repository+. These are needed when + # changes to the repository are being verified. Changes targeting the + # MTRs only are ignored by the verifiers. + def initialize(test_record:, repository:, test_records:) + super(test_record: test_record) + @repository = repository + @test_records = test_records + end + + # Performs the verification and attaches the corresponding + # +VerificationResult+ object to the +TestRecord+ object. + # @return [Dragnet::VerificationResult] The result of the verification + # process executed over the given +test_record+. + def verify + verification_result = verify_result + + verification_result ||= if test_record.files + verify_files + elsif test_record.repos + verify_repos + else + verify_changes + end + + verification_result || Dragnet::VerificationResult.new(status: :passed) + end + + private + + # Verifies the MTR's +result+ attribute. + # @return [Dragnet::VerificationResult, nil] A +VerificationResult+ object + # when the verification fails and +nil+ when the verification passes. + def verify_result + Dragnet::Verifiers::ResultVerifier.new(test_record: test_record).verify + end + + # Verifies the files listed in the MTR, if any. + # @return [Dragnet::VerificationResult, nil] A +VerificationResult+ object + # with the detected changes to the listed files or +nil+ if no changes + # are found. + def verify_files + Dragnet::Verifiers::FilesVerifier + .new(test_record: test_record, repository: repository).verify + end + + # Verifies the repositories listed in the MTR, only applies when working + # with a {Dragnet::MultiRepository} repository. + # @return [Dragnet::VerificationResult, nil] A +VerificationResult+ object + # when the verification of any of the listed repositories fails and + # +nil+ when all of them pass the verification. + def verify_repos + Dragnet::Verifiers::ReposVerifier.new(test_record: test_record, multi_repository: repository).verify + end + + # Verifies the changes in the repository between the revision referenced + # in the MTR and the tip of the current branch. + # @return [Dragnet::VerificationResult, nil] A +VerificationResult+ with + # the details of the changes found in the repository or +nil+ if no + # changes were found. + def verify_changes + Dragnet::Verifiers::ChangesVerifier + .new(test_record: test_record, repository: repository, test_records: test_records).verify + end + end + end +end diff --git a/lib/dragnet/verifiers/verifier.rb b/lib/dragnet/verifiers/verifier.rb new file mode 100644 index 0000000..e5ba050 --- /dev/null +++ b/lib/dragnet/verifiers/verifier.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +require_relative '../helpers/repository_helper' + +module Dragnet + module Verifiers + # Base class for all validators. + class Verifier + include Dragnet::Helpers::RepositoryHelper + + attr_reader :test_record + + # Creates a new instance of the class. + # @param [Dragnet::TestRecord] test_record The +TestRecord+ object to + # verify. + def initialize(test_record:) + @test_record = test_record + end + + # Needs to be implemented by the child classes. This method is called to + # perform the verification on the given +test_record+. + # @return [Dragnet::VerificationResult, nil] The method should return a + # +VerificationResult+ object if the verification fails or +nil+ if it + # passes. + def verify + raise NotImplementedError, "Please implement #{__method__} in #{self.class}" + end + + private + + # @return [String] The SHA1 stored in the MTR File. + def sha1 + @sha1 ||= test_record.sha1 + end + end + end +end diff --git a/lib/dragnet/version.rb b/lib/dragnet/version.rb new file mode 100644 index 0000000..a7693d8 --- /dev/null +++ b/lib/dragnet/version.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +module Dragnet + VERSION = '5.2.0' +end diff --git a/req/cli.dim b/req/cli.dim new file mode 100644 index 0000000..8b5a9b5 --- /dev/null +++ b/req/cli.dim @@ -0,0 +1,94 @@ +module: CLI + +DRAGNET_0017: + text: | + Dragnet shall provide a CLI to use the tool. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0018: + text: | + The CLI shall provide a command to run the verification + process. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0019: + text: | + Configuration shall be loaded by default from the + .dragnet.yaml file (in the current working directory) if no + configuration file is given via command line switch. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0020: + text: | + It shall be possible to provide a configuration file via a + command line switch. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0021: + text: | + The CLI shall provide a switch that allows the verification + process's results to be exported to an HTML file. + tags: covered, tested + refs: DRAGNET_0022, DRAGNET_0023, DRAGNET_0024, DRAGNET_0025 + test_setups: none + status: valid + +DRAGNET_0026: + text: | + It shall be possible to configure the CLI to either produce + output or stay silent during the Verification Process (via + command line switch or configuration file). + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0032: + text: | + When the CLI produces output it shall list at the top all + the MTR files it found. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0027: + text: | + When the CLI produces output it shall list the MTRs as it + checks them. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0028: + text: | + When the CLI produces output it shall display the result of + the verification for each MTR, "PASSED", "FAILED" or + "SKIPPED", preferably with a color to allow the user to + quickly see the results. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0029: + text: | + When the CLI produces output it shall print the reason for + a failure or a skipped test, for example "changed detected on + the repository since revision 1a22c051e". + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0034: + text: | + Configuration errors shall be reported immediately and the + verification process shall be aborted right away. + tags: covered, tested + test_setups: off_target + status: valid diff --git a/req/config.yml b/req/config.yml new file mode 100644 index 0000000..0be3bee --- /dev/null +++ b/req/config.yml @@ -0,0 +1,5 @@ +Config: + - originator: ESR Labs + files: + - "*.dim" + category: software diff --git a/req/explorer.dim b/req/explorer.dim new file mode 100644 index 0000000..1b02f29 --- /dev/null +++ b/req/explorer.dim @@ -0,0 +1,26 @@ +module: Explorer + +DRAGNET_0001: + text: | + The path where the MTR files are stored shall be + configurable. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0002: + text: | + It shall be possible to define a glob pattern to search for + MTR files inside the defined path. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0033: + text: | + The Explorer shall notify the user and fail the build when it + cannot find any MTR files in the specified path using the + given glob patterns. + test_setups: off_target + tags: covered, tested + status: valid diff --git a/req/exporter.dim b/req/exporter.dim new file mode 100644 index 0000000..0ce71d8 --- /dev/null +++ b/req/exporter.dim @@ -0,0 +1,146 @@ +module: Exporter + +DRAGNET_0022: + text: | + The exporter shall be capable of exporting the results of + the verification process to an HTML file. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0023: + text: | + The HTML report shall list all files from which MTR were + loaded. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0024: + text: | + In the HTML report it shall be easy to see the result of the + test at a glance (by using colors). + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0025: + text: | + In the HTML report it shall be possible to see the reason + for tests failing or being skipped, for example "changes + detected in file xyz.cpp". + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0060: + text: | + The exporter shall be capable of exporting the results of the + verification to a JSON file. + test_setups: off_target + tags: covered, tested + status: valid + refs: DRAGNET_0061, DRAGNET_0062, DRAGNET_0063, DRAGNET_0064, DRAGNET_0065 + +DRAGNET_0061: + text: | + The JSON export shall contain an array of objects. An object + for each Manual Test Record. + test_setups: off_target + tags: covered, tested + status: valid + +DRAGNET_0062: + text: | + The JSON export shall contain the MTRs and the result of + their verification. + tags: covered, tested + test_setups: off_target + status: valid + refs: DRAGNET_0078 + +DRAGNET_0063: + text: | + The JSON export shall not contain the validation errors + encountered during the MTR load process. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0064: + text: | + The JSON exporter shall export the Test Records' ``id`` + attribute as ``refs``. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0069: + text: | + The JSON exporter shall export all the meta-data fields + to the generated JSON file. + refs: DRAGNET_0065, DRAGNET_0070 + tags: covered, tested + test_setups: none + status: valid + +DRAGNET_0070: + text: | + The fields ``test_method`` and ``tc_derivation_method`` shall + be exported as arrays of strings (possibly with a single + element) when thy have a value and omitted when they have + none. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0065: + text: | + The JSON exporter shall export the Test Records' ``name`` + attribute as ``owner``. + refs: DRAGNET_0071 + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0071: + text: | + The ``owner`` field shall always be exported as a String + when the field has a value (arrays shall be "joined") and + omitted when there is no value. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0066: + text: | + Since none of the properties of an MTR are guaranteed to be + unique among them, the exporters shall generate a unique ID + for each MTR to allow them to be uniquely identified outside + of Dragnet. + tags: covered, tested + test_setups: off_target + status: valid + refs: DRAGNET_0067 + +DRAGNET_0078: + text: | + The JSON exporter shall include the timestamp attributes of + the verification result. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0067: + text: | + The unique ID shall be generated by SHA1-hashing a string + with the concatenation of: + + * The name of the file that contains the MTR + * The content of the 'id' field (converted to string) + + Only the first 16 characters of the resulting SHA1 shall be + used. + tags: covered, tested + test_setups: off_target + status: valid diff --git a/req/validator.dim b/req/validator.dim new file mode 100644 index 0000000..22a9383 --- /dev/null +++ b/req/validator.dim @@ -0,0 +1,254 @@ +module: Validator + +DRAGNET_0003: + text: | + The Validator shall verify that the loaded MTR files are valid + YAML files. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0004: + text: | + The MTR files can contain a list of tested files. + tags: covered, tested + refs: DRAGNET_0055, DRAGNET_0013, DRAGNET_0005, DRAGNET_0072 + test_setups: off_target + status: valid + +DRAGNET_0055: + text: | + The list of files shall not be mandatory. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0013: + text: | + The "files" field can contain glob patterns as well as + individual files from a single repository. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0005: + text: | + If the MTR file contains a set of tested files The Validator + shall verify that the files exist in the repository. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0072: + text: | + The listed files or glob patterns shall be considered + relative to the path being checked by Dragnet, even if they + start with ``/``. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0035: + text: | + The MTR files may contain a list of repositories. + tags: covered, tested + status: valid + test_setups: off_target + refs: DRAGNET_0056, DRAGNET_0036, DRAGNET_0037 + +DRAGNET_0056: + text: | + The list of repositories shall not be mandatory. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0036: + text: | + If the MTR file contains a list of files it cannot contain a + list of repositories as well. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0037: + text: | + The "repos" field shall contain an array of Objects. + tags: covered, tested + status: valid + test_setups: off_target + refs: DRAGNET_0038 + +DRAGNET_0038: + text: | + The objects in the "repos" field shall contain the following + attributes: "path", "sha1" and optionally "files". + tags: covered, tested + status: valid + test_setups: none + refs: DRAGNET_0039, DRAGNET_0040, DRAGNET_0041, DRAGNET_0049 + +DRAGNET_0039: + text: | + The "path" attribute defines the path where the repository + can be found. It can be either a relative path to the current + working directory or an absolute path. + status: valid + tags: covered, tested + test_setups: off_target + refs: DRAGNET_0042 + +DRAGNET_0042: + text: | + Dragnet shall verify that the "path" attribute contains a + valid path. + status: valid + tags: covered, tested + test_setups: off_target + refs: DRAGNET_0058 + +DRAGNET_0058: + text: | + If the "path" attribute doesn't point to an existing path + the MTR shall be considered invalid. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0040: + text: | + The "sha1" attribute shall contain the SHA1 the repository had + when the manual test was performed. This will be used to + validate the MTR. + status: valid + tags: covered, tested + test_setups: none + refs: DRAGNET_0043 + +DRAGNET_0043: + text: | + Dragnet shall verify that the given SHA1 is a valid SHA1 + status: valid + tags: covered, tested + test_setups: off_target + refs: DRAGNET_0046 + +DRAGNET_0046: + text: | + If the "sha1" attribute doesn't contain a valid SHA1 the MTR + shall be considered invalid. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0041: + text: | + The "files" attribute shall contain a list of individual files + or glob patterns, these refer to files inside the repository + located at the path defined by the "path" attribute. + tags: covered, tested + test_setups: off_target + status: valid + refs: DRAGNET_0044, DRAGNET_0073 + +DRAGNET_0049: + text: | + The "files" attribute shall not be mandatory. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0044: + text: | + Dragnet shall verify that all the listed files (or the files + the glob patterns resolve to) exist in the repository. + status: valid + tags: covered, tested + test_setups: off_target + refs: DRAGNET_0047, DRAGNET_0048 + +DRAGNET_0073: + text: | + The listed files or glob patterns shall be considered + relative to the repository root, even if they start with + ``/``. + tags: covered, tested + status: valid + test_setups: off_target + +DRAGNET_0047: + text: | + If one or more of the files listed in the "files" attribute + doesn't exist the MTR shall be considered invalid. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0048: + text: | + If the "files" attribute contains only glob patterns they + should resolve to at least one file. If no files are matched + the MTR shall be considered invalid. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0006: + text: | + The MTR file shall contain the SHA1 on which the tests were + carried out. The Validator shall verify that the SHA1 is + valid. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0057: + text: | + The MTR may contain a SHA1 attribute or a list of + repositories but NOT both. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0007: + text: | + MTR files shall contain an "id" field, this must contain the + ID of the requirement being tested or an array of IDs being + tested. (In case of an array it shall follow YAML's syntax) + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0008: + text: | + MTR files shall contain a "result" field. The field can + either be "passed" or "failed". + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0009: + text: | + FuSa related tests shall have the "reviewstatus", + "reviewcomments" and "findings" fields. + test_setups: off_target + status: draft + +DRAGNET_0010: + text: | + The Validator shall be able to check if a test is related to + Functional Safety (FuSa). + test_setups: off_target + status: draft + +DRAGNET_0068: + text: | + MTR Files may contain the following additional meta-data + attributes, none of which shall be mandatory: + + * ``name``: Single String or Array of Strings + * ``test_method``: Single String or Array of Strings + * ``tc_derivation_method`` Single String or Array of Strings + tags: covered, tested + test_setups: off_target + status: valid diff --git a/req/verifier.dim b/req/verifier.dim new file mode 100644 index 0000000..d6972d2 --- /dev/null +++ b/req/verifier.dim @@ -0,0 +1,166 @@ +module: Verifier + +DRAGNET_0011: + text: | + If the "result" field has the value "failed", the Manual + Tests shall be marked as failed. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0012: + text: | + If a MTR lists files and there has been any change to the + listed files after the revision specified in the "sha1" + field, the Manual Test shall be marked as skipped. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0014: + text: | + If a MTR lists glob patterns and any file matched by the glob + pattern has changed since the revision specified in the + "sha1" field then, the Manual Tests shall be marked as + skipped. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0050: + text: | + If the MTR lists repositories, each individual repository + shall be checked. + tags: covered, tested + status: valid + test_setups: off_target + refs: DRAGNET_0051, DRAGNET_0053, DRAGNET_0059, DRAGNET_0045 + +DRAGNET_0045: + text: | + If the "path" attribute doesn't point to a valid git + repository the MTR shall be considered invalid. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0059: + text: | + If the verification of any the listed repositories fails the + MTR shall be considered invalid. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0051: + text: | + If the repository lists files, Dragnet shall verify that none + of those files have changed between the revision specified by + the "sha1" attribute and the current revision. + tags: covered, tested + status: valid + test_setups: off_target + refs: DRAGNET_0052 + +DRAGNET_0052: + text: | + If changes are detected between the two revisions, the MTR + shall be marked as Skipped. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0053: + text: | + If no "files" attribute is given, then Dragnet shall verify + that no changes have been done to the repository between the + revision specified by the "sha1" attribute and the current + revision. + tags: covered, tested + test_setups: off_target + status: valid + refs: DRAGNET_0054 + +DRAGNET_0054: + text: | + If changes are detected between the two revisions, the MTR + shall be marked as Skipped. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0015: + text: | + If the MTR doesn't list any files and there are any changes + to the repository since the revision specified in the "sha1" + field. (Except for the commit that introduced the Manual Test + itself), then the Manual Test shall be marked as skipped. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0016: + text: | + The Manual Test is marked as passed if: + - The "result" field's value is "passed". + - There hasn't been any changes to the files it lists (if + any) since the revision specified in the "sha1" field. + - There hasn't been any changes on the repository since the + Manual Test Record was added (if it doesn't list any + files) + - The validation of the listed repositories (if any) pass. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0030: + text: | + The Verifier shall run through the whole set of MTR without + stopping because of failures, format errors or invalid files. + The results of the verification process shall be provided at + the end of the run. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0031: + text: | + The verifier shall not print anything to the console, it + shall be left to the exporter and or the CLI to take care of + the output. + tags: covered, tested + test_setups: off_target + status: valid + +DRAGNET_0074: + text: | + The result of the verification shall include information on + when the verification was executed and how much time it took. + test_setups: none + status: valid + refs: DRAGNET_0075, DRAGNET_0076, DRAGNET_0077 + +DRAGNET_0075: + text: | + The result of the verification shall include a timestamp to + mark the start of the verification. + test_setups: off_target + status: valid + tags: covered, tested + +DRAGNET_0076: + text: | + The result of the verification shall include a timestamp to + mark the completion of the verification. + test_setups: off_target + status: valid + tags: covered, tested + +DRAGNET_0077: + text: | + The result of the verification shall include its runtime, + this is, the number of seconds elapsed between the start and + the completion of the verification. + test_setups: off_target + status: valid + tags: covered, tested diff --git a/spec/.rubocop.yml b/spec/.rubocop.yml new file mode 100644 index 0000000..e34401d --- /dev/null +++ b/spec/.rubocop.yml @@ -0,0 +1,13 @@ +inherit_from: ../.rubocop.yml + +require: + - rubocop-rspec + +RSpec/MessageSpies: + EnforcedStyle: receive +RSpec/MultipleExpectations: + Max: 2 +RSpec/MultipleMemoizedHelpers: + Enabled: false +RSpec/NestedGroups: + Max: 5 diff --git a/spec/dragnet/cli/logger_spec.rb b/spec/dragnet/cli/logger_spec.rb new file mode 100644 index 0000000..f0e6445 --- /dev/null +++ b/spec/dragnet/cli/logger_spec.rb @@ -0,0 +1,131 @@ +# frozen_string_literal: true + +require 'dragnet/cli/logger' + +RSpec.describe Dragnet::CLI::Logger do + subject(:logger) { described_class.new(shell, log_level) } + + let(:shell) do + instance_double( + Thor::Shell::Basic + ) + end + + let(:default_log_level) { described_class::LEVELS[described_class::DEFAULT_LOG_LEVEL] } + let(:message) { 'hello world!' } + + describe '#initialize' do + context 'when no log level is given' do + subject(:logger) { described_class.new(shell) } + + it 'sets the log level to the default' do + expect(logger.log_level).to eq(default_log_level) + end + end + + context 'when the log level is not valid' do + let(:log_level) { :happy } + + it 'raises an ArgumentError' do + expect { logger }.to raise_error(ArgumentError, 'Unknown logger level: happy') + end + end + end + + describe '#debug' do + subject(:method_call) { logger.debug(message) } + + context 'when the log level is debug' do + let(:log_level) { :debug } + + it 'outputs the message' do + expect(shell).to receive(:say).with(/#{message}/) + method_call + end + + it 'colors the level with the expected color' do + expect(shell).to receive(:say).with(/\e\[0;32;49mDebug: \e\[0m/) + method_call + end + end + + context 'when the log level is greater than debug' do + let(:log_level) { %i[info warn error].sample } + + it "doesn't output the message" do + expect(shell).not_to receive(:say) + method_call + end + end + end + + describe '#info' do + subject(:method_call) { logger.info(message) } + + context 'when the log level is info or lower' do + let(:log_level) { %i[debug info].sample } + + it 'outputs the message' do + expect(shell).to receive(:say).with(/#{message}/) + method_call + end + + it 'colors the level with the expected color' do + expect(shell).to receive(:say).with(/\e\[0;34;49mInfo: \e\[0m/) + method_call + end + end + + context 'when the log level is greater than info' do + let(:log_level) { %i[warn error].sample } + + it "doesn't output the message" do + expect(shell).not_to receive(:say) + method_call + end + end + end + + describe '#warn' do + subject(:method_call) { logger.warn(message) } + + context 'when the log level is warn or lower' do + let(:log_level) { %i[debug info warn].sample } + + it 'outputs the message' do + expect(shell).to receive(:say).with(/#{message}/) + method_call + end + + it 'colors the level with the expected color' do + expect(shell).to receive(:say).with(/\e\[0;33;49mWarn: \e\[0m/) + method_call + end + end + + context 'when the log level is greater than warn' do + let(:log_level) { %i[error].sample } + + it "doesn't output the message" do + expect(shell).not_to receive(:say) + method_call + end + end + end + + describe '#error' do + subject(:method_call) { logger.error(message) } + + let(:log_level) { %i[debug info warn error].sample } + + it 'always outputs the message' do + expect(shell).to receive(:say).with(/Error: .*#{message}/) + method_call + end + + it 'colors the level with the expected color' do + expect(shell).to receive(:say).with(/\e\[0;31;49mError: \e\[0m/) + method_call + end + end +end diff --git a/spec/dragnet/cli/master_spec.rb b/spec/dragnet/cli/master_spec.rb new file mode 100644 index 0000000..fdf370f --- /dev/null +++ b/spec/dragnet/cli/master_spec.rb @@ -0,0 +1,642 @@ +# frozen_string_literal: true + +require 'dragnet/cli/master' +require 'shared/cli_master' + +RSpec.shared_context 'when Dragnet::Validator detects error in the MTR files' do + let(:errors) do + [ + { + file: 'test/manual/ESR_REQ_1030.yaml', + message: "Missing required key 'sha1'" + } + ] + end +end + +RSpec.shared_context 'when Dragnet::Verifier finds a failed MTR' do + let(:test_records) do + [ + instance_double( + Dragnet::TestRecord, + source_file: 'test/manual/ESR_REQ_5138.yaml', + result: 'passed', + verification_result: instance_double( + Dragnet::VerificationResult, + status: :passed, + passed?: true + ) + ), + instance_double( + Dragnet::TestRecord, + source_file: 'test/manual/ESR_REQ_4570.yaml', + result: 'passed', + verification_result: instance_double( + Dragnet::VerificationResult, + status: :skipped, + reason: 'Changes detected in the repository', + passed?: false + ) + ) + ] + end +end + +RSpec.shared_examples 'a fatal error is raised inside Dragnet::CLI::Master#check' do + it 'prints the expected error to the console' do + message = Regexp.escape("#{expected_message_header}\n #{expected_message}") + expect { method_call }.to raise_error(SystemExit) + .and output(Regexp.new(message)).to_stdout + end + + it 'exists with the expected error code' do + expect { method_call }.to output.to_stdout.and( + raise_error { |error| expect(error.status).to eq(expected_exit_code) } + ) + end +end + +RSpec.describe Dragnet::CLI::Master do + subject(:master) { described_class.new } + + describe '#version', requirements: %w[DRAGNET_0017 DRAGNET_0026] do + subject(:method_call) { master.version } + + include_context "with the default CLI's --version output" + + it 'prints the current version of the Gem' do + expect { method_call }.to output(expected_output).to_stdout + end + + context 'when the quit options is given' do + before do + master.options = { quiet: true } + end + + it "doesn't print anything to the output" do + expect { method_call }.not_to output.to_stdout + end + end + end + + describe '#check', requirements: ['DRAGNET_0018'] do + subject(:method_call) { master.check(path) } + + let(:path) { nil } + + let(:files) do + %w[ + test/manual/ESR_REQ_5138.yaml + test/manual/ESR_REQ_1030.yaml + test/manual/ESR_REQ_4570.yaml + ] + end + + let(:explorer) do + instance_double( + Dragnet::Explorer, + files: files + ) + end + + let(:test_records) { [] } + let(:errors) { [] } + + let(:repository) do + instance_double( + Dragnet::Repository + ) + end + + let(:multi_repository) do + instance_double( + Dragnet::MultiRepository + ) + end + + let(:validator) do + instance_double( + Dragnet::Validator, + validate: test_records, + errors: errors + ) + end + + let(:verifier) do + instance_double( + Dragnet::Verifier, + verify: true + ) + end + + let(:config_yaml) do + <<~YAML + glob_patterns: + - tests/manual/*.yaml + YAML + end + + let(:logger) do + instance_double( + Dragnet::CLI::Logger, + info: true + ) + end + + before do + allow(File).to receive(:read).with('.dragnet.yaml').and_return(config_yaml) + allow(Dragnet::CLI::Logger).to receive(:new).and_return(logger) + allow(Dragnet::Explorer).to receive(:new).and_return(explorer) + allow(Dragnet::Validator).to receive(:new).and_return(validator) + allow(Dragnet::Verifier).to receive(:new).and_return(verifier) + allow(Dragnet::Repository).to receive(:new).and_return(repository) + allow(Dragnet::MultiRepository).to receive(:new).and_return(multi_repository) + end + + context 'when no configuration file is specified' do + it 'loads the default configuration file', requirements: ['DRAGNET_0019'] do + expect(File).to receive(:read).with('.dragnet.yaml') + method_call + end + end + + context 'when a configuration file is specified', requirements: ['DRAGNET_0020'] do + before do + master.options = { configuration: 'my_config.yaml' } + allow(File).to receive(:read).with('my_config.yaml').and_return(config_yaml) + end + + it 'loads the specified configuration file' do + expect(File).to receive(:read).with('my_config.yaml') + method_call + end + end + + context 'when the specified configuration file cannot be loaded', requirements: ['DRAGNET_0034'] do + before do + allow(File).to receive(:read).with('.dragnet.yaml').and_raise( + Errno::ENOENT, 'File not found .dragnet.yaml' + ) + end + + it 'prints the expected error to the console' do + expect { method_call }.to raise_error(SystemExit).and output( + /Error: .*Unable to load the given configuration file: '\.dragnet\.yaml'/ + ).to_stdout + end + + it 'prints the exception message to the console' do + expect { method_call }.to raise_error(SystemExit).and output( + /File not found \.dragnet\.yaml/ + ).to_stdout + end + + it 'exists with the expected error code' do + expect { method_call }.to output.to_stdout.and( + raise_error { |error| expect(error.status).to eq(described_class::E_CONFIG_LOAD_ERROR) } + ) + end + end + + context 'when no path is specified', requirements: %w[DRAGNET_0001 DRAGNET_0002] do + context 'when none is configured in the configuration file' do + let(:pwd) { Pathname.pwd } + + it 'uses the current working directory as path for the Explorer' do + expect(Dragnet::Explorer).to receive(:new) + .with(path: pwd, glob_patterns: ['tests/manual/*.yaml'], logger: logger) + + method_call + end + + it 'uses the current working directory as path for the Validator' do + expect(Dragnet::Validator).to receive(:new) + .with(files: files, path: pwd, logger: logger) + + method_call + end + + shared_examples 'creates a repository and a verifier' do + it 'creates a repository pointing to the current working directory' do + expect(repository_class).to receive(:new).with(path: pwd) + method_call + end + + it 'passes down the created repository object to the Verifier' do + expect(Dragnet::Verifier).to receive(:new) + .with(test_records: test_records, repository: repository_instance, logger: logger) + + method_call + end + end + + context 'when multi-repo compatibility is disabled' do + let(:repository_class) { Dragnet::Repository } + let(:repository_instance) { repository } + + include_examples 'creates a repository and a verifier' + end + + context 'when multi-repo compatibility is enabled' do + let(:repository_class) { Dragnet::MultiRepository } + let(:repository_instance) { multi_repository } + + before { master.options = master.options.merge('multi-repo': true) } + + include_examples 'creates a repository and a verifier' + end + end + + context 'when the configuration file contains a path' do + let(:config_yaml) do + <<~YAML + path: /Workspace/source + glob_patterns: + - tests/manual/*.yaml + YAML + end + + let(:expected_path) { Pathname.new('/Workspace/source') } + + it 'uses the path from the configuration file for the Explorer' do + expect(Dragnet::Explorer).to receive(:new) + .with(path: expected_path, glob_patterns: ['tests/manual/*.yaml'], logger: logger) + + method_call + end + + it 'uses the path from the configuration file for the Validator' do + expect(Dragnet::Validator).to receive(:new) + .with(files: files, path: expected_path, logger: logger) + + method_call + end + + shared_examples 'creates a repository and a verifier' do + it 'creates a repository using the path from the configuration file' do + expect(repository_class).to receive(:new).with(path: expected_path) + method_call + end + + it 'passes down the created repository to the Verifier' do + expect(Dragnet::Verifier).to receive(:new) + .with(test_records: test_records, repository: repository_instance, logger: logger) + + method_call + end + end + + context 'when multi-repo compatibility is disabled' do + let(:repository_class) { Dragnet::Repository } + let(:repository_instance) { repository } + + include_examples 'creates a repository and a verifier' + end + + context 'when multi-repo compatibility is enabled' do + let(:repository_class) { Dragnet::MultiRepository } + let(:repository_instance) { multi_repository } + + before { master.options = master.options.merge('multi-repo': true) } + + include_examples 'creates a repository and a verifier' + end + end + end + + context 'when a path is specified', requirements: %w[DRAGNET_0001 DRAGNET_0002] do + let(:path) { '/tmp/repository' } + let(:pathname) { Pathname.new('/tmp/repository') } + + it 'uses a Pathname created from the specified path for the Explorer' do + expect(Dragnet::Explorer).to receive(:new) + .with(path: pathname, glob_patterns: ['tests/manual/*.yaml'], logger: logger) + + method_call + end + + it 'uses a Pathname created from the specified path for the Validator' do + expect(Dragnet::Validator).to receive(:new) + .with(files: files, path: pathname, logger: logger) + + method_call + end + + shared_examples 'creates a Repository and a Verifier' do + it 'creates a Repository object using a Pathname created with the given path' do + expect(repository_class).to receive(:new).with(path: pathname) + method_call + end + + it 'passed down the created repository object to the Verifier' do + expect(Dragnet::Verifier).to receive(:new) + .with(test_records: test_records, repository: repository_instance, logger: logger) + + method_call + end + end + + context 'when multi-repo compatibility is disabled' do + let(:repository_class) { Dragnet::Repository } + let(:repository_instance) { repository } + + include_examples 'creates a Repository and a Verifier' + end + + context 'when multi-repo compatibility is enabled' do + let(:repository_class) { Dragnet::MultiRepository } + let(:repository_instance) { multi_repository } + + before { master.options = master.options.merge('multi-repo': true) } + + include_examples 'creates a Repository and a Verifier' + end + end + + it 'creates an instance of the Explorer class' do + expect(Dragnet::Explorer).to receive(:new) + method_call + end + + it 'uses the instance of the Explorer class to get the list of MTR files' do + expect(explorer).to receive(:files) + method_call + end + + context 'when the Explorer class raises an ArgumentError', requirements: ['DRAGNET_0034'] do + before do + allow(Dragnet::Explorer).to receive(:new).and_raise( + ArgumentError, 'Missing required parameter glob_patterns' + ) + end + + it 'prints the expected error to the console' do + expect { method_call }.to raise_error(SystemExit).and output( + /Initialization error. Missing or malformed parameter\./ + ).to_stdout + end + + it 'prints the exception message to the console' do + expect { method_call }.to raise_error(SystemExit).and output( + /Missing required parameter glob_patterns/ + ).to_stdout + end + + it 'exists with the expected error code' do + expect { method_call }.to output.to_stdout.and( + raise_error { |error| expect(error.status).to eq(described_class::E_MISSING_PARAMETER_ERROR) } + ) + end + end + + context 'when the Explorer raises a Dragnet::Errors::NoMTRFilesFoundError', requirements: ['DRAGNET_0033'] do + before do + allow(explorer).to receive(:files).and_raise( + Dragnet::Errors::NoMTRFilesFoundError, + 'No MTR Files found in /Workspace/source with the following glob patterns: tests/manual/*.yaml' + ) + end + + it 'prints the expected error to the console' do + expect { method_call }.to raise_error(SystemExit).and output( + /No MTR Files found\./ + ).to_stdout + end + + it 'prints the exception message to the console' do + expect { method_call }.to raise_error(SystemExit).and output( + %r{No MTR Files found in /Workspace/source with the following glob patterns: tests/manual/\*\.yaml} + ).to_stdout + end + + it 'exists with the expected error code' do + expect { method_call }.to output.to_stdout.and( + raise_error { |error| expect(error.status).to eq(described_class::E_NO_MTR_FILES_FOUND) } + ) + end + end + + it 'creates an instance of the Validator class' do + expect(Dragnet::Validator).to receive(:new) + method_call + end + + it 'calls #validate on the validator' do + expect(validator).to receive(:validate) + method_call + end + + it 'creates an instance of the Verifier class' do + expect(Dragnet::Verifier).to receive(:new) + method_call + end + + context 'when the repository cannot be created' do + before do + allow(Dragnet::Repository).to receive(:new).and_raise( + ArgumentError, 'path does not exist from /Workspace/project' + ) + end + + it 'prints the expected error to the console' do + message = Regexp.escape("Could not open the specified path: #{Dir.pwd} as a Git Repository") + expect { method_call }.to raise_error(SystemExit) + .and output(Regexp.new(message)).to_stdout + end + + it 'prints the exception message to the console' do + message = Regexp.escape('path does not exist from /Workspace/project') + expect { method_call }.to raise_error(SystemExit) + .and output(Regexp.new(message)).to_stdout + end + + it 'exists with the expected error code' do + expect { method_call }.to output.to_stdout.and( + raise_error { |error| expect(error.status).to eq(described_class::E_GIT_ERROR) } + ) + end + end + + it 'calls #verify on the verifier' do + expect(verifier).to receive(:verify) + method_call + end + + context 'when the Verifier raises a Dragnet::Errors::IncompatibleRepositoryError' do + let(:expected_message_header) { 'Incompatible git operation:' } + let(:expected_message) { 'Incompatible git operation performed over a multi-repository' } + let(:expected_exit_code) { described_class::E_INCOMPATIBLE_REPOSITORY } + + before do + allow(verifier).to receive(:verify).and_raise( + Dragnet::Errors::IncompatibleRepositoryError, + expected_message + ) + end + + include_examples 'a fatal error is raised inside Dragnet::CLI::Master#check' + end + + context 'when no errors nor issues on the MTRs are found' do + let(:test_records) do + [ + instance_double( + Dragnet::TestRecord, + source_file: 'test/manual/ESR_REQ_5138.yaml', + result: 'passed', + verification_result: instance_double( + Dragnet::VerificationResult, + status: :passed, + passed?: true + ) + ), + instance_double( + Dragnet::TestRecord, + source_file: 'test/manual/ESR_REQ_4570.yaml', + result: 'passed', + verification_result: instance_double( + Dragnet::VerificationResult, + status: :passed, + passed?: true + ) + ) + ] + end + + it 'does not raise an error' do + expect { method_call }.not_to raise_error + end + end + + context 'when errors are detected in the MTR files' do + include_context 'when Dragnet::Validator detects error in the MTR files' + + it 'exits with the expected exit code' do + expect { method_call }.to raise_error(SystemExit) do |error| + expect(error.status).to eq(described_class::E_ERRORS_DETECTED) + end + end + end + + context 'when the verification fails for any of the MTR files' do + include_context 'when Dragnet::Verifier finds a failed MTR' + + it 'exists with the expected exit code' do + expect { method_call }.to raise_error(SystemExit) do |error| + expect(error.status).to eq(described_class::E_FAILED_TESTS) + end + end + end + + context 'when there are errors in the MTRs and the verification fails' do + include_context 'when Dragnet::Validator detects error in the MTR files' + include_context 'when Dragnet::Verifier finds a failed MTR' + + let(:expected_exit_code) do + described_class::E_ERRORS_DETECTED | described_class::E_FAILED_TESTS + end + + it 'exists with the expected exit code' do + expect { method_call }.to raise_error(SystemExit) do |error| + expect(error.status).to eq(expected_exit_code) + end + end + end + + context 'when export targets are given' do + let(:export_files) do + %w[ + output/report.html + output/report.tex + ] + end + + let(:exporter) do + instance_double( + Dragnet::Exporter, + export: true + ) + end + + before do + master.options = master.options.merge(export: export_files) + allow(Dragnet::Exporter).to receive(:new).and_return(exporter) + end + + shared_examples 'create an exporter with the expected parameters' do + it 'creates an exporter with the expected parameters (including the target files)' do + expect(Dragnet::Exporter).to receive(:new).with( + test_records: test_records, errors: errors, repository: repository_instance, targets: export_files, logger: logger + ) + + method_call + end + end + + context 'when the multi-repo compatibility is disabled' do + let(:repository_instance) { repository } + + include_examples 'create an exporter with the expected parameters' + end + + context 'when the multi-repo compatibility is enabled' do + let(:repository_instance) { multi_repository } + + before { master.options = master.options.merge('multi-repo': true) } + + include_examples 'create an exporter with the expected parameters' + end + + it 'executes the export procedure' do + expect(exporter).to receive(:export) + method_call + end + + shared_context 'when the Exporter raises a known error' do + before do + allow(exporter).to receive(:export).and_raise( + expected_error, expected_message + ) + end + end + + context 'when the Exporter raises a UnknownExportFormatError' do + let(:expected_error) { Dragnet::Errors::UnknownExportFormatError } + let(:expected_message_header) { 'Export failed' } + + let(:expected_message) do + "Unknown export format: '.tex'. Valid export formats are: .html, .htm" + end + + let(:expected_exit_code) { described_class::E_EXPORT_ERROR } + + include_context 'when the Exporter raises a known error' + include_examples 'a fatal error is raised inside Dragnet::CLI::Master#check' + end + + context 'when the Exporter raises an UnableToWriteReportError' do + let(:expected_error) { Dragnet::Errors::UnableToWriteReportError } + let(:expected_message_header) { 'Export failed' } + + let(:expected_message) do + 'Unable to write report output to output/report.html: Permission Denied' + end + + let(:expected_exit_code) { described_class::E_EXPORT_ERROR } + + include_context 'when the Exporter raises a known error' + include_examples 'a fatal error is raised inside Dragnet::CLI::Master#check' + end + + context 'when the Exporter raises a Dragnet::Errors::IncompatibleRepositoryError' do + let(:expected_error) { Dragnet::Errors::IncompatibleRepositoryError } + let(:expected_message_header) { 'Incompatible git operation:' } + let(:expected_message) { 'Incompatible git operation performed over a multi-repository' } + let(:expected_exit_code) { described_class::E_INCOMPATIBLE_REPOSITORY } + + include_context 'when the Exporter raises a known error' + include_examples 'a fatal error is raised inside Dragnet::CLI::Master#check' + end + end + end +end diff --git a/spec/dragnet/explorer_spec.rb b/spec/dragnet/explorer_spec.rb new file mode 100644 index 0000000..fc2c9a4 --- /dev/null +++ b/spec/dragnet/explorer_spec.rb @@ -0,0 +1,157 @@ +# frozen_string_literal: true + +require 'dragnet/explorer' + +RSpec.describe Dragnet::Explorer do + subject(:explorer) { described_class.new(path: path, glob_patterns: glob_patterns, logger: logger) } + + let(:path) { Pathname.new('/Workspace/source') } + let(:glob_patterns) { 'tests/manual/*.yaml' } + + let(:logger) do + instance_double( + Dragnet::CLI::Logger, + info: true + ) + end + + describe '#initialize', requirements: %w[DRAGNET_0001 DRAGNET_0002] do + subject(:method_call) { explorer } + + describe 'parameter checks', requirements: ['DRAGNET_0034'] do + context 'when the path is missing' do + let(:path) { nil } + + it 'raises an ArgumentError' do + expect { method_call }.to raise_error( + ArgumentError, 'Missing required parameter path' + ) + end + end + + context 'when the path has an invalid type' do + let(:path) { [] } + + it 'raises an ArgumentError' do + expect { method_call }.to raise_error( + ArgumentError, + 'Incompatible parameter type path. Expected: Pathname, given: Array' + ) + end + end + + context 'when the glob_patterns are missing' do + let(:glob_patterns) { nil } + + it 'raises an ArgumentError' do + expect { method_call }.to raise_error( + ArgumentError, 'Missing required parameter glob_patterns' + ) + end + end + + context 'when the glob patterns have an invalid type' do + let(:glob_patterns) { {} } + + it 'raises an ArgumentError' do + expect { method_call }.to raise_error( + ArgumentError, 'Incompatible parameter type glob_patterns. Expected: String or Array, given: Hash' + ) + end + end + + context 'when one of the glob patterns is not a string' do + let(:glob_patterns) { ['requirements/*.yaml', 2] } + + it 'raises an ArgumentError' do + expect { method_call }.to raise_error( + ArgumentError, 'Incompatible parameter type glob_patterns. Expected: String or Array, given: Array' + ) + end + end + end + + context 'when glob_patterns is not an array' do + let(:glob_patterns) { 'src/main/reqs/*.yaml' } + + it 'turns it into an array' do + expect(explorer.glob_patterns).to eq([glob_patterns]) + end + end + end + + describe '#files' do + subject(:method_call) { explorer.files } + + context 'when no files are found on the given path', requirements: ['DRAGNET_0033'] do + before do + allow(path).to receive(:glob).with('tests/manual/*.yaml').and_return([]) + end + + it 'raises a Dragnet::Errors::NoMTRFilesFoundError' do + expect { method_call }.to raise_error( + Dragnet::Errors::NoMTRFilesFoundError, + 'No MTR Files found in /Workspace/source with the following glob patterns: tests/manual/*.yaml' + ) + end + end + + context 'when the explorer finds files' do + let(:files) do + %w[ + /Workspace/source/tests/manual/ESR_9473.yaml + /Workspace/source/tests/manual/ESR_1532.yaml + ] + end + + before do + allow(path).to receive(:glob).with('tests/manual/*.yaml').and_return(files) + end + + shared_examples_for '#files when the explorer finds files' do + it 'logs the found MTR files', requirements: %w[DRAGNET_0032] do + expect(logger).to receive(:info).with('Found MTR file: /Workspace/source/tests/manual/ESR_9473.yaml') + expect(logger).to receive(:info).with('Found MTR file: /Workspace/source/tests/manual/ESR_1532.yaml') + method_call + end + end + + include_examples '#files when the explorer finds files' + + it 'returns the list of found files' do + expect(method_call).to eq(files) + end + + context 'when two or more glob patterns are given' do + let(:glob_patterns) { %w[tests/manual/*.yaml req/manual/*.yml] } + + let(:other_files) do + %w[ + /Workspace/source/req/manual/ESR_6348.yml + ] + end + + before do + allow(path).to receive(:glob).with('req/manual/*.yml').and_return(other_files) + end + + it 'searches for files using both patterns' do + expect(path).to receive(:glob).with('tests/manual/*.yaml') + expect(path).to receive(:glob).with('req/manual/*.yml') + method_call + end + + it_behaves_like '#files when the explorer finds files' + + it 'logs the MTR found in the second glob pattern', requirements: %w[DRAGNET_0032] do + expect(logger).to receive(:info).with('Found MTR file: /Workspace/source/req/manual/ESR_6348.yml') + method_call + end + + it 'returns the files returned from both patterns' do + expect(method_call).to eq(files + other_files) + end + end + end + end +end diff --git a/spec/dragnet/exporter_spec.rb b/spec/dragnet/exporter_spec.rb new file mode 100644 index 0000000..eb2e9f0 --- /dev/null +++ b/spec/dragnet/exporter_spec.rb @@ -0,0 +1,174 @@ +# frozen_string_literal: true + +require 'dragnet/exporter' + +RSpec.describe Dragnet::Exporter do + subject(:exporter) do + described_class.new( + test_records: test_records, errors: errors, repository: repository, targets: targets, logger: logger + ) + end + + let(:test_records) { [] } + let(:errors) { [] } + let(:repository) { instance_double(Dragnet::Repository) } + let(:targets) { %w[output/export.html] } + + let(:logger) do + instance_double( + Dragnet::CLI::Logger, + debug: true, + info: true + ) + end + + describe '#export' do + subject(:method_call) { exporter.export } + + let(:html_output) do + <<~HTML + + + Test Output + + + HTML + end + + let(:html_exporter) do + instance_double( + Dragnet::Exporters::HTMLExporter, + export: html_output + ) + end + + let(:json_output) do + <<~JSON + [ + {"first": "MTR"}, + {"second": "MTR"} + ] + JSON + end + + let(:json_exporter) do + instance_double( + Dragnet::Exporters::JSONExporter, + export: json_output + ) + end + + before do + allow(Dragnet::Exporters::HTMLExporter) + .to receive(:new).and_return(html_exporter) + + allow(Dragnet::Exporters::JSONExporter) + .to receive(:new).and_return(json_exporter) + + allow(File).to receive(:write).and_return(2459) + end + + context 'when one of the target files has an unknown format' do + let(:targets) { %w[output/report.HTML output/report.log] } + + it 'raises a Dragnet::Errors::UnknownExportFormatError' do + expect { method_call }.to raise_error( + Dragnet::Errors::UnknownExportFormatError, + "Unknown export format: '.log'. Valid export formats are: .html, .htm, .json" + ) + end + end + + describe 'exporters creation (one for each target type)' do + let(:targets) { %w[output/report.html output/report.json] } + + it 'creates an HTML exporter' do + expect(Dragnet::Exporters::HTMLExporter).to receive(:new).with( + test_records: test_records, errors: errors, repository: repository, logger: logger + ) + + method_call + end + + it 'calls export on the HTML exporter' do + expect(html_exporter).to receive(:export) + method_call + end + + it 'creates a JSON exporter' do + expect(Dragnet::Exporters::JSONExporter).to receive(:new).with( + test_records: test_records, errors: errors, repository: repository, logger: logger + ) + + method_call + end + + it 'calls export on the JSON exporter' do + expect(json_exporter).to receive(:export) + method_call + end + end + + it 'writes the output to the target file' do + expect(File).to receive(:write).with(targets.first, html_output) + method_call + end + + context 'when targets with multiple formats are given' do + let(:targets) { %w[output/report.html output/report.json] } + + it 'creates an exporter for the HTML report' do + expect(Dragnet::Exporters::HTMLExporter).to receive(:new).once + method_call + end + + it 'writes the output to the HTML target' do + expect(File).to receive(:write).with('output/report.html', html_output) + method_call + end + + it 'creates an exporter for the JSON report' do + expect(Dragnet::Exporters::JSONExporter).to receive(:new).once + method_call + end + + it 'writes the output to the JSON target', requirements: %w[DRAGNET_0060] do + expect(File).to receive(:write).with('output/report.json', json_output) + method_call + end + end + + context 'when multiple output files with the same format are given' do + let(:targets) { %w[output/report.html output/other-report.htm] } + + it 'creates ONLY ONE exporter for each format' do + expect(Dragnet::Exporters::HTMLExporter).to receive(:new).once + method_call + end + + it 'writes the output to all given targets' do + targets.each do |target| + expect(File).to receive(:write).with(target, html_output) + end + + method_call + end + end + + context 'when the output file cannot be written' do + before do + allow(File).to receive(:write).and_raise( + Errno::EACCES, 'Read only file system' + ) + end + + it 'raises a Dragnet::Errors::UnableToWriteReportError' do + expect { method_call } + .to raise_error( + Dragnet::Errors::UnableToWriteReportError, + 'Unable to write report output to output/export.html: Permission denied - Read only file system' + ) + end + end + end +end diff --git a/spec/dragnet/exporters/exporter_spec.rb b/spec/dragnet/exporters/exporter_spec.rb new file mode 100644 index 0000000..ef26564 --- /dev/null +++ b/spec/dragnet/exporters/exporter_spec.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +require 'dragnet/exporters/exporter' + +RSpec.describe Dragnet::Exporters::Exporter do + subject(:exporter) do + described_class.new(test_records: test_records, errors: errors, repository: repository, logger: logger) + end + + let(:test_records) { [] } + let(:errors) { [] } + + let(:repository) do + instance_double( + Dragnet::Repository + ) + end + + let(:logger) do + instance_double( + Logger + ) + end + + describe '#export' do + subject(:method_call) { exporter.export } + + it 'raises a NotImplementedError' do + expect { method_call }.to raise_error( + NotImplementedError, + "'export' method not implemented for class Dragnet::Exporters::Exporter" + ) + end + end +end diff --git a/spec/dragnet/exporters/html_exporter_spec.rb b/spec/dragnet/exporters/html_exporter_spec.rb new file mode 100644 index 0000000..b6e5aa2 --- /dev/null +++ b/spec/dragnet/exporters/html_exporter_spec.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: true + +require 'dragnet/exporters/html_exporter' + +RSpec.describe Dragnet::Exporters::HTMLExporter, requirements: ['DRAGNET_0022'] do + subject(:html_exporter) do + described_class.new( + test_records: test_records, errors: errors, repository: repository, logger: logger + ) + end + + let(:test_records) { [] } + let(:errors) { [] } + + let(:repository) do + instance_double( + Dragnet::Repository + ) + end + + let(:logger) do + instance_double( + Dragnet::CLI::Logger, + info: true + ) + end + + let(:template) do + <<~ERB + + ERB + end + + let(:output) { '' } + + let(:erb) do + instance_double( + ERB, + result: output + ) + end + + before do + allow(File).to receive(:read).with(described_class::TEMPLATE).and_return(template) + allow(ERB).to receive(:new).and_return(erb) + end + + describe '#export' do + subject(:method_call) { html_exporter.export } + + it 'logs the template being used for export' do + expect(logger).to receive(:info).with( + "Generating HTML report from template: #{described_class::TEMPLATE}..." + ) + + method_call + end + + it 'reads the template and passes it down to ERB' do + expect(File).to receive(:read).with(described_class::TEMPLATE).and_return(template) + expect(ERB).to receive(:new).with(template) + method_call + end + + it "calls result on ERB and passes the class's bindings to it" do + expect(erb).to receive(:result).with(instance_of(Binding)) + method_call + end + + it "returns the output returned by ERB's #result method" do + expect(method_call).to eq(output) + end + end +end diff --git a/spec/dragnet/exporters/id_generator_spec.rb b/spec/dragnet/exporters/id_generator_spec.rb new file mode 100644 index 0000000..851de9d --- /dev/null +++ b/spec/dragnet/exporters/id_generator_spec.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +require 'dragnet/exporters/id_generator' +require 'dragnet/multi_repository' +require 'dragnet/test_record' + +RSpec.describe Dragnet::Exporters::IDGenerator, requirements: %w[DRAGNET_0067] do + subject(:id_generator) { described_class.new(repository) } + + let(:repository) do + instance_double( + Dragnet::MultiRepository, + path: Pathname.new('/workspace/project') + ) + end + + describe '#id_for' do + subject(:method_call) { id_generator.id_for(test_record) } + + let(:test_record) do + instance_double( + Dragnet::TestRecord, + source_file: Pathname.new('/workspace/project/MTR/buffer_overflow.yaml'), + id: id + ) + end + + context 'when the Test Record has only one ID' do + let(:id) { 'ESR_REQ_2370' } + + it 'returns the expected string' do + # Hashed string: "MTR/buffer_overflow.yamlESR_REQ_2370" + expect(method_call).to eq('18572e9e32d29aae') + end + end + + context 'when the Test Record has multiple IDs' do + let(:id) { %w[ESR_REQ_9788 ESR_REQ_7249] } + + it 'returns the expected string' do + # Hashed string: "MTR/buffer_overflow.yaml[\"ESR_REQ_9788\", \"ESR_REQ_7249\"]" + expect(method_call).to eq('0a142cfc270408a2') + end + end + end +end diff --git a/spec/dragnet/exporters/json_exporter_spec.rb b/spec/dragnet/exporters/json_exporter_spec.rb new file mode 100644 index 0000000..0d93e01 --- /dev/null +++ b/spec/dragnet/exporters/json_exporter_spec.rb @@ -0,0 +1,163 @@ +# frozen_string_literal: true + +require 'dragnet/exporters/json_exporter' + +RSpec.describe Dragnet::Exporters::JSONExporter, requirements: %w[DRAGNET_0060] do + subject(:json_exporter) do + described_class.new(test_records: test_records, errors: errors, repository: repository, logger: logger) + end + + let(:test_records) do + [ + instance_double(Dragnet::TestRecord), + instance_double(Dragnet::TestRecord), + instance_double(Dragnet::TestRecord) + ] + end + + let(:errors) { [] } + + let(:repository) do + instance_double( + Dragnet::Repository + ) + end + + let(:logger) do + instance_double( + Logger, + info: true + ) + end + + describe '#export' do + subject(:method_call) { json_exporter.export } + + let(:test_record_serializer) do + instance_double( + Dragnet::Exporters::Serializers::TestRecordSerializer + ) + end + + let(:serialized_test_records) do + [ + { + refs: %w[ESR_REQ_1559], + result: 'passed', + sha1: 'b226f108ff1b83d911264fa224f4f56435a7742f' + }, + { + refs: %w[ESR_REQ_6860], + result: 'passed', + sha1: '889b64e1b363fd25b0e49da41c5c717c04b37f47' + }, + { + refs: %w[ESR_REQ_8988], + result: 'failed', + sha1: 'af91433d43978a356c19f3b18ffd52dbd9f5c136' + } + ] + end + + let(:expected_json) do + '[' \ + '{' \ + '"refs":["ESR_REQ_1559"],' \ + '"result":"passed",' \ + '"sha1":"b226f108ff1b83d911264fa224f4f56435a7742f",' \ + '"id":"f8f653fd1d2fc7af"'\ + '},' \ + '{' \ + '"refs":["ESR_REQ_6860"],' \ + '"result":"passed",' \ + '"sha1":"889b64e1b363fd25b0e49da41c5c717c04b37f47",' \ + '"id":"e3145e30a4468b60"' \ + '},' \ + '{' \ + '"refs":["ESR_REQ_8988"],' \ + '"result":"failed",' \ + '"sha1":"af91433d43978a356c19f3b18ffd52dbd9f5c136",' \ + '"id":"e0454575ffa3d94f"' \ + '}' \ + ']' + end + + let(:ids) do + %w[ + f8f653fd1d2fc7af + e3145e30a4468b60 + e0454575ffa3d94f + ] + end + + let(:id_generator) do + instance_double( + Dragnet::Exporters::IDGenerator + ) + end + + before do + allow(Dragnet::Exporters::Serializers::TestRecordSerializer) + .to receive(:new).and_return(test_record_serializer) + + allow(test_record_serializer).to receive(:serialize).and_return(*serialized_test_records) + + allow(Dragnet::Exporters::IDGenerator).to receive(:new).and_return(id_generator) + allow(id_generator).to receive(:id_for).and_return(*ids) + end + + it 'passes each of the given Test Records to the Serializer' do + test_records.each do |test_record| + expect(Dragnet::Exporters::Serializers::TestRecordSerializer) + .to receive(:new).with(test_record, repository) + end + + method_call + end + + it 'creates a single instance of the IDGenerator class', requirements: %w[DRAGNET_0066] do + expect(Dragnet::Exporters::IDGenerator).to receive(:new).with(repository).once + method_call + end + + it 'generates IDs for each of the Test Records', requirements: %w[DRAGNET_0066] do + test_records.each do |test_record| + expect(id_generator).to receive(:id_for).with(test_record) + end + + method_call + end + + it 'calls serialize as many times as there are Test Records' do + expect(test_record_serializer).to receive(:serialize) + .exactly(test_records.size).times + + method_call + end + + it 'returns the expected JSON string' do + expect(method_call).to eq(expected_json) + end + + describe 'Generated JSON string' do + subject(:generated_json) { method_call } + + context 'when parsed' do + subject(:parsed_json) { JSON.parse(generated_json) } + + it 'produces an Array' do + expect(parsed_json).to be_an(Array) + end + + it 'produces an Array of Hashes', requirements: %w[DRAGNET_0061] do + expect(parsed_json).to all(be_a(Hash)) + end + + it 'produces an array with the same number of elements as Test Records there are', + requirements: %w[DRAGNET_0061] do + expect(parsed_json.size).to eq(test_records.size) + end + end + end + end +end diff --git a/spec/dragnet/exporters/serializers/repo_serializer_spec.rb b/spec/dragnet/exporters/serializers/repo_serializer_spec.rb new file mode 100644 index 0000000..5f4ce26 --- /dev/null +++ b/spec/dragnet/exporters/serializers/repo_serializer_spec.rb @@ -0,0 +1,78 @@ +# frozen_string_literal: true + +require 'dragnet/exporters/serializers/repo_serializer' + +RSpec.describe Dragnet::Exporters::Serializers::RepoSerializer do + subject(:repo_serializer) { described_class.new(repo) } + + let(:path) { 'path/to/repo' } + let(:sha1) { '1a3425a' } + let(:files) { nil } + + let(:repo) do + instance_double( + Dragnet::Repo, + path: path, + sha1: sha1, + files: files + ) + end + + describe '#serialize' do + subject(:method_call) { repo_serializer.serialize } + + it 'produces a Hash' do + expect(method_call).to be_a(Hash) + end + + it 'includes the path to the repo' do + expect(method_call).to include(path: path) + end + + it 'includes the SHA1 of the repo' do + expect(method_call).to include(sha1: sha1) + end + + shared_examples_for '#serialize when the Repo has no listed files' do + it 'does not include the :files key' do + expect(method_call).not_to have_key(:files) + end + end + + context 'when the repo has no listed files' do + let(:files) { nil } + + it_behaves_like '#serialize when the Repo has no listed files' + end + + context 'when the list of files is empty' do + let(:files) { [] } + + it_behaves_like '#serialize when the Repo has no listed files' + end + + context 'when there are listed files' do + let(:files) do + [ + 'path/to/repo/some/directory/file.cpp', # Has the path to the repo in it + Pathname.new('path/to/repo/another/directory/other-file.cpp'), # Pathname and path to the repo + 'just/a/simple-file.h', # A simple file, without the repo's path + Pathname.new('another/simple/file/in/a/directory.c') # Pathname, without the path to the repo + ] + end + + let(:expected_files) do + %w[ + some/directory/file.cpp + another/directory/other-file.cpp + just/a/simple-file.h + another/simple/file/in/a/directory.c + ] + end + + it 'includes the expected list of files' do + expect(method_call).to include(files: expected_files) + end + end + end +end diff --git a/spec/dragnet/exporters/serializers/test_record_serializer_spec.rb b/spec/dragnet/exporters/serializers/test_record_serializer_spec.rb new file mode 100644 index 0000000..1895b1b --- /dev/null +++ b/spec/dragnet/exporters/serializers/test_record_serializer_spec.rb @@ -0,0 +1,406 @@ +# frozen_string_literal: true + +require 'dragnet/exporters/serializers/test_record_serializer' + +RSpec.describe Dragnet::Exporters::Serializers::TestRecordSerializer do + subject(:test_record_serializer) { described_class.new(test_record, repository) } + + let(:id) { 'ESR_REQ_7630' } + let(:result) { 'passed' } + let(:sha1) { nil } + let(:name) { nil } + let(:description) { nil } + let(:test_method) { nil } + let(:tc_derivation_method) { nil } + let(:reviewed) { false } + let(:review_comments) { nil } + let(:has_findings) { false } + let(:findings) { nil } + let(:files) { nil } + let(:repos) { nil } + + let(:verification_result) do + instance_double( + Dragnet::VerificationResult + ) + end + + let(:test_record) do + instance_double( + Dragnet::TestRecord, + id: id, + result: result, + reviewed?: reviewed, + review_comments: review_comments, + sha1: sha1, + name: name, + description: description, + test_method: test_method, + tc_derivation_method: tc_derivation_method, + findings?: has_findings, + findings: findings, + verification_result: verification_result, + files: files, + repos: repos + ) + end + + let(:repository) do + instance_double( + Dragnet::Repository, + path: Pathname.new('/workspace/path/to/repo') + ) + end + + describe '#serialize' do + subject(:method_call) { test_record_serializer.serialize } + + let(:serialized_verification_result) do + { + status: :passed, + started_at: Time.new(2024, 2, 28, 15, 36, 48), + finished_at: Time.new(2024, 2, 28, 15, 36, 50) + } + end + + let(:verification_result_serializer) do + instance_double( + Dragnet::Exporters::Serializers::VerificationResultSerializer, + serialize: serialized_verification_result + ) + end + + before do + allow(Dragnet::Exporters::Serializers::VerificationResultSerializer) + .to receive(:new).and_return(verification_result_serializer) + end + + it 'returns a Hash' do + expect(method_call).to be_a(Hash) + end + + context 'when the ID of the Test Record is a String' do + let(:id) { 'ESR_REQ_7630' } + + it 'includes the expected Array of "refs"', requirements: %w[DRAGNET_0064] do + expect(method_call).to include(refs: [id]) + end + end + + context 'when the ID of the Test Record is an Array' do + let(:id) { %w[ESR_REQ_1008 ESR_REQ_1065] } + + it 'includes the expected Array of "refs"', requirements: %w[DRAGNET_0064] do + expect(method_call).to include(refs: id) + end + end + + it 'includes the result of the Test Record' do + expect(method_call).to include(result: result) + end + + context "when the Test Record doesn't have a SHA1" do + let(:sha1) { nil } + + it 'does not include the :sha1 key' do + expect(method_call).not_to have_key(:sha1) + end + end + + context 'when the TestRecord has a SHA1' do + let(:sha1) { '76e440d0d12763baaf0f825ad4eee9a1b28afa5c' } + + it "includes the Test Record's SHA1" do + expect(method_call).to include(sha1: sha1) + end + end + + context "when the TestRecord doesn't have the tester's name" do + let(:name) { nil } + + it 'does not include the :owner key', requirements: %w[DRAGNET_0071] do + expect(method_call).not_to have_key(:owner) + end + end + + context "when the TestRecord has the tester's name" do + context 'when there is a single tester' do + let(:name) { ['Freddy Mercury'] } + + it "includes the tester's name (as 'owner')", requirements: %w[DRAGNET_0065] do + expect(method_call).to include(owner: 'Freddy Mercury') + end + end + + context 'when there are multiple testers' do + let(:name) { ['Freddy Mercury', 'Brian May', 'John Deacon', 'Roger Taylor'] } + + it "includes all the testers' names as a single string", requirements: %w[DRAGNET_0071] do + expect(method_call).to include(owner: 'Freddy Mercury, Brian May, John Deacon, Roger Taylor') + end + end + end + + context "when the TestRecord doesn't have a description" do + it 'does not include the :description key' do + expect(method_call).not_to have_key(:description) + end + end + + context 'when the TestRecord has a description' do + let(:description) do + <<~TEXT + Perform a factory reset of the ECU and checks that: + * The ROM wasn't deleted and the checksum of the ROM image is still valid. + * The VKMS keys have not been lost. + * All the DTC has been cleared. + * The system can still boot to the application. + TEXT + end + + it "includes the Manual Test Record's description" do + expect(method_call).to include(description: description) + end + end + + context "when the TestRecord doesn't have a test method" do + let(:test_method) { nil } + + it 'does not include the :test_method key', requirements: %w[DRAGNET_0070] do + expect(method_call).not_to have_key(:test_method) + end + end + + context 'when the TestRecord has a test method', requirements: %w[DRAGNET_0070] do + context 'when there is a single method' do + let(:test_method) { 'Failure injection' } + + it "includes the Manual Test Record's test method(s)" do + expect(method_call).to include(test_method: ['Failure injection']) + end + end + + context 'when there are multiple methods' do + let(:test_method) { ['Main-path checking', 'Tampering'] } + + it "includes the Manual Test Record's test method(s)" do + expect(method_call).to include(test_method: test_method) + end + end + end + + context "when the TestRecord doesn't have a derivation method" do + let(:tc_derivation_method) { nil } + + it 'does not include the :tc_derivation_method key', requirements: %w[DRAGNET_0070] do + expect(method_call).not_to have_key(:tc_derivation_method) + end + end + + context 'when the TestRecord has a derivation method', requirements: %w[DRAGNET_0070] do + context 'when there is a single method' do + let(:tc_derivation_method) { 'Decision tree' } + + it "includes the Manual Test Record's test case derivation method" do + expect(method_call).to include(tc_derivation_method: ['Decision tree']) + end + end + + context 'when there are multiple methods' do + let(:tc_derivation_method) { ['BVA', 'Error guessing'] } + + it "includes the Manual Test Record's test case derivation method" do + expect(method_call).to include(tc_derivation_method: tc_derivation_method) + end + end + end + + context 'when the TestRecord has not been reviewed' do + let(:reviewed) { false } + + it 'includes the expected review_status field' do + expect(method_call).to include(review_status: 'not_reviewed') + end + end + + context 'when the TestRecord has been reviewed' do + let(:reviewed) { true } + + it 'includes the expected review_status field' do + expect(method_call).to include(review_status: 'reviewed') + end + end + + context 'when the TestRecord has no review comments' do + let(:review_comments) { nil } + + it 'does not include the :review_comments key' do + expect(method_call).not_to have_key(:review_comments) + end + end + + context 'when the TestRecord has review comments' do + let(:review_comments) do + <<~TEXT + Reviewed by John Wix on 23th February 2023 + * The MTR should include the checksum of the ROM image + and the expected VKMS keys. + TEXT + end + + it 'includes the expected review comments' do + expect(method_call).to include(review_comments: review_comments) + end + end + + context 'when the TestRecord has no findings' do + let(:has_findings) { false } + + it 'does not include the :findings keys' do + expect(method_call).not_to have_key(:findings) + end + end + + context 'when the TestRecord has findings' do + let(:has_findings) { true } + + let(:findings) do + <<~TEXT + After performing the reset the ECU had to be power cycled twice for + it to boot to the application. + TEXT + end + + it 'includes the findings' do + expect(method_call).to include(findings: findings) + end + end + + it "includes the TestRecord's serialized VerificationResult" do + expect(method_call).to include(verification_result: serialized_verification_result) + end + + it "includes the 'started_at' attribute from the TestRecord's VerificationResult" do + expect(method_call).to include(started_at: serialized_verification_result[:started_at]) + end + + it "includes the 'finished_at' attribute from the TestRecord's VerificationResult" do + expect(method_call).to include(finished_at: serialized_verification_result[:finished_at]) + end + + shared_examples_for '#serialize when the TestRecord has no files' do + it 'does not include the :files key' do + expect(method_call).not_to have_key(:files) + end + end + + context 'when the TestRecord has no files' do + let(:files) { nil } + + it_behaves_like '#serialize when the TestRecord has no files' + end + + context "when the TestRecord's files attribute is an empty Array" do + let(:files) { [] } + + it_behaves_like '#serialize when the TestRecord has no files' + end + + context 'when the TestRecord has listed files' do + let(:files) do + [ + Pathname.new('/workspace/path/to/repo/some/directory/module.cpp'), + Pathname.new('/workspace/path/to/repo/other/folder/new_module.h'), + Pathname.new('/workspace/path/to/repo/Makefile') + ] + end + + let(:expected_files) do + %w[ + some/directory/module.cpp + other/folder/new_module.h + Makefile + ] + end + + it 'includes the expected array of files' do + expect(method_call).to include(files: expected_files) + end + end + + shared_examples_for '#serialize when the TestRecord has no Repos' do + it 'does not include the :repos key' do + expect(method_call).not_to have_key(:repos) + end + end + + context 'when the TestRecord has no Repos' do + let(:repos) { nil } + + it_behaves_like '#serialize when the TestRecord has no Repos' + end + + context "when the TestRecord's repos attribute is an empty array" do + let(:repos) { [] } + + it_behaves_like '#serialize when the TestRecord has no Repos' + end + + context 'when the TestRecord has Repos' do + let(:repository) do + instance_double( + Dragnet::MultiRepository, + path: Pathname.new('/workspace/source/pd') + ) + end + + let(:repos) do + [ + instance_double(Dragnet::Repo), + instance_double(Dragnet::Repo), + instance_double(Dragnet::Repo) + ] + end + + let(:serialized_repos) do + [ + { + path: 'esrlabs/crypto/aes256', + sha1: 'd33c6e2bd8e37bc5d93dcabbfee2ee55469f428e' + }, + { + path: 'esrlabs/bsw/can', + sha1: '24987d89b32a979f39900499bde1ed713e1cd610', + files: %w[ + driver/base.h + driver/base.cpp + driver/checksum.cpp + ] + }, + { + path: 'platform/system/iot/attestation', + sha1: 'b72d3e6d4a91eb282927f29f8a2508a2a2e3711c', + files: %w[Makefile] + } + ] + end + + let(:repo_serializer) do + instance_double( + Dragnet::Exporters::Serializers::RepoSerializer + ) + end + + before do + allow(Dragnet::Exporters::Serializers::RepoSerializer) + .to receive(:new).and_return(repo_serializer) + + allow(repo_serializer).to receive(:serialize).and_return(*serialized_repos) + end + + it 'includes the serialized version of the attached Repo objects' do + expect(method_call).to include(repos: serialized_repos) + end + end + end +end diff --git a/spec/dragnet/exporters/serializers/verification_result_serializer_spec.rb b/spec/dragnet/exporters/serializers/verification_result_serializer_spec.rb new file mode 100644 index 0000000..ae83469 --- /dev/null +++ b/spec/dragnet/exporters/serializers/verification_result_serializer_spec.rb @@ -0,0 +1,71 @@ +# frozen_string_literal: true + +require 'dragnet/exporters/serializers/verification_result_serializer' + +RSpec.describe Dragnet::Exporters::Serializers::VerificationResultSerializer do + subject(:verification_result_serializer) { described_class.new(verification_result) } + + let(:status) { :passed } + let(:reason) { nil } + let(:started_at) { Time.new(2024, 2, 28, 14, 11, 36, 'UTC') } + let(:finished_at) { Time.new(2024, 2, 28, 14, 11, 42, 'UTC') } + let(:runtime) { finished_at - started_at } + + let(:verification_result) do + instance_double( + Dragnet::VerificationResult, + status: status, + reason: reason, + started_at: started_at, + finished_at: finished_at, + runtime: runtime + ) + end + + describe '#serialize' do + subject(:method_call) { verification_result_serializer.serialize } + + shared_examples_for '#serialize' do + it 'produces a Hash' do + expect(method_call).to be_a(Hash) + end + + it 'includes the status of the Verification Result' do + expect(method_call).to include(status: status) + end + + it 'includes the started_at attribute' do + expect(method_call).to include(started_at: '2024-02-28 14:11:36 +0000') + end + + it 'includes the finished_at attribute' do + expect(method_call).to include(finished_at: '2024-02-28 14:11:42 +0000') + end + + it 'includes the runtime attribute' do + expect(method_call).to include(runtime: runtime) + end + end + + context "when the Verification Result doesn't have a reason" do + let(:reason) { nil } + + it_behaves_like '#serialize' + + it 'does not include the :reason key' do + expect(method_call).not_to have_key(:reason) + end + end + + context 'when the Verification Result has a reason' do + let(:status) { :skipped } + let(:reason) { 'Changes detected in the repository' } + + it_behaves_like '#serialize' + + it 'includes the reason' do + expect(method_call).to include(reason: reason) + end + end + end +end diff --git a/spec/dragnet/helpers/repository_helper_spec.rb b/spec/dragnet/helpers/repository_helper_spec.rb new file mode 100644 index 0000000..d985bf7 --- /dev/null +++ b/spec/dragnet/helpers/repository_helper_spec.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +require 'dragnet/helpers/repository_helper' + +RSpec.describe Dragnet::Helpers::RepositoryHelper do + subject(:test_class) do + Class.new do + include Dragnet::Helpers::RepositoryHelper + end.new + end + + describe '#shorten_sha1' do + subject(:method_call) { test_class.shorten_sha1(sha1) } + + let(:sha1) { '96731e7330180ac41f168c5707628eaffa718c4a' } + + it 'returns only the first 10 characters of the given string' do + expect(method_call).to eq('96731e7330') + end + end +end diff --git a/spec/dragnet/multi_repository_spec.rb b/spec/dragnet/multi_repository_spec.rb new file mode 100644 index 0000000..1f5bfc1 --- /dev/null +++ b/spec/dragnet/multi_repository_spec.rb @@ -0,0 +1,121 @@ +# frozen_string_literal: true + +require 'dragnet/multi_repository' +require 'dragnet/repository' + +RSpec.shared_examples_for 'Dragnet::BaseRepository#incompatible_repository' do + let(:message) do + "Failed to perform the action '#{method_name}' on '#{path}'. There isn't a git"\ + ' repository there. If you are running with the --multi-repo command line'\ + " switch make sure that all of your MTRs contain a valid 'repos' attribute." + end + + it 'raises a Dragnet::Errors::IncompatibleRepositoryError' do + expect { method_call }.to raise_error( + Dragnet::Errors::IncompatibleRepositoryError, + message + ) + end +end + +RSpec.describe Dragnet::MultiRepository do + subject(:multi_repository) { described_class.new(path: path) } + + let(:path) { '/workspace/project' } + + describe 'contract' do + let(:repository) { Dragnet::Repository.new(path: path) } + + let(:git) do + instance_double(Git::Base) + end + + before do + allow(Git).to receive(:open).and_return(git) + end + + it 'responds to the same methods as Dragnet::Repository' do + expect(repository.methods).to all( + satisfy { |method| multi_repository.respond_to?(method) } + ) + end + end + + describe '#initialize' do + it 'initializes an empty repositories list' do + expect(multi_repository.repositories).to be_a(Hash).and be_empty + end + end + + describe '#multi?' do + it 'returns true' do + expect(multi_repository.multi?).to eq(true) + end + end + + describe '#git' do + subject(:method_call) { multi_repository.git } + + let(:method_name) { :git } + + it_behaves_like 'Dragnet::BaseRepository#incompatible_repository' + end + + describe '#branch' do + subject(:method_call) { multi_repository.branch } + + let(:method_name) { :branch } + + it_behaves_like 'Dragnet::BaseRepository#incompatible_repository' + end + + describe '#branches' do + subject(:method_call) { multi_repository.branches } + + let(:method_name) { :branches } + + it_behaves_like 'Dragnet::BaseRepository#incompatible_repository' + end + + describe '#diff' do + subject(:method_call) { multi_repository.diff } + + let(:method_name) { :diff } + + it_behaves_like 'Dragnet::BaseRepository#incompatible_repository' + end + + describe '#head' do + subject(:method_call) { multi_repository.head } + + let(:method_name) { :head } + + it_behaves_like 'Dragnet::BaseRepository#incompatible_repository' + end + + describe '#remote_uri_path' do + subject(:method_call) { multi_repository.remote_uri_path } + + let(:method_name) { :remote_uri_path } + + it_behaves_like 'Dragnet::BaseRepository#incompatible_repository' + end + + describe '#branches_with' do + subject(:method_call) { multi_repository.branches_with(commit) } + + let(:commit) { 'e1675e7bf1' } + let(:method_name) { :branches_with } + + it_behaves_like 'Dragnet::BaseRepository#incompatible_repository' + end + + describe '#branches_with_head' do + subject(:method_call) { multi_repository.branches_with_head } + + let(:method_name) { :branches_with_head } + + it_behaves_like 'Dragnet::BaseRepository#incompatible_repository' + end +end + diff --git a/spec/dragnet/repo_spec.rb b/spec/dragnet/repo_spec.rb new file mode 100644 index 0000000..4a61175 --- /dev/null +++ b/spec/dragnet/repo_spec.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +require 'dragnet/repo' + +RSpec.describe Dragnet::Repo do + subject(:repo) { described_class.new(**params) } + + let(:path) { 'esrlabs/bsw/crypto' } + let(:sha1) { 'a7e08c441d61cec17a007c25712b86f5b0db56bc' } + let(:files) { %w[utils/bam2f_keys.cpp utils/blowfish_algo.cpp utils/headers/blowfish.h] } + + let(:params) { { path: path, sha1: sha1, files: files } } + + describe '#initialize' do + context 'without files' do + let(:params) { { path: path, sha1: sha1 } } + + it 'does not raise any errors', requirements: ['DRAGNET_0049'] do + expect { repo }.not_to raise_error + end + end + + context 'when files is nil' do + let(:files) { nil } + + it 'does not rise any errors', requirements: ['DRAGNET_0049'] do + expect { repo }.not_to raise_error + end + end + end + + describe '#validate' do + subject(:method_call) { repo.validate } + + let(:repo_validator) do + instance_double( + Dragnet::Validators::Entities::RepoValidator, + validate: nil + ) + end + + before do + allow(Dragnet::Validators::Entities::RepoValidator) + .to receive(:new).and_return(repo_validator) + end + + context 'when the validation passes' do + it 'does not raise any errors' do + expect { method_call }.not_to raise_error + end + end + + context 'when the validation fails' do + let(:validation_error) do + [ + Dragnet::Errors::ValidationError, + 'Validation has failed' + ] + end + + before do + allow(repo_validator).to receive(:validate).and_raise(*validation_error) + end + + it 'raises a Dragnet::Errors::ValidationError' do + expect { method_call }.to raise_error(*validation_error) + end + end + end +end diff --git a/spec/dragnet/repository_spec.rb b/spec/dragnet/repository_spec.rb new file mode 100644 index 0000000..d78550d --- /dev/null +++ b/spec/dragnet/repository_spec.rb @@ -0,0 +1,210 @@ +# frozen_string_literal: true + +require 'dragnet/repository' + +RSpec.describe Dragnet::Repository do + subject(:repository) { described_class.new(path: path) } + + let(:path) { '/Workspace/project/source' } + + let(:branches) { [] } + + let(:git) do + instance_double( + Git::Base, + branches: branches + ) + end + + before do + allow(Git).to receive(:open).with(path).and_return(git) + end + + describe 'contract' do + let(:multi_repository) { Dragnet::MultiRepository.new(path: path) } + + it 'responds to the same methods as Dragnet::MultiRepository' do + expect(multi_repository.methods).to all( + satisfy { |method| repository.respond_to?(method) } + ) + end + end + + it 'delegates #branch to the git object' do + expect(repository.git).to receive(:branch) + repository.branch + end + + it 'delegates #branches to the git object' do + expect(repository.git).to receive(:branches) + repository.branches + end + + it 'delegates #diff to the git object' do + expect(repository.git).to receive(:diff) + repository.diff + end + + describe '#initialize' do + subject(:method_call) { repository } + + context 'when the given path cannot be opened as a git repository' do + let(:expected_message) { "path does not exist\nfrom #{path}" } + + before do + allow(Git).to receive(:open).with(path).and_raise( + ArgumentError, expected_message + ) + end + + it 'raises an ArgumentError' do + expect { method_call }.to raise_error(ArgumentError, expected_message) + end + end + end + + describe '#head' do + subject(:method_call) { repository.head } + + let(:head) do + instance_double( + Git::Object::Commit + ) + end + + before do + allow(git).to receive(:object).with('HEAD').and_return(head) + end + + it 'returns the commit at the head of the repository' do + expect(method_call).to eq(head) + end + end + + describe '#remote_uri_path' do + subject(:method_call) { repository.remote_uri_path } + + let(:remote) do + instance_double( + Git::Remote, + url: 'ssh://focal.fossa@gerrit.int.esrlabs.com:29418/projects/central/bsw' + ) + end + + let(:remotes) do + [ + remote, + instance_double( + Git::Remote + ) + ] + end + + before do + allow(git).to receive(:remotes).and_return(remotes) + end + + it 'fetches the URL from the first remote' do + expect(remotes).to receive(:first).and_call_original + method_call + end + + it "returns only the path of the remote's URL" do + expect(method_call).to eq('/projects/central/bsw') + end + end + + describe '#multi?' do + subject(:method_call) { repository.multi? } + + it 'returns false' do + expect(method_call).to eq(false) + end + end + + describe '#repositories' do + subject(:method_call) { repository.repositories } + + let(:message) do + "Failed to perform the action 'repositories' on '#{path}'."\ + ' The path was not set-up as a multi-repo path. If you are running'\ + ' without the --multi-repo command line switch make sure that none of'\ + " your MTRs have a 'repos' attribute or run with the --multi-repo switch" + end + + it 'raises a Dragnet::Errors::IncompatibleRepositoryError' do + expect { method_call }.to raise_error( + Dragnet::Errors::IncompatibleRepositoryError, + message + ) + end + end + + shared_examples_for '#branches_with' do + context 'when there are no branches' do + it 'returns an empty array' do + expect(method_call).to be_an(Array).and be_empty + end + end + + context 'when no branch contains the given commit' do + let(:branches) do + [ + instance_double(Git::Branch, contains?: false), + instance_double(Git::Branch, contains?: false), + instance_double(Git::Branch, contains?: false) + ] + end + + it 'returns an empty array' do + expect(method_call).to be_an(Array).and be_empty + end + end + + context 'when some of the branches contain the given commit' do + let(:containing_branches) do + [ + instance_double(Git::Branch, contains?: true), + instance_double(Git::Branch, contains?: true) + ] + end + + let(:branches) do + containing_branches + [ + instance_double(Git::Branch, contains?: false) + ] + end + + it 'returns the expected array of branches' do + expect(method_call).to eq(containing_branches) + end + end + end + + describe '#branches_with' do + subject(:method_call) { repository.branches_with(commit) } + + let(:commit) { '13002236e4' } + + it_behaves_like '#branches_with' + end + + describe '#branches_with_head' do + subject(:method_call) { repository.branches_with_head } + + let(:head_sha1) { '6d71da084791ddadc54f4acb25b739c9b240a552' } + + let(:head) do + instance_double( + Git::Object::Commit, + sha: head_sha1 + ) + end + + before do + allow(git).to receive(:object).with('HEAD').and_return(head) + end + + it_behaves_like '#branches_with' + end +end diff --git a/spec/dragnet/test_record_spec.rb b/spec/dragnet/test_record_spec.rb new file mode 100644 index 0000000..1608b67 --- /dev/null +++ b/spec/dragnet/test_record_spec.rb @@ -0,0 +1,275 @@ +# frozen_string_literal: true + +require 'dragnet/test_record' + +RSpec.describe Dragnet::TestRecord do + subject(:test_record) { described_class.new(args) } + + let(:sha1) { '6c25d4c4e0183136b558ce8cbc67b0f9463c3ad1' } + let(:id) { 'ESR_REQ_5435' } + let(:result) { 'passed' } + let(:files) { 'source/tests/manual/safeio.yaml' } + + let(:review_status) { 'reviewed' } + let(:findings) { 'no findings' } + + let(:args) do + { + sha1: sha1, + id: id, + result: result, + files: files, + review_status: review_status, + findings: findings + } + end + + describe '#initialize' do + subject(:method_call) { test_record } + + let(:review_status) { 'notReviewed' } + let(:review_comments) { '2021-06-21 Bobillier, S. No findings' } + + context 'with review_status' do + let(:args) { { review_status: review_status } } + + it 'accepts the given review status' do + expect(method_call.review_status).to eq(review_status) + end + end + + context 'with reviewstatus' do + let(:args) { { reviewstatus: review_status } } + + it 'accepts the given review status' do + expect(method_call.review_status).to eq(review_status) + end + end + + context 'with review_status and reviewstatus' do + let(:args) do + { review_status: review_status, reviewstatus: 'something else'} + end + + it 'takes review_status and not reviewstatus' do + expect(method_call.review_status).to eq(review_status) + end + end + + context 'with review_comments' do + let(:args) { { review_comments: review_comments } } + + it 'accepts the given review comments' do + expect(method_call.review_comments).to eq(review_comments) + end + end + + context 'with reviewcomments' do + let(:args) { { reviewcomments: review_comments } } + + it 'accepts the given review comments' do + expect(method_call.review_comments).to eq(review_comments) + end + end + + context 'with review_comments and reviewcomments' do + let(:args) do + { review_comments: review_comments, reviewcomments: '-'} + end + + it 'takes review_comments and not reviewcomments' do + expect(method_call.review_comments).to eq(review_comments) + end + end + + describe 'Meta-data', requirements: %w[DRAGNET_0068] do + shared_examples_for 'a meta-data attribute' do + # Required variables: + # :attribute_value: The value attribute being tested + # :arg_key: The key used to set the value of the attribute in the +args+ hash. + + context 'when the argument is not present' do + it 'leaves the attribute as nil' do + expect(attribute_value).to be_nil + end + end + + context 'when nil is given as argument' do + before { args[arg_key] = nil } + + it 'sets the attribute to nil' do + expect(attribute_value).to be_nil + end + end + + context 'when a String is given as argument' do + before { args[arg_key] = 'Single String' } + + it 'sets the attribute to the given value' do + expect(attribute_value).to eq('Single String') + end + end + + context 'when an Array of Strings is given as argument' do + before { args[arg_key] = %w[Array of Strings] } + + it 'sets the attribute to the given value' do + expect(attribute_value).to eq(%w[Array of Strings]) + end + end + end + + describe 'name' do + subject(:attribute_value) { test_record.name } + + let(:arg_key) { :name } + + it_behaves_like 'a meta-data attribute' + end + + describe 'test_method' do + subject(:attribute_value) { test_record.test_method } + + let(:arg_key) { :test_method } + + it_behaves_like 'a meta-data attribute' + end + + describe 'tc_derivation_method' do + subject(:attribute_value) { test_record.tc_derivation_method } + + let(:arg_key) { :tc_derivation_method } + + it_behaves_like 'a meta-data attribute' + end + end + end + + describe '#validate' do + subject(:method_call) { test_record.validate } + + let(:test_record_validator) do + instance_double( + Dragnet::Validators::Entities::TestRecordValidator, + validate: true + ) + end + + before do + allow(Dragnet::Validators::Entities::TestRecordValidator).to receive(:new) + .and_return(test_record_validator) + end + + it 'Creates a TestRecordValidator object and calls validate on it' do + expect(Dragnet::Validators::Entities::TestRecordValidator) + .to receive(:new).with(test_record) + + expect(test_record_validator).to receive(:validate) + method_call + end + + context 'when the validation fails' do + let(:exception) { Dragnet::Errors::ValidationError } + let(:message) { 'missing key id' } + + before do + allow(test_record_validator).to receive(:validate) + .and_raise(exception, message) + end + + it 'raises the ValidationError' do + expect { method_call }.to raise_error(exception, message) + end + end + end + + describe '#passed' do + subject(:method_call) { test_record.passed? } + + context 'when the result is passed' do + it 'returns true' do + expect(method_call).to eq(true) + end + end + + context 'when the result is something else' do + let(:result) { 'something' } + + it 'returns false' do + expect(method_call).to eq(false) + end + end + end + + describe '#reviewed?' do + subject(:method_call) { test_record.reviewed? } + + context "when the review_status is 'reviewed'" do + it 'returns true' do + expect(method_call).to eq(true) + end + end + + context 'when the review_status is something else' do + let(:review_status) { 'review in progress' } + + it 'returns false' do + expect(method_call).to eq(false) + end + end + end + + describe '#findings?' do + subject(:method_call) { test_record.findings? } + + context "when 'findings' is nil" do + let(:findings) { nil } + + it 'returns false' do + expect(method_call).to eq(false) + end + end + + context "when 'findings' is en empty string" do + let(:findings) { '' } + + it 'returns false' do + expect(method_call).to eq(false) + end + end + + context "when 'findings' has only spaces" do + let(:findings) { ' ' } + + it 'returns false' do + expect(method_call).to eq(false) + end + end + + context "when 'findings' is equal to 'no findings'" do + context "when 'no findings' is lowercase" do + let(:findings) { 'no findings' } + + it 'returns false' do + expect(method_call).to eq(false) + end + end + + context "when 'no findings' has different capitalization" do + let(:findings) { 'No Findings' } + + it 'returns false' do + expect(method_call).to eq(false) + end + end + end + + context "when 'findings' is something else" do + let(:findings) { 'Possible instability detected when testing output signal' } + + it 'returns true' do + expect(method_call).to eq(true) + end + end + end +end diff --git a/spec/dragnet/validator_spec.rb b/spec/dragnet/validator_spec.rb new file mode 100644 index 0000000..c4cbd6e --- /dev/null +++ b/spec/dragnet/validator_spec.rb @@ -0,0 +1,340 @@ +# frozen_string_literal: true + +require 'dragnet/cli/logger' +require 'dragnet/validator' + +RSpec.shared_examples 'Dragnet::Validator#validate logs the error' do + it 'logs the error' do + expect(logger).to receive(:error).with( + Regexp.new(Regexp.escape(log_message)) + ) + + method_call + end +end + +RSpec.shared_examples 'Dragnet::Validator#validate adds the file data to the errors array' do + it 'adds the file data to the errors array' do + method_call + + expect(validator.errors).to include( + file: file, message: error_message, exception: exception + ) + end +end + +RSpec.describe Dragnet::Validator do + subject(:validator) do + described_class.new(files: files, path: path, logger: logger) + end + + let(:files) do + %w[ + /Workspace/source/test/manual/ESR_REQ_6897.yaml + /Workspace/source/test/manual/ESR_REQ_9813.yaml + /Workspace/source/test/manual/ESR_REQ_1175.yaml + ] + end + + let(:path) { '/Workspace/source' } + + let(:logger) do + instance_double( + Dragnet::CLI::Logger, + info: true, + error: true + ) + end + + let(:yaml) do + <<~YAML + id: ESR_REQ_6897 + result: passed + YAML + end + + let(:test_record) do + instance_double( + Dragnet::TestRecord + ) + end + + let(:data_validator) do + instance_double( + Dragnet::Validators::DataValidator, + validate: test_record + ) + end + + let(:files_validator) do + instance_double( + Dragnet::Validators::FilesValidator, + validate: true + ) + end + + let(:repos_validator) do + instance_double( + Dragnet::Validators::ReposValidator, + validate: true + ) + end + + before do + allow(File).to receive(:read).and_call_original + allow(File).to receive(:read).with(%r{test/manual/}).and_return(yaml) + allow(YAML).to receive(:safe_load).and_call_original + + allow(Dragnet::Validators::DataValidator).to receive(:new).and_return(data_validator) + allow(Dragnet::Validators::FilesValidator).to receive(:new).and_return(files_validator) + allow(Dragnet::Validators::ReposValidator).to receive(:new).and_return(repos_validator) + end + + describe '#validate' do + subject(:method_call) { validator.validate } + + context 'when no files are given' do + let(:files) { [] } + + it 'returns an empty array' do + expect(method_call).to eq([]) + end + end + + it 'Logs the files as they are checked', requirements: %w[DRAGNET_0027] do + files.each do |file| + expect(logger).to receive(:info).with("Validating #{file}...") + end + + method_call + end + + context 'when one of the given files cannot be read' do + let(:file) { '/Workspace/source/test/manual/ESR_REQ_6897.yaml' } + + let(:message) { 'Access denied' } + let(:exception) { Errno::EACCES.new(message) } + let(:error_message) { 'IO Error: Cannot read the specified file' } + let(:log_message) { "#{file} Failed: #{error_message} - Permission denied - #{message}" } + + before do + allow(File).to receive(:read) + .with(file).and_raise(exception) + end + + include_examples 'Dragnet::Validator#validate logs the error' + include_examples 'Dragnet::Validator#validate adds the file data to the errors array' + end + + context 'when one of the files is not a valid YAML file', requirements: ['DRAGNET_0003'] do + let(:file) { '/Workspace/source/test/manual/ESR_REQ_9813.yaml' } + + let(:malformed_yaml) do + <<~YAML + id: ESR_REQ_9813 + files: + - main/module1/entry.cpp + YAML + end + + let(:line) { 2 } + let(:column) { 8 } + let(:problem) { 'mapping values are not allowed in this context' } + + let(:exception) do + Psych::SyntaxError.new(file, line, column, nil, problem, nil) + end + + let(:exception_message) { "(#{file}): #{problem} at line #{line} column #{column}" } + let(:error_message) { 'YAML Parsing Error' } + + let(:log_message) do + "#{file} Failed: #{error_message} - #{exception_message}" + end + + before do + allow(File).to receive(:read).with(file).and_return(malformed_yaml) + allow(YAML).to receive(:safe_load).with(malformed_yaml).and_raise(exception) + end + + include_examples 'Dragnet::Validator#validate logs the error' + include_examples 'Dragnet::Validator#validate adds the file data to the errors array' + end + + context 'when there is a format error' do + let(:file) { '/Workspace/source/test/manual/ESR_REQ_1175.yaml' } + + let(:other_yaml) do + <<~YAML + id: ESR_REQ_1175 + result: passed + sha1: -1 + YAML + end + + let(:exception_message) { 'Invalid value for key sha1' } + let(:exception) { Dragnet::Errors::YAMLFormatError.new(exception_message) } + let(:error_message) { 'YAML Formatting Error' } + let(:log_message) { "#{file} Failed: #{error_message} - #{exception_message}" } + + let(:data) do + { + id: 'ESR_REQ_1175', + result: 'passed', + sha1: -1 + } + end + + before do + allow(File).to receive(:read).with(file).and_return(other_yaml) + allow(YAML).to receive(:safe_load).with(other_yaml).and_return(data) + allow(data_validator).to receive(:validate).and_raise(exception) + end + + include_examples 'Dragnet::Validator#validate logs the error' + include_examples 'Dragnet::Validator#validate adds the file data to the errors array' + end + + context 'when one of the referenced files is not found' do + let(:file) { '/Workspace/source/test/manual/ESR_REQ_6897.yaml' } + + let(:other_yaml) do + <<~YAML + id: ESR_REQ_6897 + result: passed + sha1: 364c2cea75d9328a446a515814c36464d8f62052 + files: + - main/module1/security.cpp + - main/module1/assertions.cpp + YAML + end + + let(:exception_message) do + 'Could not find any files matching main/module1/assertions.cpp in /Workspace/source' + end + + let(:exception) { Dragnet::Errors::FileNotFoundError.new(exception_message) } + let(:error_message) { 'Referenced file not found in repository' } + let(:log_message) { "#{file} Failed: #{error_message} - #{exception_message}" } + + let(:data) do + { + id: 'ESR_REQ_6897', + result: 'passed', + sha1: '364c2cea75d9328a446a515814c36464d8f62052', + files: %w[ + main/module1/security.cpp + main/module1/assertions.c + ] + } + end + + before do + allow(File).to receive(:read).with(file).and_return(other_yaml) + allow(YAML).to receive(:safe_load).with(other_yaml).and_return(data) + allow(files_validator).to receive(:validate).and_raise(exception) + end + + include_examples 'Dragnet::Validator#validate logs the error' + include_examples 'Dragnet::Validator#validate adds the file data to the errors array' + end + + context 'when one of the MTRs has repos' do + let(:file) { '/Workspace/source/test/manual/ESR_REQ_1175.yaml' } + + let(:other_yaml) do + <<~YAML + id: ESR_REQ_1175 + result: passed + repos: + - + sha1: eb8b4f9cd67c90b527962a51a488c0f80f9ea599 + path: path/to/the/repo + files: + - lib/security/crypto/rsa*.cpp + - lib/security/crypto/rsa*.h + YAML + end + + let(:data) do + { + id: 'ESR_REQ_1175', + result: 'passed', + repos: [ + { + sha1: 'eb8b4f9cd67c90b527962a51a488c0f80f9ea599', + path: 'path/to/the/repo', + files: %w[ + lib/security/crypto/rsa*.cpp + lib/security/crypto/rsa*.h + ] + } + ] + } + end + + before do + allow(File).to receive(:read).with(file).and_return(other_yaml) + allow(YAML).to receive(:safe_load).with(other_yaml).and_return(data) + end + + it 'creates an instance of the ReposValidator' do + expect(Dragnet::Validators::ReposValidator).to receive(:new).with(test_record, path) + method_call + end + + it 'calls validate on the ReposValidator' do + expect(repos_validator).to receive(:validate) + method_call + end + + it 'does not raise any errors' do + expect { method_call }.not_to raise_error + end + + context "when one of the Repos' path doesn't exist", requirements: %w[DRAGNET_0058] do + let(:exception_message) do + 'Cannot find the repository path path/to/the/repo inside /Workspace/source' + end + + let(:exception) { Dragnet::Errors::RepoPathNotFoundError.new(exception_message) } + let(:error_message) { 'Referenced repository not found' } + let(:log_message) { "#{file} Failed: #{error_message} - #{exception_message}" } + + before do + allow(repos_validator).to receive(:validate).and_raise(exception) + end + + it 'does not raise any errors' do + expect { method_call }.not_to raise_error + end + + include_examples 'Dragnet::Validator#validate logs the error' + include_examples 'Dragnet::Validator#validate adds the file data to the errors array' + end + + context "when one or more of the files listed in the Repo doesn't exist", + requirements: %w[DRAGNET_0047 DRAGNET_0048] do + + let(:exception_message) do + 'Could not find any files matching lib/security/crypto/rsa*.h in path/to/the/repo' + end + + let(:exception) { Dragnet::Errors::FileNotFoundError.new(exception_message) } + let(:error_message) { 'Referenced file not found in repository' } + let(:log_message) { "#{file} Failed: #{error_message} - #{exception_message}" } + + before do + allow(repos_validator).to receive(:validate).and_raise(exception) + end + + it 'does not raise any errors' do + expect { method_call }.not_to raise_error + end + + include_examples 'Dragnet::Validator#validate logs the error' + include_examples 'Dragnet::Validator#validate adds the file data to the errors array' + end + end + end +end diff --git a/spec/dragnet/validators/data_validator_spec.rb b/spec/dragnet/validators/data_validator_spec.rb new file mode 100644 index 0000000..b0225bb --- /dev/null +++ b/spec/dragnet/validators/data_validator_spec.rb @@ -0,0 +1,115 @@ +# frozen_string_literal: true + +require 'dragnet/validators/data_validator' + +RSpec.shared_examples 'Dragnet::Validators::DataValidator#validate raises a Dragnet::Errors::YAMLFormatError' do + it 'raises a Dragnet::Errors::YAMLFormatError' do + expect { method_call } + .to raise_error(Dragnet::Errors::YAMLFormatError, expected_message) + end +end + +RSpec.describe Dragnet::Validators::DataValidator do + subject(:data_validator) { described_class.new(data, source_file) } + + let(:sha1) { 'e65af096e3104190e004fe0dc2f9b4cb29ea553e' } + let(:id) { 'ESR_REQ_5723' } + let(:result) { 'Passed' } + + let(:description) do + <<~TEXT + Makes sure that that pin 34 of the device is high whenever the watchdog + triggers a reset and that it stays high for at least 2.34 seconds after + the reset happens. + TEXT + end + + let(:data) do + { + 'sha1' => sha1, + 'id' => id, + 'result' => result, + 'description' => description + } + end + + let(:transformed_data) do + { + sha1: sha1, + id: id, + result: result, + description: description.chomp + } + end + + let(:source_file) { '/Workspace/project/source/module/source_file.cpp' } + + let(:test_record) do + instance_double( + Dragnet::TestRecord, + 'source_file=': true, + validate: true + ) + end + + before do + allow(Dragnet::TestRecord).to receive(:new).and_return(test_record) + end + + describe '#validate' do + subject(:method_call) { data_validator.validate } + + context 'when the data is not a hash', requirements: %w[DRAGNET_0006 DRAGNET_0007 DRAGNET_0008] do + let(:data) { 'The quick brown fox...' } + + let(:expected_message) do + 'Incompatible data structure. Expecting a Hash, got a String' + end + + include_examples 'Dragnet::Validators::DataValidator#validate raises a Dragnet::Errors::YAMLFormatError' + end + + it "symbolizes the data's keys" do + expect { method_call }.to change(data, :keys) + .from(%w[sha1 id result description]).to(transformed_data.keys) + end + + it 'removes newlines at the end of the strings' do + expect { method_call }.to change { data[:description] }.to(transformed_data[:description]) + end + + it 'creates the Test Record with the expected data' do + expect(Dragnet::TestRecord).to receive(:new).with(transformed_data) + method_call + end + + it 'assigns the source file to the newly created Test Record' do + expect(test_record).to receive(:source_file=).with(source_file) + method_call + end + + it 'validates the newly created Test Record' do + expect(test_record).to receive(:validate) + method_call + end + + context 'when the Test Record validation fails' do + let(:expected_message) do + 'Incompatible type for key sha1: Expected String got Integer instead' + end + + before do + allow(test_record).to receive(:validate).and_raise( + Dragnet::Errors::ValidationError, + expected_message + ) + end + + include_examples 'Dragnet::Validators::DataValidator#validate raises a Dragnet::Errors::YAMLFormatError' + end + + it 'returns the newly created Test Record' do + expect(method_call).to eq(test_record) + end + end +end diff --git a/spec/dragnet/validators/entities/repo_validator_spec.rb b/spec/dragnet/validators/entities/repo_validator_spec.rb new file mode 100644 index 0000000..05b087f --- /dev/null +++ b/spec/dragnet/validators/entities/repo_validator_spec.rb @@ -0,0 +1,119 @@ +# frozen_string_literal: true + +require 'dragnet/validators/entities/repo_validator' +require 'dragnet/repo' + +RSpec.describe Dragnet::Validators::Entities::RepoValidator do + subject(:repo_validator) { described_class.new(repo) } + + let(:sha1) { 'de97dcc0dbd57bed7e4a6565ed854197c406a343' } + let(:path) { 'esrlabs/bsw/crypto' } + let(:files) { nil } + + let(:repo) do + instance_double( + Dragnet::Repo, + files: files, + 'files=': true, + path: path, + sha1: sha1 + ) + end + + describe '#validate' do + subject(:method_call) { repo_validator.validate } + + let(:sha1_validator) do + instance_double(Dragnet::Validators::Fields::SHA1Validator, validate: true) + end + + let(:path_validator) do + instance_double(Dragnet::Validators::Fields::PathValidator, validate: true) + end + + let(:processed_files) { nil } + + let(:files_validator) do + instance_double(Dragnet::Validators::Fields::FilesValidator, validate: processed_files) + end + + before do + allow(Dragnet::Validators::Fields::SHA1Validator) + .to receive(:new).and_return(sha1_validator) + + allow(Dragnet::Validators::Fields::PathValidator) + .to receive(:new).and_return(path_validator) + + allow(Dragnet::Validators::Fields::FilesValidator) + .to receive(:new).and_return(files_validator) + end + + shared_context 'when an individual validator fails' do + before do + allow(validator).to receive(:validate).and_raise( + validation_error, message + ) + end + + it 'raises the expected error' do + expect { method_call }.to raise_error(validation_error, message) + end + end + + it 'uses the SHA1Validator class to validate the `sha1` attribute', requirements: ['DRAGNET_0043'] do + expect(sha1_validator).to receive(:validate).with('repos[sha1]', sha1) + method_call + end + + context 'when the SHA1Validator fails', requirements: ['DRAGNET_0046'] do + let(:validator) { sha1_validator } + let(:validation_error) { Dragnet::Errors::ValidationError } + let(:message) { 'Missing required key: repos[sha1]' } + + include_context 'when an individual validator fails' + end + + it 'uses the PathValidator class to validate the `path` attribute', requirements: ['DRAGNET_0039'] do + expect(path_validator).to receive(:validate).with('repos[path]', path) + method_call + end + + context 'when the PathValidator fails', requirements: ['DRAGNET_0042'] do + let(:validator) { path_validator } + let(:validation_error) { Dragnet::Errors::ValidationError } + + let(:message) do + 'Incompatible type for key repos[path]: Expected String got Float instead' + end + + include_context 'when an individual validator fails' + end + + context 'when the Repo has files', requirements: ['DRAGNET_0041'] do + let(:files) { 'utils/b2f/password.c' } + let(:processed_files) { ['utils/b2f/password.c'] } + + it 'uses the FilesValidator class to validate the `files` attribute' do + expect(files_validator).to receive(:validate).with('repos[files]', files) + method_call + end + + context 'when the FilesValidator fails' do + let(:validator) { files_validator } + let(:validation_error) { Dragnet::Errors::ValidationError } + + let(:message) do + 'Incompatible type for key repos[files]: Expected a Array. '\ + 'Found a(n) Hash inside the array' + end + + include_context 'when an individual validator fails' + end + + it 'overwrites the `files` attribute with the files array returned by the validator' do + expect(repo).to receive(:'files=').with(processed_files) + method_call + end + end + end +end diff --git a/spec/dragnet/validators/entities/test_record_validator_spec.rb b/spec/dragnet/validators/entities/test_record_validator_spec.rb new file mode 100644 index 0000000..d299854 --- /dev/null +++ b/spec/dragnet/validators/entities/test_record_validator_spec.rb @@ -0,0 +1,353 @@ +# frozen_string_literal: true + +require 'dragnet/validators/entities/test_record_validator' + +RSpec.describe Dragnet::Validators::Entities::TestRecordValidator do + subject(:test_record_validator) do + described_class.new(test_record) + end + + let(:sha1) { '6c25d4c4e0183136b558ce8cbc67b0f9463c3ad1' } + let(:id) { 'ESR_REQ_5435' } + let(:description) { 'Check the functionality of the SafeIO feature' } + let(:name) { nil } + let(:test_method) { nil } + let(:tc_derivation_method) { nil } + let(:result) { 'passed' } + let(:files) { 'source/tests/manual/safeio.yaml' } + let(:repos) { nil } + + let(:test_record) do + instance_double( + Dragnet::TestRecord, + sha1: sha1, + id: id, + description: description, + name: name, + 'name=': true, + test_method: test_method, + 'test_method=': true, + tc_derivation_method: tc_derivation_method, + 'tc_derivation_method=': true, + result: result, + files: files, + 'files=': true, + repos: repos, + 'repos=': true, + 'result=': true + ) + end + + describe '#validate' do + subject(:method_call) { test_record_validator.validate } + + let(:sha1_validator) do + instance_double( + Dragnet::Validators::Fields::SHA1Validator, + validate: true + ) + end + + let(:id_validator) do + instance_double( + Dragnet::Validators::Fields::IDValidator, + validate: true + ) + end + + let(:validated_files) { ['source/tests/manual/safeio.yaml'] } + + let(:files_validator) do + instance_double( + Dragnet::Validators::Fields::FilesValidator, + validate: validated_files + ) + end + + let(:validated_repos) { nil } + + let(:repos_validator) do + instance_double( + Dragnet::Validators::Fields::ReposValidator, + validate: validated_repos + ) + end + + let(:validated_result) { 'failed' } + + let(:result_validator) do + instance_double( + Dragnet::Validators::Fields::ResultValidator, + validate: validated_result + ) + end + + let(:description_validator) do + instance_double( + Dragnet::Validators::Fields::DescriptionValidator, + validate: true + ) + end + + let(:meta_data_field_validator) do + instance_double( + Dragnet::Validators::Fields::MetaDataFieldValidator, + validate: true + ) + end + + before do + allow(Dragnet::Validators::Fields::SHA1Validator).to receive(:new).and_return(sha1_validator) + allow(Dragnet::Validators::Fields::IDValidator).to receive(:new).and_return(id_validator) + allow(Dragnet::Validators::Fields::FilesValidator).to receive(:new).and_return(files_validator) + allow(Dragnet::Validators::Fields::ReposValidator).to receive(:new).and_return(repos_validator) + allow(Dragnet::Validators::Fields::ResultValidator).to receive(:new).and_return(result_validator) + allow(Dragnet::Validators::Fields::DescriptionValidator).to receive(:new).and_return(description_validator) + allow(Dragnet::Validators::Fields::MetaDataFieldValidator).to receive(:new).and_return(meta_data_field_validator) + end + + shared_context 'when an individual validator fails' do + before do + allow(validator).to receive(:validate).and_raise(exception, message) + end + + it 'Raises the validation error' do + expect { method_call }.to raise_error(exception, message) + end + end + + context 'when the MTR has neither a `files` nor a `repos` attribute' do + let(:files) { nil } + + it 'passes the validation', requirements: %w[DRAGNET_0055 DRAGNET_0056] do + expect { method_call }.not_to raise_error + end + end + + context 'when the MTR has a `files` attribute but no `repos` attribute' do + it 'passes the validation', requirements: %w[DRAGNET_0004] do + expect { method_call }.not_to raise_error + end + end + + context 'when the MTR has a `repos` attribute but no `files` attribute' do + it 'passes the validation', requirements: %w[DRAGNET_0035] do + expect { method_call }.not_to raise_error + end + end + + context 'when the MTR has a `files` and a `repos` attribute' do + let(:repos) do + [ + { some: 'repo' }, + { another: 'repo' } + ] + end + + it 'fails the validation', requirements: %w[DRAGNET_0036] do + expect { method_call }.to raise_error( + Dragnet::Errors::ValidationError, + "Invalid MTR: ESR_REQ_5435. Either 'files' or 'repos' should be provided, not both" + ) + end + end + + context 'when the MTR has a SHA1 but not a list of repositories' do + it 'uses the SHA1 Validator to validate', requirements: ['DRAGNET_0006'] do + expect(sha1_validator).to receive(:validate).with('sha1', sha1) + method_call + end + + context 'when the SHA1 validation fails', requirements: ['DRAGNET_0006'] do + let(:exception) { Dragnet::Errors::ValidationError } + let(:message) { 'missing key sha1' } + let(:validator) { sha1_validator } + + include_context 'when an individual validator fails' + end + end + + context 'when the Description validation fails' do + let(:exception) { Dragnet::Errors::ValidationError } + let(:message) { 'Incompatible type for key description: Expected String got Array instead' } + let(:validator) { description_validator } + + include_context 'when an individual validator fails' + end + + context 'when the MTR has both a SHA1 and a list of repositories' do + let(:files) { nil } + let(:repos) { [{ a: 'repo' }, { b: 'repo' }, { c: 'repo' }] } + + it 'raises a Dragnet::Errors::ValidationError', requirements: %w[DRAGNET_0057] do + expect { method_call }.to raise_error( + Dragnet::Errors::ValidationError, + "Invalid MTR: ESR_REQ_5435. Either 'repos' or 'sha1' should be provided, not both" + ) + end + end + + it 'uses the ID Validator to validate' do + expect(id_validator).to receive(:validate).with('id', id) + method_call + end + + it 'uses the Description Validator to validate' do + expect(description_validator).to receive(:validate).with('description', description) + method_call + end + + context 'when the ID validation fails' do + let(:exception) { Dragnet::Errors::ValidationError } + let(:message) { 'missing key id' } + let(:validator) { id_validator } + + include_context 'when an individual validator fails' + end + + it 'uses the Files Validator to validate' do + expect(files_validator).to receive(:validate).with('files', files) + method_call + end + + it "updates the files field with the Files Validator's return value" do + expect(test_record).to receive(:files=).with(validated_files) + method_call + end + + context 'when the Files validation fails' do + let(:exception) { Dragnet::Errors::ValidationError } + let(:message) { 'unsupported type Integer' } + let(:validator) { files_validator } + + include_context 'when an individual validator fails' + end + + context 'when the MTR has a list of repositories' do + let(:files) { nil } # Cannot have files and repos at the same time + let(:sha1) { nil } # Cannot have repos and sha1 at the same time + + let(:repos) do + [ + { path: 'esrlabs/crypto', sha1: '19544d4ecd6f577c0742a01f71e139ab75935ea9', files: 'utilities/b2f/*.cpp' }, + { path: 'esrlabs/bsw/safeRng', sha1: '75430dc90b1e82ef8a688c7bf036eb48f6941b8a', files: '**/**/*.cpp'} + ] + end + + let(:validated_repos) do + [instance_double(Dragnet::Repo), instance_double(Dragnet::Repo)] + end + + it 'does not validate the SHA1 attribute', requirements: ['DRAGNET_0057'] do + expect(Dragnet::Validators::Fields::SHA1Validator).not_to receive(:new) + expect(sha1_validator).not_to receive(:validate) + method_call + end + + it 'uses the ReposValidator to validate the repos', requirements: ['DRAGNET_0037'] do + expect(repos_validator).to receive(:validate).with('repos', repos) + method_call + end + + context 'when the ReposValidator validation fails' do + let(:validator) { repos_validator } + let(:exception) { Dragnet::Errors::ValidationError } + + let(:message) do + 'Incompatible type for key repos: Expected Array, Hash got String instead' + end + + include_context 'when an individual validator fails' + end + + it 'overwrites the `repos` attribute with the array of repos returned by the validator' do + expect(test_record).to receive(:'repos=').with(validated_repos) + method_call + end + end + + it 'uses the Result Validator to validate' do + expect(result_validator).to receive(:validate).with('result', result) + method_call + end + + it "updates the result field with the Result Validator's return value" do + expect(test_record).to receive(:result=).with(validated_result) + method_call + end + + context 'when the Result validation fails' do + let(:exception) { Dragnet::Errors::ValidationError } + let(:message) { 'unknown result missed' } + let(:validator) { result_validator } + + include_context 'when an individual validator fails' + end + + describe 'meta-data validation', requirements: %w[DRAGNET_0068] do + let(:name) { 'Bruce Willis' } + let(:test_method) { 'Nuclear explosion' } + let(:tc_derivation_method) { 'BVA' } + + before do + allow(meta_data_field_validator).to receive(:validate) + .with('name', 'Bruce Willis').and_return(['Bruce Willis']) + + allow(meta_data_field_validator).to receive(:validate) + .with('test_method', 'Nuclear explosion').and_return(['Nuclear explosion']) + + allow(meta_data_field_validator).to receive(:validate) + .with('tc_derivation_method', 'BVA').and_return(['BVA']) + end + + it "validates the 'name' attribute" do + expect(meta_data_field_validator).to receive(:validate).with('name', 'Bruce Willis') + method_call + end + + it "assigns the value returned by the validator to the 'name' attribute" do + expect(test_record).to receive(:name=).with(['Bruce Willis']) + method_call + end + + it "validates the 'test_method' attribute" do + expect(meta_data_field_validator).to receive(:validate).with('test_method', 'Nuclear explosion') + method_call + end + + it "assigns the value returned by the validator to the 'test_method' attribute" do + expect(test_record).to receive(:test_method=).with(['Nuclear explosion']) + method_call + end + + it "validates the 'tc_derivation_method' attribute" do + expect(meta_data_field_validator).to receive(:validate).with('tc_derivation_method', 'BVA') + method_call + end + + it "assigns the value returned by the validator to the 'tc_derivation_method' attribute" do + expect(test_record).to receive(:tc_derivation_method=).with(['BVA']) + method_call + end + + context 'when the meta-data validation fails' do + let(:test_method) { 1994 } + + let(:expected_error) do + [ + Dragnet::Errors::ValidationError, + 'Incompatible type for key test_method: Expected a String, Array got Integer instead' + ] + end + + before do + allow(meta_data_field_validator).to receive(:validate).and_raise(*expected_error) + end + + it 'raises the validation error' do + expect { method_call }.to raise_error(*expected_error) + end + end + end + end +end diff --git a/spec/dragnet/validators/fields/description_validator_spec.rb b/spec/dragnet/validators/fields/description_validator_spec.rb new file mode 100644 index 0000000..584c6a9 --- /dev/null +++ b/spec/dragnet/validators/fields/description_validator_spec.rb @@ -0,0 +1,78 @@ +# frozen_string_literal: true + +require 'dragnet/validators/fields/description_validator' + +RSpec.describe Dragnet::Validators::Fields::DescriptionValidator do + subject(:description_validator) { described_class.new } + + describe '#validate' do + subject(:method_call) { description_validator.validate(key, value) } + + let(:key) { 'description' } + + context 'when the value is nil' do + let(:value) { nil } + + it 'does not raise any errors' do + expect { method_call }.not_to raise_error + end + end + + context 'when the values is a string' do + let(:value) { 'Subway tile woke 3 wolf moon occupy bicycle rights, anim ennui unicorn gluten-free roof party.' } + + it 'does not raise any errors' do + expect { method_call }.not_to raise_error + end + end + + shared_examples_for '#validate with an invalid type' do + it 'raises the expected error' do + expect { method_call }.to raise_error( + Dragnet::Errors::ValidationError, + "Incompatible type for key description: Expected String got #{type} instead" + ) + end + end + + context 'when the value is an Array' do + let(:value) do + [ + 'Dreamcatcher nisi reprehenderit edison bulb, dolore in direct trade do dolore.', + 'Minim photo booth stumptown, kogi cardigan banjo post-ironic try-hard migas biodiesel.' + ] + end + + let(:type) { 'Array' } + + it_behaves_like '#validate with an invalid type' + end + + context 'when the value is a Hash' do + let(:value) do + { + 'Text 1' => 'Test fails during CPU0 boot', + 'Text 2' => 'Test fails during PMIC execution' + } + end + + let(:type) { 'Hash' } + + it_behaves_like '#validate with an invalid type' + end + + context 'when the value is a Float' do + let(:value) { 11.35 } + let(:type) { 'Float' } + + it_behaves_like '#validate with an invalid type' + end + + context 'when the value is a FalseClass' do + let(:value) { false } + let(:type) { 'FalseClass' } + + it_behaves_like '#validate with an invalid type' + end + end +end diff --git a/spec/dragnet/validators/fields/field_validator_shared.rb b/spec/dragnet/validators/fields/field_validator_shared.rb new file mode 100644 index 0000000..b61905f --- /dev/null +++ b/spec/dragnet/validators/fields/field_validator_shared.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +RSpec.shared_examples_for 'Dragnet::Validators::Fields::FieldValidator#validate when the validation fails' do + it 'raises a Dragnet::Errors::ValidationError' do + expect { method_call } + .to raise_error(Dragnet::Errors::ValidationError, expected_message) + end +end diff --git a/spec/dragnet/validators/fields/field_validator_spec.rb b/spec/dragnet/validators/fields/field_validator_spec.rb new file mode 100644 index 0000000..3279a20 --- /dev/null +++ b/spec/dragnet/validators/fields/field_validator_spec.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +require 'dragnet/validators/fields/field_validator' + +RSpec.describe Dragnet::Validators::Fields::FieldValidator do + subject(:field_validator) { described_class.new } + + describe '#validate' do + subject(:method_call) { field_validator.validate(key, value) } + + let(:key) { nil } + let(:value) { nil } + + it 'raises a NotImplementedError' do + expect { method_call }.to raise_error( + NotImplementedError, + '#validate method not implemented in Dragnet::Validators::Fields::FieldValidator' + ) + end + end +end diff --git a/spec/dragnet/validators/fields/files_validator_spec.rb b/spec/dragnet/validators/fields/files_validator_spec.rb new file mode 100644 index 0000000..e8efe5f --- /dev/null +++ b/spec/dragnet/validators/fields/files_validator_spec.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +require 'dragnet/validators/fields/files_validator' + +require_relative 'field_validator_shared' + +RSpec.describe Dragnet::Validators::Fields::FilesValidator do + subject(:files_validator) { described_class.new } + + describe '#validate' do + subject(:method_call) { files_validator.validate(key, value) } + + let(:key) { 'files' } + let(:value) do + %w[ + source/tests/manual/safeio.yaml + source/tests/manual/safety.yaml + source/tests/manual/signals.yaml + ] + end + + context 'with an array of files' do + it "doesn't raise any errors" do + expect { method_call }.not_to raise_error + end + end + + context 'with a single string' do + let(:value) { 'test/manual/ESR_REQ_5745.yaml' } + let(:expected_result) { [value] } + + it 'turns it into an array' do + expect(method_call).to eq(expected_result) + end + end + + context 'when the files key has an invalid type' do + let(:value) { -5 } + + let(:expected_message) do + 'Incompatible type for key files: Expected String, Array got Integer instead' + end + + it_behaves_like 'Dragnet::Validators::Fields::FieldValidator#validate when the validation fails' + end + + context 'when the array on the files key contains something that is not a string' do + let(:value) { ['test/manual/ESR_REQ_3003.yaml', 23] } + + let(:expected_message) do + 'Incompatible type for key files: Expected a Array. '\ + 'Found a(n) Integer inside the array' + end + + it_behaves_like 'Dragnet::Validators::Fields::FieldValidator#validate when the validation fails' + end + end +end + diff --git a/spec/dragnet/validators/fields/id_validator_spec.rb b/spec/dragnet/validators/fields/id_validator_spec.rb new file mode 100644 index 0000000..edc393f --- /dev/null +++ b/spec/dragnet/validators/fields/id_validator_spec.rb @@ -0,0 +1,61 @@ +# frozen_string_literal: true + +require 'dragnet/validators/fields/id_validator' + +require_relative 'field_validator_shared' + +RSpec.describe Dragnet::Validators::Fields::IDValidator do + subject(:id_validator) { described_class.new } + + describe '#validate' do + subject(:method_call) { id_validator.validate(key, value) } + + let(:key) { 'id' } + let(:value) { 'ESR_REQ_5435' } + + context 'with a valid ID' do + it "doesn't raise any errors" do + expect { method_call }.not_to raise_error + end + end + + context "when the data doesn't have an id key", requirements: ['DRAGNET_0007'] do + let(:value) { nil } + let(:expected_message) { 'Missing required key: id' } + + it_behaves_like 'Dragnet::Validators::Fields::FieldValidator#validate when the validation fails' + end + + context 'when the id key has an invalid data type', requirements: ['DRAGNET_0007'] do + let(:value) { 6754.54 } + + let(:expected_message) do + 'Incompatible type for key id: Expected String, Array got Float instead' + end + + it_behaves_like 'Dragnet::Validators::Fields::FieldValidator#validate when the validation fails' + end + + context 'when the id key has multiple IDs in a string', requirements: ['DRAGNET_0007'] do + let(:value) { 'ERS_REQ_6845, ESR_REQ_9459' } + + let(:expected_message) do + "Disallowed character ',' found in the value for key id. "\ + 'To use multiple requirement IDs please put them into an array' + end + + it_behaves_like 'Dragnet::Validators::Fields::FieldValidator#validate when the validation fails' + end + + context 'when the array of IDs has something that is not a string', requirements: ['DRAGNET_0007'] do + let(:value) { ['ESR_REQ_3175', 2 + 3i, 'ESR_REQ_8518'] } + + let(:expected_message) do + 'Incompatible type for key id: Expected a Array. '\ + 'Found a(n) Complex inside the array' + end + + it_behaves_like 'Dragnet::Validators::Fields::FieldValidator#validate when the validation fails' + end + end +end diff --git a/spec/dragnet/validators/fields/meta_data_field_validator_spec.rb b/spec/dragnet/validators/fields/meta_data_field_validator_spec.rb new file mode 100644 index 0000000..8318ee5 --- /dev/null +++ b/spec/dragnet/validators/fields/meta_data_field_validator_spec.rb @@ -0,0 +1,85 @@ +# frozen_string_literal: true + +require 'dragnet/validators/fields/meta_data_field_validator' + +RSpec.describe Dragnet::Validators::Fields::MetaDataFieldValidator, requirements: %w[DRAGNET_0068] do + subject(:meta_data_field_validator) { described_class.new } + + describe '#validate' do + subject(:method_call) { meta_data_field_validator.validate(key, value) } + + let(:key) { 'name' } + + context 'when value is nil' do + let(:value) { nil } + + it 'does not raise any error' do + expect { method_call }.not_to raise_error + end + + it 'returns nil' do + expect(method_call).to be_nil + end + end + + context 'when the value is neither a String nor an Array' do + let(:value) { { the: 'best name' } } + + it 'raises a Dragnet::Errors::ValidationError' do + expect { method_call }.to raise_error( + Dragnet::Errors::ValidationError, + 'Incompatible type for key name: Expected String, Array got Hash instead' + ) + end + end + + context 'when the value is a String' do + let(:value) { 'Some name' } + + it 'does not raise any errors' do + expect { method_call }.not_to raise_error + end + + it 'returns an array with the given string' do + expect(method_call).to eq([value]) + end + end + + context 'when the value is an Array' do + context 'when the Array is empty' do + let(:value) { [] } + + it 'does not raise any errors' do + expect { method_call }.not_to raise_error + end + + it 'returns nil' do + expect(method_call).to be_nil + end + end + + context 'when the array has only strings' do + let(:value) { %w[a beautiful name right?] } + + it 'does not raise any errors' do + expect { method_call }.not_to raise_error + end + + it 'returns the same array' do + expect(method_call).to be(value) + end + end + + context 'when the array has something besides strings' do + let(:value) { ['some', 'name', 47] } + + it 'raises a Dragnet::Errors::ValidationError' do + expect { method_call }.to raise_error( + Dragnet::Errors::ValidationError, + 'Incompatible type for key name: Expected a Array. Found a(n) Integer inside the array' + ) + end + end + end + end +end diff --git a/spec/dragnet/validators/fields/path_validator_spec.rb b/spec/dragnet/validators/fields/path_validator_spec.rb new file mode 100644 index 0000000..bca3241 --- /dev/null +++ b/spec/dragnet/validators/fields/path_validator_spec.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +require 'dragnet/validators/fields/path_validator' + +require_relative 'field_validator_shared' + +RSpec.describe Dragnet::Validators::Fields::PathValidator do + subject(:path_validator) { described_class.new } + + describe '#validate' do + subject(:method_call) { path_validator.validate(key, value) } + + let(:key) { 'path' } + let(:value) { 'esrlabs/bsw/crypto' } + + context 'when the value is nil' do + let(:value) { nil } + let(:expected_message) { 'Missing required key: path' } + + it_behaves_like 'Dragnet::Validators::Fields::FieldValidator#validate when the validation fails' + end + + context 'when the value is not a String' do + let(:value) { 45 } + + let(:expected_message) do + 'Incompatible type for key path: Expected String got Integer instead' + end + + it_behaves_like 'Dragnet::Validators::Fields::FieldValidator#validate when the validation fails' + end + + context 'with a valid value' do + it 'does not raise any errors' do + expect { method_call }.not_to raise_error + end + end + end +end diff --git a/spec/dragnet/validators/fields/repos_validator_spec.rb b/spec/dragnet/validators/fields/repos_validator_spec.rb new file mode 100644 index 0000000..ccd6233 --- /dev/null +++ b/spec/dragnet/validators/fields/repos_validator_spec.rb @@ -0,0 +1,99 @@ +# frozen_string_literal: true + +require 'dragnet/validators/fields/repos_validator' + +require_relative 'field_validator_shared' + +RSpec.describe Dragnet::Validators::Fields::ReposValidator do + subject(:repos_validator) { described_class.new } + + describe '#validate' do + subject(:method_call) { repos_validator.validate(key, value) } + + let(:key) { 'repos' } + let(:value) { nil } + + let(:repo) do + instance_double(Dragnet::Repo, validate: true) + end + + before { allow(Dragnet::Repo).to receive(:new).and_return(repo) } + + context 'when the value is nil' do + it 'returns nil' do + expect(method_call).to be_nil + end + end + + context 'when the value is neither a hash nor an array' do + let(:value) { 'esrlabs/bsw/crypto' } + + let(:expected_message) do + 'Incompatible type for key repos: Expected Hash, Array got String instead' + end + + it_behaves_like 'Dragnet::Validators::Fields::FieldValidator#validate when the validation fails' + end + + shared_examples_for '#validate with an Array of Hashes' do + it 'creates a Repo object for each of the Hashes' do + hashes.each { |hash| expect(Dragnet::Repo).to receive(:new).with(**hash) } + method_call + end + + it 'returns an array' do + expect(method_call).to be_an(Array) + end + + it 'returns an array of Repo objects' do + expect(method_call).to all(eq(repo)) + end + + it 'calls validate on each of the Repo objects' do + expect(repo).to receive(:validate).exactly(hashes.length).times + method_call + end + end + + context 'when the value is an Array', requirements: ['DRAGNET_0037'] do + context 'when the array is empty' do + let(:value) { [] } + + it 'returns nil' do + expect(method_call).to be_nil + end + end + + context 'when the array contains something that is not a Hash' do + let(:value) { [{ some: 'repo' }, { another: 'repo' }, 'bsw/central/tools'] } + + let(:expected_message) do + 'Incompatible type for key repos: Expected a Array. Found a(n) String inside the array' + end + + it_behaves_like 'Dragnet::Validators::Fields::FieldValidator#validate when the validation fails' + end + + context 'when the array contains only hashes' do + let(:value) { [{ a: 'repo' }, { example_of: 'a repo' }] } + let(:hashes) { value } + + it_behaves_like '#validate with an Array of Hashes' + end + end + + context 'when the value is a Hash' do + let(:value) do + { + path: 'bsw/central/tools/pit_generator', + sha1: 'c6bb9fe3bd918094a24593fae480cdfa9fde28b3', + files: 'deconfabulator.c' + } + end + + let(:hashes) { [value] } + + it_behaves_like '#validate with an Array of Hashes' + end + end +end diff --git a/spec/dragnet/validators/fields/result_validator_spec.rb b/spec/dragnet/validators/fields/result_validator_spec.rb new file mode 100644 index 0000000..ef4cf81 --- /dev/null +++ b/spec/dragnet/validators/fields/result_validator_spec.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +require 'dragnet/validators/fields/result_validator' + +require_relative 'field_validator_shared' + +RSpec.describe Dragnet::Validators::Fields::ResultValidator do + subject(:result_validator) { described_class.new } + + describe '#validate' do + subject(:method_call) { result_validator.validate(key, value) } + + let(:key) { 'result' } + let(:value) { 'passed' } + + context 'with a valid result' do + it 'does not raise any errors' do + expect { method_call }.not_to raise_error + end + + context 'when the given value has odd capitalization' do + let(:value) { 'PaSsEd' } + + it 'returns the downcase version of the value' do + expect(method_call).to eq('passed') + end + end + end + + context "when the data doesn't have a result key", requirements: ['DRAGNET_0008'] do + let(:value) { nil } + let(:expected_message) { 'Missing required key: result' } + + it_behaves_like 'Dragnet::Validators::Fields::FieldValidator#validate when the validation fails' + end + + context 'when the result key contains something that is not a string', requirements: ['DRAGNET_0008'] do + let(:value) { /missed/ } + + let(:expected_message) do + 'Incompatible type for key result: Expected String got Regexp instead' + end + + it_behaves_like 'Dragnet::Validators::Fields::FieldValidator#validate when the validation fails' + end + + context 'when the value of the result field is not valid', requirements: ['DRAGNET_0008'] do + let(:value) { 'missed' } + + let(:expected_message) do + "Invalid value for key result: '#{value}'. Valid values are passed, failed" + end + + it_behaves_like 'Dragnet::Validators::Fields::FieldValidator#validate when the validation fails' + end + end +end diff --git a/spec/dragnet/validators/fields/sha1_validator_spec.rb b/spec/dragnet/validators/fields/sha1_validator_spec.rb new file mode 100644 index 0000000..44ad299 --- /dev/null +++ b/spec/dragnet/validators/fields/sha1_validator_spec.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +require 'dragnet/validators/fields/sha1_validator' + +require_relative 'field_validator_shared.rb' + +RSpec.describe Dragnet::Validators::Fields::SHA1Validator do + subject(:sha1_validator) { described_class.new } + + describe '#valiudate' do + subject(:method_call) { sha1_validator.validate(key, value) } + + let(:key) { 'sha1' } + let(:value) { '6c25d4c4e0183136b558ce8cbc67b0f9463c3ad1' } + + context 'with a valid SHA1' do + it "doesn't raise any errors" do + expect { method_call }.not_to raise_error + end + end + + context "when the data doesn't have a sha1 key", requirements: ['DRAGNET_0006'] do + let(:value) { nil } + let(:expected_message) { 'Missing required key: sha1' } + + it_behaves_like 'Dragnet::Validators::Fields::FieldValidator#validate when the validation fails' + end + + context 'when the SHA1 is not a string', requirements: ['DRAGNET_0006'] do + let(:value) { 123_456 } + + let(:expected_message) do + 'Incompatible type for key sha1: Expected String got Integer instead' + end + + it_behaves_like 'Dragnet::Validators::Fields::FieldValidator#validate when the validation fails' + end + + context 'when the SHA1 is too short', requirements: ['DRAGNET_0006'] do + let(:value) { 'af27' } + + let(:expected_message) do + "Invalid value for key sha1: '#{value}'. Expected a string between 7 and 40 characters" + end + + it_behaves_like 'Dragnet::Validators::Fields::FieldValidator#validate when the validation fails' + end + + context 'when the SHA1 is too long', requirements: ['DRAGNET_0006'] do + let(:value) { 'ca3a9455ae12dc3a1939a3152d82250cc9ed001a1f8736b43010a41702b' } + + let(:expected_message) do + "Invalid value for key sha1: '#{value}'. Expected a string between 7 and 40 characters" + end + + it_behaves_like 'Dragnet::Validators::Fields::FieldValidator#validate when the validation fails' + end + + context 'when the SHA1 is not a valid hexadecimal string', requirements: ['DRAGNET_0006'] do + let(:value) { '...jumped over the lazy gray dog' } + + let(:expected_message) do + "Invalid value for key sha1: '#{value}'. Doesn't seem to be a valid hexadecimal string" + end + + it_behaves_like 'Dragnet::Validators::Fields::FieldValidator#validate when the validation fails' + end + end +end diff --git a/spec/dragnet/validators/files_validator_spec.rb b/spec/dragnet/validators/files_validator_spec.rb new file mode 100644 index 0000000..f98e862 --- /dev/null +++ b/spec/dragnet/validators/files_validator_spec.rb @@ -0,0 +1,147 @@ +# frozen_string_literal: true + +require 'dragnet/validators/files_validator' + +RSpec.describe Dragnet::Validators::FilesValidator do + subject(:files_validator) { described_class.new(test_record, path) } + + let(:files) do + %w[ + test/manual/ESR_REQ_5745.yaml + test/manual/ESR_REQ_6845.yaml + test/manual/security/ESR_REQ_*.yaml + ] + end + + let(:expected_result) do + %w[ + /Workspace/source/test/manual/ESR_REQ_5745.yaml + /Workspace/source/test/manual/ESR_REQ_6845.yaml + /Workspace/source/test/manual/security/ESR_REQ_2005.yaml + /Workspace/source/test/manual/security/ESR_REQ_1721.yaml + ] + end + + let(:test_record) do + instance_double( + Dragnet::TestRecord, + files: files, + 'files=': true + ) + end + + let(:path) { Pathname.new('/Workspace/source') } + + before do + allow(path).to receive(:glob) + .with('test/manual/ESR_REQ_5745.yaml') + .and_return(expected_result.slice(0, 1)) + + allow(path).to receive(:glob) + .with('test/manual/ESR_REQ_6845.yaml') + .and_return(expected_result.slice(1, 1)) + + allow(path).to receive(:glob) + .with('test/manual/security/ESR_REQ_*.yaml') + .and_return(expected_result.slice(2, 2)) + end + + describe '#validate' do + subject(:method_call) { files_validator.validate } + + context 'when the files key is not present or has no value', requirements: ['DRAGNET_0004'] do + let(:files) { nil } + + it 'does nothing' do + expect(test_record).not_to receive(:files=) + method_call + end + end + + context "when one of the given files doesn't match a file in the repository", requirements: ['DRAGNET_0005'] do + let(:file) { 'test/manual/ESR_REQ_5745.yaml' } + + before do + allow(path).to receive(:glob).with(file).and_return([]) + end + + it 'raises a Dragnet::Errors::FileNotFoundError' do + expect { method_call }.to raise_error( + Dragnet::Errors::FileNotFoundError, + "Could not find any files matching #{file} in #{path}") + end + end + + context 'when a glob pattern is given', requirements: %w[DRAGNET_0013 DRAGNET_0014] do + let(:files) { ['test/manual/security/ESR_REQ_*.yaml'] } + + let(:expected_files) do + %w[ + /Workspace/source/test/manual/security/ESR_REQ_2005.yaml + /Workspace/source/test/manual/security/ESR_REQ_1721.yaml + ] + end + + it 'returns all files matching the pattern' do + expect(method_call).to eq(expected_files) + end + end + + context 'when the files have windows-style paths' do + let(:files) do + %w[ + test\manual\ESR_REQ_5745.yaml + test/manual\ESR_REQ_6845.yaml + test/manual/security/ESR_REQ_*.yaml + ] + end + + it 'translates the paths to linux-like paths' do + expect(method_call).to eq(expected_result) + end + end + + context 'when the listed files or glob patterns have a / at the beginning', + requirements: %w[DRAGNET_0072 DRAGNET_0073] do + let(:files) do + %w[ + /test/manual/safety/ESR_REQ_*.yaml + /test/manual/external/SRS_5452.yaml + /test/manual/external/SRS_6951.yaml + ] + end + + let(:expected_result) do + %w[ + /Workspace/source/test/manual/safety/ESR_REQ_5333.yaml + /Workspace/source/test/manual/safety/ESR_REQ_5069.yaml + /Workspace/source/test/manual/external/SRS_5452.yaml + /Workspace/source/test/manual/external/SRS_6951.yaml + ] + end + + before do + allow(path).to receive(:glob) + .with('test/manual/safety/ESR_REQ_*.yaml') + .and_return(expected_result.slice(0, 2)) + + allow(path).to receive(:glob) + .with('test/manual/external/SRS_5452.yaml') + .and_return(expected_result.slice(2, 1)) + + allow(path).to receive(:glob) + .with('test/manual/external/SRS_6951.yaml') + .and_return(expected_result.slice(3, 1)) + end + + it 'coerces the paths into relative paths' do + expect(method_call).to eq(expected_result) + end + end + + it 'resolves the files in the files key (including glob patterns)' do + expect(test_record).to receive(:files=).with(expected_result) + method_call + end + end +end diff --git a/spec/dragnet/validators/repos_validator_spec.rb b/spec/dragnet/validators/repos_validator_spec.rb new file mode 100644 index 0000000..43ad753 --- /dev/null +++ b/spec/dragnet/validators/repos_validator_spec.rb @@ -0,0 +1,191 @@ +# frozen_string_literal: true + +require 'dragnet/validators/repos_validator' + +RSpec.describe Dragnet::Validators::ReposValidator do + subject(:repos_validator) { described_class.new(test_record, path) } + + let(:repos) { nil } + + let(:test_record) do + instance_double( + Dragnet::TestRecord, + repos: repos + ) + end + + let(:path) do + instance_double( + Pathname, + to_s: '/workspace/source' + ) + end + + describe '#validate' do + subject(:method_call) { repos_validator.validate } + + context "when the Test Record has no 'repos'" do + it 'does not raise any errors' do + expect { method_call }.not_to raise_error + end + end + + context "when the Test Record have 'repos'" do + let(:absolute_path_string) { '/workspace/some/other/repo' } + let(:relative_path_string) { 'path/to/repo' } + let(:another_path_string) { 'another/path' } + + let(:files) { %w[some/random/file.cpp a/glob/pattern*.cpp] } + + let(:another_repo) do + instance_double( + Dragnet::Repo, + files: files, + path: another_path_string, + 'path=': true + ) + end + + let(:repos) do + [ + instance_double( + Dragnet::Repo, + files: nil, + path: absolute_path_string, + 'path=': true + ), + instance_double( + Dragnet::Repo, + files: nil, + path: relative_path_string, + 'path=': true + ), + another_repo + ] + end + + let(:complete_exists) { true } + let(:complete_path) { instance_double(Pathname, exist?: complete_exists) } + + let(:absolute_exists) { true } + + let(:absolute_path) do + instance_double( + Pathname, + absolute?: true, + relative?: false, + exist?: absolute_exists, + to_s: absolute_path_string + ) + end + + let(:relative_path) { instance_double(Pathname, absolute?: false, relative?: true, to_s: relative_path_string) } + let(:another_path) { instance_double(Pathname, absolute?: false) } + + let(:files_validator) do + instance_double( + Dragnet::Validators::FilesValidator, + validate: true + ) + end + + before do + allow(Pathname).to receive(:new).with(relative_path_string).and_return(relative_path) + allow(Pathname).to receive(:new).with(absolute_path_string).and_return(absolute_path) + allow(Pathname).to receive(:new).with(another_path_string).and_return(another_path) + + allow(path).to receive(:/).with(relative_path).and_return(complete_path) + allow(path).to receive(:/).with(another_path).and_return(complete_path) + + allow(Dragnet::Validators::FilesValidator).to receive(:new).and_return(files_validator) + end + + context 'when the path has backslashes and not slashes' do + let(:transformed_path) { 'another/path' } + + it 'transform the slashes and replaces the path string' do + expect(another_repo).to receive(:path=).with(transformed_path) + method_call + end + + it 'uses the transformed path to do the checking' do + expect(Pathname).to receive(:new).with(transformed_path) + method_call + end + end + + context 'when the repo has a relative path', requirements: %w[DRAGNET_0039] do + let(:complete_path) { instance_double(Pathname, exist?: complete_exists) } + + it 'creates a path by joining the workspace path with the path of the repo' do + expect(path).to receive(:/).with(relative_path) + method_call + end + + it 'verifies the existence of the generated path' do + expect(complete_path).to receive(:exist?) + method_call + end + + context "when the repo path doesn't exist" do + let(:complete_exists) { false } + + it 'raises a Dragnet::Errors::RepoPathNotFoundError', requirements: %w[DRAGNET_0058] do + expect { method_call }.to raise_error( + Dragnet::Errors::RepoPathNotFoundError, + 'Cannot find the repository path path/to/repo inside /workspace/source' + ) + end + end + end + + context 'when the repo has an absolute path', requirements: %w[DRAGNET_0039] do + it 'verifies the existence of the given path directly' do + expect(absolute_path).to receive(:exist?) + method_call + end + + context "when the repo path doesn't exist" do + let(:absolute_exists) { false } + + it 'raises a Dragnet::Errors::RepoPathNotFoundError', requirements: %w[DRAGNET_0058] do + expect { method_call }.to raise_error( + Dragnet::Errors::RepoPathNotFoundError, + 'Cannot find the repository path /workspace/some/other/repo' + ) + end + end + end + + context 'when the repos have no files', requirements: %w[DRAGNET_0049] do + let(:files) { nil } + + it 'does not perform any validation over files' do + expect(Dragnet::Validators::FilesValidator).not_to receive(:new) + method_call + end + + it 'does not raise any errors' do + expect { method_call }.not_to raise_error + end + end + + context "when one of the files listed in a 'repo' doesn't exist" do + let(:expected_error) do + [ + Dragnet::Errors::FileNotFoundError, + 'Could not find any files matching a/glob/pattern*.cpp in /workspace/source/another/path' + ] + end + + before do + allow(files_validator).to receive(:validate).and_raise(*expected_error) + end + + it 'raises a Dragnet::Errors::FileNotFoundError', requirements: %w[DRAGNET_0044 DRAGNET_0047 DRAGNET_0048] do + expect { method_call }.to raise_error(*expected_error) + end + end + end + end +end diff --git a/spec/dragnet/verification_result_spec.rb b/spec/dragnet/verification_result_spec.rb new file mode 100644 index 0000000..bdd4340 --- /dev/null +++ b/spec/dragnet/verification_result_spec.rb @@ -0,0 +1,342 @@ +# frozen_string_literal: true + +require 'date' +require 'dragnet/verification_result' + +RSpec.shared_examples_for 'Dragnet::VerificationResult#status= with an invalid status' do + it 'raises an ArgumentError' do + expect { method_call }.to raise_error( + ArgumentError, "Invalid status #{new_status}."\ + ' Valid statuses are: passed, skipped, failed' + ) + end +end + +RSpec.shared_examples_for 'Dragnet::VerificationResult#status=' do + it 'assigns the given status' do + method_call + expect(verification_result.status).to eq(new_status) + end +end + +RSpec.describe Dragnet::VerificationResult do + subject(:verification_result) { described_class.new(status: status) } + + let(:status) { :passed } + let(:new_status) { status } + + describe '#initialize' do + subject(:method_call) { verification_result } + + context 'with an invalid status' do + let(:status) { :deleted } + + it_behaves_like 'Dragnet::VerificationResult#status= with an invalid status' + end + + it_behaves_like 'Dragnet::VerificationResult#status=' + end + + describe '#status=' do + subject(:method_call) { verification_result.status = new_status } + + let(:new_status) { :skipped } + + context 'with an invalid status' do + let(:new_status) { 'passed' } + + it_behaves_like 'Dragnet::VerificationResult#status= with an invalid status' + end + + it_behaves_like 'Dragnet::VerificationResult#status=' + end + + describe '#passed?' do + subject(:method_call) { verification_result.passed? } + + context 'when status is :passed' do + it 'returns true' do + expect(method_call).to eq(true) + end + end + + context 'when status is not :passed' do + let(:status) { :failed } + + it 'returns false' do + expect(method_call).to eq(false) + end + end + end + + describe '#skipped?' do + subject(:method_call) { verification_result.skipped? } + + context 'when status is not :skipped' do + it 'returns false' do + expect(method_call).to eq(false) + end + end + + context 'when status is skipped' do + let(:status) { :skipped } + + it 'returns true' do + expect(method_call).to eq(true) + end + end + end + + describe 'failed?' do + subject(:method_call) { verification_result.failed? } + + context 'when status is not :failed' do + it 'returns false' do + expect(method_call).to eq(false) + end + end + + context 'when status is failed' do + let(:status) { :failed } + + it 'returns true' do + expect(method_call).to eq(true) + end + end + end + + shared_examples 'runtime update after timestamp change' do + describe 'runtime update', requirements: %w[DRAGNET_0077] do + before do + verification_result.started_at = Time.new(2028, 2, 6, 22, 40, 24) + verification_result.finished_at = Time.new(2032, 9, 17, 6, 3, 18) + end + + it 'updates the runtime' do + expect { method_call }.to change(verification_result, :runtime) + end + end + end + + shared_examples_for '#started_at' do + # Required variables: + # :attribute: The attribute whose value should change after the assignment + + it 'does not raise any errors' do + expect { method_call }.not_to raise_error + end + + it 'sets the given time' do + expect { method_call }.to change(verification_result, attribute).to(time) + end + + include_examples 'runtime update after timestamp change' + end + + shared_examples_for '#started_at with an object which is not a Time' do + it 'raises an ArgumentError' do + expect { method_call }.to raise_error( + ArgumentError, + "Expected a Time object, got #{time.class}" + ) + end + end + + describe '#started_at=', requirements: %w[DRAGNET_0075] do + subject(:method_call) { verification_result.started_at = time } + + let(:time) { Time.new(2024, 1, 31, 11, 20, 12) } + let(:attribute) { :started_at } + + context 'when the given time is not a Time object' do + let(:time) { ['2024/01/31 11:20:12', 1_706_696_412, nil, Date.new(2024, 1, 31)].sample } + + it_behaves_like '#started_at with an object which is not a Time' + end + + context "when finished_at hasn't been set" do + it_behaves_like '#started_at' + end + + context 'when finished_at is already set' do + before do + verification_result.finished_at = Time.new(2048, 2, 1, 22, 40, 24) + end + + context 'when the given time is bigger than finished_at' do + let(:time) { Time.new(2096, 4, 2, 20, 20, 48) } + + it 'raises an ArgumentError' do + expect { method_call }.to raise_error( + ArgumentError, 'started_at must be smaller than finished_at' + ) + end + end + + context 'when the given time is bigger than started_at' do + it_behaves_like '#started_at' + end + end + end + + describe '#finished_at=', requirements: %w[DRAGNET_0076] do + subject(:method_call) { verification_result.finished_at = time } + + let(:time) { Time.new(2031, 1, 24, 12, 20, 11) } + let(:attribute) { :finished_at } + + context 'when the given time is not a Time object' do + let(:time) { ['2031/01/24 12:20:11', 1_706_696_412, nil, Date.new(2031, 1, 24)].sample } + + it_behaves_like '#started_at with an object which is not a Time' + end + + context "when started_at hasn't been set" do + it_behaves_like '#started_at' + end + + context 'when started_at is already set' do + before do + verification_result.started_at = Time.new(2024, 1, 31, 11, 20, 12) + end + + context 'when the given time is smaller than started_at' do + let(:time) { Time.new(2016, 6, 12, 6, 10, 5) } + + it 'raises an ArgumentError' do + expect { method_call }.to raise_error( + ArgumentError, 'finished_at must be greater than started_at' + ) + end + end + + context 'when the given time is bigger than started_at' do + it_behaves_like '#started_at' + end + end + end + + shared_examples_for '#runtime! when both started_at and finished_at are set' do + before do + verification_result.started_at = Time.new(2024, 1, 31, 15, 34, 8) + verification_result.finished_at = Time.new(2024, 1, 31, 15, 35, 42) + end + + it 'returns the expected runtime' do + expect(method_call).to be_within(0.01).of(94) + end + end + + describe '#runtime!', requirements: %w[DRAGNET_0077] do + subject(:method_call) { verification_result.runtime! } + + shared_examples_for '#runtime! when started_at or finished_at are nil' do + it 'raises a MissingTimestampAttributeError' do + expect { method_call }.to raise_error( + Dragnet::Errors::MissingTimestampAttributeError, + 'Both started_at and finished_at must be set in order to calculate the runtime' + ) + end + end + + context 'when both started_at and finished_at are nil' do + it_behaves_like '#runtime! when started_at or finished_at are nil' + end + + context 'when started_at is set but finished_at is nil' do + before { verification_result.started_at = Time.new(2024, 1, 31, 15, 34, 8) } + + it_behaves_like '#runtime! when started_at or finished_at are nil' + end + + context 'when finished_at is set but started_at is nil' do + before { verification_result.finished_at = Time.new(2024, 1, 31, 15, 34, 8) } + + it_behaves_like '#runtime! when started_at or finished_at are nil' + end + + context 'when both started_at and finished_at are set' do + it_behaves_like '#runtime! when both started_at and finished_at are set' + end + end + + describe '#runtime', requirements: %w[DRAGNET_0077] do + subject(:method_call) { verification_result.runtime } + + context 'when both started_at and finished_at are nil' do + it 'returns nil' do + expect(method_call).to be_nil + end + end + + context 'when started_at is set but finished_at is nil' do + before { verification_result.started_at = Time.new(2024, 1, 31, 15, 34, 8) } + + it 'returns nil' do + expect(method_call).to be_nil + end + end + + context 'when finished_at is set but started_at is nil' do + before { verification_result.finished_at = Time.new(2024, 1, 31, 15, 34, 8) } + + it 'returns nil' do + expect(method_call).to be_nil + end + end + + context 'when both started_at and finished_at are set' do + it_behaves_like '#runtime! when both started_at and finished_at are set' + end + end + + describe '#log_message' do + subject(:method_call) { verification_result.log_message } + + context 'when the VerificationResult is passed' do + it 'returns the expected log message' do + expect(method_call).to eq("\e[0;92;49m✔ PASSED \e[0m") + end + end + + context 'when the VerificationResult is skipped' do + let(:verification_result) do + described_class.new( + status: :skipped, + reason: 'Changes detected in listed file(s): df0a857bc9..b00826b104 -- src/crypto/rsa.rs' + ) + end + + it 'returns the expected log message', requirements: %w[DRAGNET_0029] do + expect(method_call).to eq( + "\e[0;93;49m⚠ SKIPPED\e[0m Changes detected in listed file(s): df0a857bc9..b00826b104 -- src/crypto/rsa.rs" + ) + end + end + + context 'when the VerificationResult is failed' do + context 'with a reason' do + let(:verification_result) do + described_class.new( + status: :failed, + reason: "The path 'esrlabs/bsw/crypto' does not contain a valid git repository." + ) + end + + it 'returns the expected log message', requirements: %w[DRAGNET_0029] do + expect(method_call).to eq( + "\e[0;91;49m✘ FAILED \e[0m The path 'esrlabs/bsw/crypto' does not contain a valid git repository." + ) + end + end + + context 'without a reason' do + let(:verification_result) { described_class.new(status: :failed) } + + it 'returns the expected log message' do + expect(method_call).to eq("\e[0;91;49m✘ FAILED \e[0m Unknown reason") + end + end + end + end +end diff --git a/spec/dragnet/verifier_spec.rb b/spec/dragnet/verifier_spec.rb new file mode 100644 index 0000000..5e78dd0 --- /dev/null +++ b/spec/dragnet/verifier_spec.rb @@ -0,0 +1,277 @@ +# frozen_string_literal: true + +require 'dragnet/verifier' + +RSpec.describe Dragnet::Verifier do + subject(:verifier) do + described_class.new(test_records: test_records, repository: repository, logger: logger) + end + + let(:test_records) do + [ + instance_double( + Dragnet::TestRecord, + source_file: 'Workspace/project/test/manual/security.yml', + 'verification_result=': true + ), + instance_double( + Dragnet::TestRecord, + source_file: 'Workspace/project/test/manual/crypto.yml', + 'verification_result=': true + ), + instance_double( + Dragnet::TestRecord, + source_file: 'Workspace/project/test/manual/processes.yml', + 'verification_result=': true + ) + ] + end + + let(:repository) do + instance_double( + Dragnet::Repository + ) + end + + let(:logger) do + instance_double( + Dragnet::CLI::Logger, + info: true + ) + end + + describe '#verify' do + subject(:method_call) { verifier.verify } + + let(:passed_verification_result) do + instance_double( + Dragnet::VerificationResult, + status: :passed, + 'started_at=': true, + 'finished_at=': true, + log_message: 'PASSED' + ) + end + + let(:test_record_verifier) do + instance_double( + Dragnet::Verifiers::TestRecordVerifier, + verify: passed_verification_result + ) + end + + before do + allow(Dragnet::Verifiers::TestRecordVerifier).to receive(:new).and_return(test_record_verifier) + end + + RSpec.shared_examples 'prints nothing to STDOUT' do + it 'prints nothing to STDOUT', requirements: ['DRAGNET_0031'] do + expect { method_call }.not_to output.to_stdout + end + end + + include_examples 'prints nothing to STDOUT' + + it 'passes all the Test Records through the TestRecordVerifier', requirements: ['DRAGNET_0030'] do + test_records.each do |test_record| + expect(Dragnet::Verifiers::TestRecordVerifier).to receive(:new) + .with(test_record: test_record, repository: repository, test_records: test_records) + end + + method_call + end + + shared_examples 'logs the passing of the passing MTRs' do + # Required variables: + # :passed_test_records_count: The number of test records that should have passed the verification. + + it 'logs the passing of all MTRs', requirements: %w[DRAGNET_0028] do + expect(passed_verification_result).to receive(:log_message).exactly(passed_test_records_count).times + expect(logger).to receive(:info).with('PASSED').exactly(passed_test_records_count).times + + method_call + end + end + + shared_examples 'records the timestamp attributes to the VerificationResult objects' do + # Required variables + # :verification_result: The VerificationResult double that should receive the messages + # :number_of_messages: The number of messages that should be received by the VerificationResult double + + it 'records the started_at timestamp', requirements: %w[DRAGNET_0075] do + expect(verification_result).to receive(:started_at=).with(instance_of(Time)).exactly(number_of_messages).times + method_call + end + + it 'records the finished_at timestamp', requirements: %w[DRAGNET_0076] do + expect(verification_result).to receive(:finished_at=).with(instance_of(Time)).exactly(number_of_messages).times + method_call + end + end + + shared_examples_for 'attaches the passed VerificationResult to the passing MTRs' do + it 'attaches the passed VerificationResult to the passing MTRs' do + expect(passed_test_records).to all( + receive(:verification_result=).with(passed_verification_result) + ) + + method_call + end + end + + context 'when the verifications passes for all MTRs' do + let(:passed_test_records) { test_records } + let(:passed_test_records_count) { passed_test_records.size } + + include_examples 'prints nothing to STDOUT' + include_examples 'logs the passing of the passing MTRs' + + describe 'timestamp values for the passing MTRs' do + let(:verification_result) { passed_verification_result } + let(:number_of_messages) { passed_test_records_count } + + include_examples 'records the timestamp attributes to the VerificationResult objects' + end + + include_examples 'attaches the passed VerificationResult to the passing MTRs' + end + + context 'when the verification fails for one or more of the MTRs' do + let(:failed_test_records_count) { rand(1..2) } + let(:failed_test_records) { test_records.sample(failed_test_records_count) } + let(:passed_test_records) { test_records - failed_test_records } + let(:passed_test_records_count) { passed_test_records.size } + + let(:reason) { "'result' field has the status 'failed'" } + + let(:failed_verification_result) do + instance_double( + Dragnet::VerificationResult, + status: :failed, + reason: reason, + 'started_at=': true, + 'finished_at=': true, + log_message: 'FAILED' + ) + end + + let(:failing_test_record_verifier) do + instance_double( + Dragnet::Verifiers::TestRecordVerifier, + verify: failed_verification_result + ) + end + + before do + failed_test_records.each do |failed_test_record| + allow(Dragnet::Verifiers::TestRecordVerifier).to receive(:new) + .with(test_record: failed_test_record, repository: repository, test_records: test_records) + .and_return(failing_test_record_verifier) + end + end + + include_examples 'prints nothing to STDOUT' + + it 'logs the failure of the test record(s)', requirements: %w[DRAGNET_0028] do + expect(failed_verification_result).to receive(:log_message).exactly(failed_test_records_count).times + expect(logger).to receive(:info).with('FAILED').exactly(failed_test_records_count).times + + method_call + end + + describe 'timestamp values for the passing MTRs' do + let(:verification_result) { passed_verification_result } + let(:number_of_messages) { passed_test_records_count } + + include_examples 'records the timestamp attributes to the VerificationResult objects' + end + + describe 'timestamp values for the failing MTRs' do + let(:verification_result) { failed_verification_result } + let(:number_of_messages) { failed_test_records_count } + + include_examples 'records the timestamp attributes to the VerificationResult objects' + end + + it 'attaches the failed VerificationResult to the failed TestRecords' do + expect(failed_test_records).to all( + receive(:verification_result=).with(failed_verification_result) + ) + + method_call + end + + include_examples 'logs the passing of the passing MTRs' + include_examples 'attaches the passed VerificationResult to the passing MTRs' + end + + context 'when the verification is skipped for one or more of the MTRs' do + let(:skipped_test_records_count) { rand(1..2) } + let(:skipped_test_records) { test_records.sample(skipped_test_records_count) } + let(:passed_test_records) { test_records - skipped_test_records } + let(:passed_test_records_count) { passed_test_records.size } + + let(:reason) { 'Changes detected in listed file(s)' } + + let(:skipped_verification_result) do + instance_double( + Dragnet::VerificationResult, + status: :skipped, + reason: reason, + 'started_at=': true, + 'finished_at=': true, + log_message: 'SKIPPED' + ) + end + + let(:skipping_test_record_verifier) do + instance_double( + Dragnet::Verifiers::TestRecordVerifier, + verify: skipped_verification_result + ) + end + + before do + skipped_test_records.each do |skipped_test_record| + allow(Dragnet::Verifiers::TestRecordVerifier).to receive(:new) + .with(test_record: skipped_test_record, repository: repository, test_records: test_records) + .and_return(skipping_test_record_verifier) + end + end + + include_examples 'prints nothing to STDOUT' + + it 'logs the skipping of the test record(s)', requirements: %w[DRAGNET_0028] do + expect(skipped_verification_result).to receive(:log_message).exactly(skipped_test_records_count).times + expect(logger).to receive(:info).with('SKIPPED').exactly(skipped_test_records_count).times + + method_call + end + + describe 'timestamp values for the passing MTRs' do + let(:verification_result) { passed_verification_result } + let(:number_of_messages) { passed_test_records_count } + + include_examples 'records the timestamp attributes to the VerificationResult objects' + end + + describe 'timestamp values for the skipped MTRs' do + let(:verification_result) { skipped_verification_result } + let(:number_of_messages) { skipped_test_records_count } + + include_examples 'records the timestamp attributes to the VerificationResult objects' + end + + it 'attaches the skipped VerificationResult to the skipped TestRecords' do + expect(skipped_test_records).to all( + receive(:verification_result=).with(skipped_verification_result) + ) + + method_call + end + + include_examples 'logs the passing of the passing MTRs' + include_examples 'attaches the passed VerificationResult to the passing MTRs' + end + end +end diff --git a/spec/dragnet/verifiers/changes_verifier_spec.rb b/spec/dragnet/verifiers/changes_verifier_spec.rb new file mode 100644 index 0000000..f46b9b5 --- /dev/null +++ b/spec/dragnet/verifiers/changes_verifier_spec.rb @@ -0,0 +1,126 @@ +# frozen_string_literal: true + +require 'dragnet/verifiers/changes_verifier' + +RSpec.describe Dragnet::Verifiers::ChangesVerifier do + subject(:changes_verifier) do + described_class.new(test_record: test_record, repository: repository, test_records: test_records) + end + + let(:path) { Pathname.new('/Workspace/project/') } + + let(:commit) do + instance_double( + Git::Object::Commit, + sha: '83674b8a8168c21de46547f62b606e6ec981c9c7' + ) + end + + let(:repository) do + instance_double( + Dragnet::Repository, + path: path, + head: commit + ) + end + + let(:test_records) do + [ + instance_double( + Dragnet::TestRecord, + source_file: path / 'tests/manual/security.yml', + sha1: 'ed981b34eed' + ), + instance_double( + Dragnet::TestRecord, + source_file: path / 'tests/manual/processes.yml', + sha1: '05f961d151e' + ) + ] + end + + let(:test_record) { test_records.first } + + before do + allow(repository).to receive(:diff).with('ed981b34eed', 'HEAD').and_return(diff) + end + + describe '#verify' do + subject(:method_call) { changes_verifier.verify } + + context 'when there are no changes in the repository', requirements: ['DRAGNET_0016'] do + let(:diff) do + instance_double( + Git::Diff, + size: 0 + ) + end + + it 'returns nil' do + expect(method_call).to be_nil + end + end + + context 'when there are changes in the repository', requirements: ['DRAGNET_0016'] do + let(:diff) do + instance_double( + Git::Diff, + size: 2, + stats: stats + ) + end + + context 'when the changes are only in MTR files', requirements: ['DRAGNET_0015'] do + let(:stats) do + { + files: { + 'tests/manual/processes.yml' => { insertions: 2, deletions: 6 } + } + } + end + + it 'returns nil' do + expect(method_call).to be_nil + end + end + + context 'when the change include other files', requirements: ['DRAGNET_0015'] do + let(:stats) do + { + files: { + 'tests/manual/security.yml' => { insertions: 1, deletions: 1 }, + 'src/startup/entry.cpp' => { insertions: 14, deletions: 6 } + } + } + end + + let(:expected_parameters) do + { + status: :skipped, + reason: 'Changes detected in the repository: ed981b34ee..83674b8a81 # -- src/startup/entry.cpp' + } + end + + let(:verification_result) do + instance_double( + Dragnet::VerificationResult + ) + end + + before do + allow(Dragnet::VerificationResult).to receive(:new) + .and_return(verification_result) + end + + it 'creates a VerificationResult object with the expected parameters' do + expect(Dragnet::VerificationResult).to receive(:new).with(expected_parameters) + method_call + end + + it 'returns the failed VerificationResult' do + expect(method_call).to eq(verification_result) + end + end + end + end +end diff --git a/spec/dragnet/verifiers/files_verifier_spec.rb b/spec/dragnet/verifiers/files_verifier_spec.rb new file mode 100644 index 0000000..e820099 --- /dev/null +++ b/spec/dragnet/verifiers/files_verifier_spec.rb @@ -0,0 +1,115 @@ +# frozen_string_literal: true + +require 'dragnet/verifiers/files_verifier' + +RSpec.describe Dragnet::Verifiers::FilesVerifier do + subject(:files_verifier) do + described_class.new(test_record: test_record, repository: repository) + end + + let(:path) { Pathname.new('/Workspace/project') } + + let(:files) do + [ + path / 'src/master/module.cpp', + path / 'src/master/module.h', + path / 'src/master/constants.h' + ] + end + + let(:test_record) do + instance_double( + Dragnet::TestRecord, + sha1: 'a981468aedddc0b6b19a00949591561985f8b956', + files: files + ) + end + + let(:commit) do + instance_double( + Git::Object::Commit, + sha: '83674b8a8168c21de46547f62b606e6ec981c9c7' + ) + end + + let(:repository) do + instance_double( + Dragnet::Repository, + diff: diff, + head: commit, + path: path + ) + end + + let(:diff) do + instance_double( + Git::Diff, + size: 0 + ) + end + + before do + allow(diff).to receive(:path).and_return(diff) + end + + describe '#verify' do + subject(:method_call) { files_verifier.verify } + + context 'when the MTR has not files' do + let(:files) { [] } + + it 'returns nil' do + expect(method_call).to be_nil + end + end + + context 'when there are no changes in the listed files', requirements: ['DRAGNET_0016'] do + it 'returns nil' do + expect(method_call).to be_nil + end + end + + context 'when one or more of the files have changes', requirements: %w[DRAGNET_0012 DRAGNET_0014] do + let(:changed_diff) do + instance_double( + Git::Diff, + size: 1 + ) + end + + let(:verification_result) do + instance_double( + Dragnet::VerificationResult + ) + end + + let(:expected_parameters) do + { + status: :skipped, + reason: 'Changes detected in listed file(s): a981468aed..83674b8a81'\ + ' -- src/master/module.cpp src/master/constants.h' + } + end + + before do + allow(diff).to receive(:path) + .with('src/master/module.cpp').and_return(changed_diff) + + allow(diff).to receive(:path) + .with('src/master/constants.h').and_return(changed_diff) + + allow(Dragnet::VerificationResult).to receive(:new) + .and_return(verification_result) + end + + it 'creates a VerificationResult object with the expected parameters' do + expect(Dragnet::VerificationResult).to receive(:new).with(expected_parameters) + method_call + end + + it 'returns the expected VerificationResult' do + expect(method_call).to eq(verification_result) + end + end + end +end diff --git a/spec/dragnet/verifiers/repos_verifier_spec.rb b/spec/dragnet/verifiers/repos_verifier_spec.rb new file mode 100644 index 0000000..0ab7214 --- /dev/null +++ b/spec/dragnet/verifiers/repos_verifier_spec.rb @@ -0,0 +1,263 @@ +# frozen_string_literal: true + +require 'dragnet/verifiers/repos_verifier' + +RSpec.describe Dragnet::Verifiers::ReposVerifier do + subject(:repos_verifier) { described_class.new(test_record: test_record, multi_repository: multi_repository) } + + let(:repos) { nil } + + let(:test_record) do + instance_double( + Dragnet::TestRecord, + repos: repos + ) + end + + let(:existing_repositories) { {} } + + let(:multi_repository) do + instance_double( + Dragnet::MultiRepository, + path: Pathname('/Workspace/project/source'), + repositories: existing_repositories + ) + end + + describe '#verify' do + subject(:method_call) { repos_verifier.verify } + + context "when the Test Record has no 'repos'" do + it 'does not raise any errors' do + expect { method_call }.not_to raise_error + end + + it 'returns nil' do + expect(method_call).to be_nil + end + end + + context "when the Test Record has 'repos'" do + let(:repo_files) do + %w[ + /Workspace/project/source/esrlabs/bsw/crypto/safe_rng.cpp + /Workspace/project/source/esrlabs/bsw/crypto/safe_rng.h + ] + end + + let(:repo_with_files) do + instance_double( + Dragnet::Repo, + path: 'esrlabs/bsw/crypto', + files: repo_files, + sha1: '6fd07835de' + ) + end + + let(:repo_without_files) do + instance_double( + Dragnet::Repo, + path: 'esrlabs/libs/security', + files: nil, + sha1: '5ac903b80e' + ) + end + + let(:repos) do + [ + repo_with_files, + repo_without_files + ] + end + + let(:repository_with_files) do + instance_double( + Dragnet::Repository + ) + end + + let(:repository_without_files) do + instance_double( + Dragnet::Repository + ) + end + + let(:files_verifier) do + instance_double( + Dragnet::Verifiers::FilesVerifier, + verify: nil + ) + end + + let(:changes_verifier) do + instance_double( + Dragnet::Verifiers::ChangesVerifier, + verify: nil + ) + end + + let(:proxy_test_record_with_files) do + instance_double( + Dragnet::TestRecord + ) + end + + let(:proxy_test_record_without_files) do + instance_double( + Dragnet::TestRecord + ) + end + + before do + allow(Dragnet::Repository).to receive(:new) + .with(path: Pathname.new('/Workspace/project/source/esrlabs/bsw/crypto')) + .and_return(repository_with_files) + + allow(Dragnet::Repository).to receive(:new) + .with(path: Pathname.new('/Workspace/project/source/esrlabs/libs/security')) + .and_return(repository_without_files) + + allow(Dragnet::Verifiers::FilesVerifier).to receive(:new).and_return(files_verifier) + allow(Dragnet::Verifiers::ChangesVerifier).to receive(:new).and_return(changes_verifier) + + allow(Dragnet::TestRecord).to receive(:new) + .with(files: repo_files, sha1: '6fd07835de').and_return(proxy_test_record_with_files) + + allow(Dragnet::TestRecord).to receive(:new) + .with(files: nil, sha1: '5ac903b80e').and_return(proxy_test_record_without_files) + end + + describe 'Repositories', requirements: %w[DRAGNET_0050] do + it 'creates a Repository object for the Repo with files with the expected path' do + expect(Dragnet::Repository).to receive(:new) + .with(path: Pathname.new('/Workspace/project/source/esrlabs/bsw/crypto')) + + method_call + end + + it 'creates a Repository object for the Repo without files with the expected path' do + expect(Dragnet::Repository).to receive(:new) + .with(path: Pathname.new('/Workspace/project/source/esrlabs/libs/security')) + + method_call + end + + context 'when a Repository for the path already exists' do + let(:existing_repositories) do + { 'esrlabs/bsw/crypto' => repository_with_files } + end + + it 'does not create a new Repository for that path' do + expect(Dragnet::Repository).not_to receive(:new) + .with(path: '/Workspace/project/source/esrlabs/bsw/crypto') + + method_call + end + end + + context 'when the creation of a repository fails', requirements: %w[DRAGNET_0045] do + let(:failed_verification_result) do + instance_double( + Dragnet::VerificationResult + ) + end + + before do + allow(Dragnet::Repository).to receive(:new) + .and_raise(ArgumentError, 'Path not found .git') + + allow(Dragnet::VerificationResult).to receive(:new) + .and_return(failed_verification_result) + end + + it 'does not raise any errors' do + expect { method_call }.not_to raise_error + end + + it 'creates a failed VerificationResult object with the expected status and reason' do + expect(Dragnet::VerificationResult).to receive(:new) + .with(status: :failed, reason: "The path 'esrlabs/bsw/crypto' does not contain a valid git repository.") + + method_call + end + + it 'returns the expected VerificationResult object' do + expect(method_call).to eq(failed_verification_result) + end + end + end + + describe 'Proxy TestRecords', requirements: %w[DRAGNET_0050] do + it 'creates a proxy TestRecord for the first Repo with the expected parameters' do + expect(Dragnet::TestRecord).to receive(:new).with(files: repo_files, sha1: '6fd07835de') + method_call + end + + it 'creates a proxy TestRecord for the second Repo with the expected parameters' do + expect(Dragnet::TestRecord).to receive(:new).with(files: nil, sha1: '5ac903b80e') + method_call + end + end + + describe 'Verification' do + it 'verifies the Repo that has files with the FilesVerifier', requirements: %w[DRAGNET_0051] do + expect(Dragnet::Verifiers::FilesVerifier).to receive(:new) + .with(test_record: proxy_test_record_with_files, repository: repository_with_files) + + expect(files_verifier).to receive(:verify) + method_call + end + + it 'verifies the Repo that has no files with the ChangesVerifier', requirements: %w[DRAGNET_0053] do + expect(Dragnet::Verifiers::ChangesVerifier).to receive(:new) + .with(test_record: proxy_test_record_without_files, repository: repository_without_files, test_records: []) + + expect(changes_verifier).to receive(:verify) + method_call + end + end + + describe 'Inner verifier failures' do + shared_examples_for '#verify when one of the inner verifiers fails' do + before do + allow(files_verifier).to receive(:verify).and_return(failed_verification_result) + end + + it 'returns the VerificationResult returned by the inner verifier' do + expect(method_call).to eq(failed_verification_result) + end + + it 'does not raise any errors' do + expect { method_call }.not_to raise_error + end + end + + context 'when the FilesVerifier fails', requirements: %w[DRAGNET_0052 DRAGNET_0059] do + let(:failed_verification_result) do + instance_double( + Dragnet::VerificationResult, + status: :failed, + reason: 'Changes detected in listed file(s): 6fd07835de..b8fce26205 ' \ + '-- /Workspace/project/source/esrlabs/bsw/crypto/safe_rng.cpp' + ) + end + + it_behaves_like '#verify when one of the inner verifiers fails' + end + + context 'when the ChangesVerifier fails', requirements: %w[DRAGNET_0054 DRAGNET_0059] do + let(:failed_verification_result) do + instance_double( + Dragnet::VerificationResult, + status: :failed, + reason: 'Changes detected in the repository: 5ac903b80e..eeb9101593 '\ + '# -- include/securenvm/AsyncSecureNvm.h' + ) + end + + it_behaves_like '#verify when one of the inner verifiers fails' + end + end + end + end +end diff --git a/spec/dragnet/verifiers/result_verifier_spec.rb b/spec/dragnet/verifiers/result_verifier_spec.rb new file mode 100644 index 0000000..45ef18d --- /dev/null +++ b/spec/dragnet/verifiers/result_verifier_spec.rb @@ -0,0 +1,78 @@ +# frozen_string_literal: true + +require 'dragnet/verifiers/result_verifier' + +RSpec.shared_examples 'Dragnet::Verifiers::ResultVerifier#verify creates and assign the VerificationResult object' do + it 'creates the Verification Result with the expected parameters' do + expect(Dragnet::VerificationResult).to receive(:new).with(expected_parameters) + method_call + end + + it 'returns the failed VerificationResult' do + expect(method_call).to eq(verification_result) + end +end + +RSpec.describe Dragnet::Verifiers::ResultVerifier do + subject(:result_verifier) { described_class.new(test_record: test_record) } + + let(:passed) { false } + + let(:test_record) do + instance_double( + Dragnet::TestRecord, + result: result, + passed?: passed + ) + end + + let(:verification_result) do + instance_double( + Dragnet::VerificationResult + ) + end + + before do + allow(Dragnet::VerificationResult).to receive(:new) + .and_return(verification_result) + end + + describe '#verify' do + subject(:method_call) { result_verifier.verify } + + context 'when the result is "passed"', requirements: ['DRAGNET_0016'] do + let(:result) { 'passed' } + let(:passed) { true } + + it 'returns nil' do + expect(method_call).to be_nil + end + end + + context 'when the result is "failed"', requirements: ['DRAGNET_0011'] do + let(:result) { 'failed' } + + let(:expected_parameters) do + { + status: :failed, + reason: "'result' field has the status 'failed'" + } + end + + include_examples 'Dragnet::Verifiers::ResultVerifier#verify creates and assign the VerificationResult object' + end + + context 'when the result is something else' do + let(:result) { 'unknown' } + + let(:expected_parameters) do + { + status: :failed, + reason: "'result' field has the status 'unknown'" + } + end + + include_examples 'Dragnet::Verifiers::ResultVerifier#verify creates and assign the VerificationResult object' + end + end +end diff --git a/spec/dragnet/verifiers/test_record_verifier_spec.rb b/spec/dragnet/verifiers/test_record_verifier_spec.rb new file mode 100644 index 0000000..c6070a3 --- /dev/null +++ b/spec/dragnet/verifiers/test_record_verifier_spec.rb @@ -0,0 +1,271 @@ +# frozen_string_literal: true + +require 'dragnet/verifiers/test_record_verifier' + +RSpec.describe Dragnet::Verifiers::TestRecordVerifier do + subject(:test_record_verifier) do + described_class.new(test_record: test_record, repository: repository, test_records: test_records) + end + + let(:files) { nil } + let(:repos) { nil } + + let(:test_record) do + instance_double( + Dragnet::TestRecord, + files: files, + repos: repos, + verification_result: nil, + 'verification_result=': true + ) + end + + let(:repository) do + instance_double( + Dragnet::Repository + ) + end + + let(:test_records) do + [ + instance_double(Dragnet::TestRecord), + instance_double(Dragnet::TestRecord), + instance_double(Dragnet::TestRecord) + ] + end + + describe '#verify' do + subject(:method_call) { test_record_verifier.verify } + + let(:result_verifier) do + instance_double( + Dragnet::Verifiers::ResultVerifier, + verify: nil + ) + end + + let(:changes_verifier) do + instance_double( + Dragnet::Verifiers::ChangesVerifier, + verify: nil + ) + end + + before do + allow(Dragnet::Verifiers::ResultVerifier).to receive(:new).and_return(result_verifier) + allow(Dragnet::Verifiers::ChangesVerifier).to receive(:new).and_return(changes_verifier) + end + + shared_examples '#verify' do + it "uses the ResultVerifier to verify the TestRecord's result" do + expect(Dragnet::Verifiers::ResultVerifier).to receive(:new).with(test_record: test_record) + expect(result_verifier).to receive(:verify) + method_call + end + end + + shared_examples_for '#verify when all verifications pass' do + let(:passed_verification_result) do + instance_double( + Dragnet::VerificationResult + ) + end + + before do + allow(Dragnet::VerificationResult).to receive(:new) + .with(status: :passed).and_return(passed_verification_result) + end + + it 'creates a passed VerificationResult', requirements: %w[DRAGNET_0016] do + expect(Dragnet::VerificationResult).to receive(:new).with(status: :passed) + method_call + end + + it 'returns the passed VerificationResult', requirements: %w[DRAGNET_0016] do + expect(method_call).to eq(passed_verification_result) + end + end + + shared_context 'when the TestRecord fails the verification' do + # Required variables + # :test_record: The test record that should to fail the verification + # :failed_verifier: The instance double of the Verifier class which + # triggers the failure + + let(:failed_verification_result) do + instance_double( + Dragnet::VerificationResult + ) + end + + before do + allow(failed_verifier).to receive(:verify).and_return(failed_verification_result) + end + + it 'returns the failed VerificationResult' do + expect(method_call).to eq(failed_verification_result) + end + end + + it_behaves_like '#verify' + + context 'when the TestRecord fails the result verification' do + let(:failed_verifier) { result_verifier } + + include_context 'when the TestRecord fails the verification' + + it 'does not pass the TestRecord to the FilesVerifier' do + expect(Dragnet::Verifiers::FilesVerifier).not_to receive(:new) + method_call + end + + it 'does not pass the TestRecord to the ReposVerifier' do + expect(Dragnet::Verifiers::ReposVerifier).not_to receive(:new) + method_call + end + + it 'does not pass the TestRecord to the ChangesVerifier' do + expect(Dragnet::Verifiers::ChangesVerifier).not_to receive(:new) + method_call + end + end + + context 'when the TestRecord has files' do + let(:files) do + %w[ + modules/dem/src/dem/DEMLocker.cpp + modules/dem/src/dem/DEMUtils.cpp + modules/dem/src/dem/DiagJobs/SecondaryErrorMemory/SecAppDummyDTCJob.cpp + ] + end + + let(:files_verifier) do + instance_double( + Dragnet::Verifiers::FilesVerifier, + verify: nil + ) + end + + before do + allow(Dragnet::Verifiers::FilesVerifier).to receive(:new).and_return(files_verifier) + end + + it_behaves_like '#verify' + + it 'does not pass the TestRecord to the ReposVerifier' do + expect(Dragnet::Verifiers::ReposVerifier).not_to receive(:new) + method_call + end + + it 'does not pass the TestRecord to the ChangesVerifier' do + expect(Dragnet::Verifiers::ChangesVerifier).not_to receive(:new) + method_call + end + + it 'uses the FilesVerifier to verify the changes to the listed files' do + expect(Dragnet::Verifiers::FilesVerifier).to receive(:new) + .with(test_record: test_record, repository: repository) + + expect(files_verifier).to receive(:verify) + method_call + end + + context 'when the TestRecord fails the files verification' do + let(:failed_verifier) { files_verifier } + + include_context 'when the TestRecord fails the verification' + end + + context 'when the TestRecord passes the files verification' do + it_behaves_like '#verify when all verifications pass' + end + end + + context 'when the TestRecord has repositories' do + let(:repos) do + [ + instance_double(Dragnet::Repo), + instance_double(Dragnet::Repo), + instance_double(Dragnet::Repo) + ] + end + + let(:repos_verifier) do + instance_double( + Dragnet::Verifiers::ReposVerifier, + verify: nil + ) + end + + before do + allow(Dragnet::Verifiers::ReposVerifier).to receive(:new).and_return(repos_verifier) + end + + it_behaves_like '#verify' + + it 'does not pass the TestRecord to the FilesVerifier' do + expect(Dragnet::Verifiers::FilesVerifier).not_to receive(:new) + method_call + end + + it 'does not pass the TestRecord to the ChangesVerifier' do + expect(Dragnet::Verifiers::ChangesVerifier).not_to receive(:new) + method_call + end + + it 'uses the ReposVerifier to verify the changes to the listed repositories', requirements: %w[DRAGNET_0050] do + expect(Dragnet::Verifiers::ReposVerifier).to receive(:new) + .with(test_record: test_record, multi_repository: repository) + + expect(repos_verifier).to receive(:verify) + method_call + end + + context 'when the TestRecord fails the files verification' do + let(:failed_verifier) { repos_verifier } + + include_context 'when the TestRecord fails the verification' + end + + context 'when the TestRecord passes the repos verification' do + it_behaves_like '#verify when all verifications pass' + end + end + + context "when the TestRecord doesn't have files nor repositories" do + it_behaves_like '#verify' + + it 'does not pass the TestRecord to the FilesVerifier' do + expect(Dragnet::Verifiers::FilesVerifier).not_to receive(:new) + method_call + end + + it 'does not pass the TestRecord to the ReposVerifier' do + expect(Dragnet::Verifiers::ReposVerifier).not_to receive(:new) + method_call + end + + it 'uses the ChangesVerifier to verify the changes in the repository' do + expect(Dragnet::Verifiers::ChangesVerifier).to receive(:new) + .with(test_record: test_record, repository: repository, test_records: test_records) + + expect(changes_verifier).to receive(:verify) + method_call + end + + context 'when the TestRecord fails the changes verification' do + let(:failed_verifier) { changes_verifier } + + include_context 'when the TestRecord fails the verification' + end + + context 'when the TestRecord passes the changes verification' do + it_behaves_like '#verify when all verifications pass' + end + end + + context 'when the TestRecord passes all the verifiers' do + it_behaves_like '#verify when all verifications pass' + end + end +end diff --git a/spec/dragnet_spec.rb b/spec/dragnet_spec.rb new file mode 100644 index 0000000..2e94b38 --- /dev/null +++ b/spec/dragnet_spec.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +RSpec.describe Dragnet do + it 'has a version number' do + expect(Dragnet::VERSION).not_to be nil + end +end diff --git a/spec/integration/dragnet/cli/master_spec.rb b/spec/integration/dragnet/cli/master_spec.rb new file mode 100644 index 0000000..20d1f20 --- /dev/null +++ b/spec/integration/dragnet/cli/master_spec.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +require 'dragnet/cli/master' +require 'shared/cli_master' + +RSpec.describe Dragnet::CLI::Master do + describe '--version', requirements: %w[DRAGNET_0017 DRAGNET_0026] do + subject(:output) { `#{base_command}` } + + let(:base_command) { 'bundle exec exe/dragnet --version' } + + include_context "with the default CLI's --version output" + + it 'prints the current version of the gem' do + expect(output).to eq(expected_output) + end + + context 'when the -q switch is used' do + subject(:output) { `#{base_command} -q` } + + let(:expected_output) { '' } + + it 'prints nothing' do + expect(output).to eq(expected_output) + end + end + end +end diff --git a/spec/integration/dragnet/exporters/html_exporter_spec.rb b/spec/integration/dragnet/exporters/html_exporter_spec.rb new file mode 100644 index 0000000..b4211ed --- /dev/null +++ b/spec/integration/dragnet/exporters/html_exporter_spec.rb @@ -0,0 +1,524 @@ +# frozen_string_literal: true + +require 'active_support' +require 'active_support/core_ext/array/access' +require 'fileutils' +require 'logger' +require 'tmpdir' + +require 'dragnet/exporters/html_exporter' + +RSpec.shared_context 'with a mocked template for Dragnet::Exporters::HTMLExporter' do + before do + # This has to be mocked because there is no way to pass a different template + # to the class, so the only way to be able to change the content is by + # mocking the file read. + allow(File).to receive(:read) + .with(described_class::TEMPLATE).and_return(template) + end +end + +RSpec.shared_examples 'Dragnet::Exporters::HTMLExporter#export returns the expected output' do + it 'returns the expected output' do + expect(output).to eq(expected_output) + end +end + +RSpec.shared_context 'with a test repository for Dragnet::Exporters::HTMLExporter' do + let(:temp_dir) { Pathname.new(Dir.mktmpdir) } + let(:repository) { Dragnet::Repository.new(path: temp_dir) } + let(:git_bundle) { Pathname.new(__dir__) / 'test_files' / 'repo.git' } + let(:git) { Git.clone(git_bundle, '', path: temp_dir) } + + before { git.checkout('master') } + + after do + FileUtils.rm_rf(temp_dir) + end +end + +RSpec.describe Dragnet::Exporters::HTMLExporter, requirements: ['DRAGNET_0022'] do + subject(:output) { html_exporter.export } + + let(:html_exporter) do + described_class.new( + test_records: test_records, errors: errors, repository: repository, logger: logger + ) + end + + let(:test_records) { [] } + let(:errors) { [] } + + # We only use a real repository for certain methods, it takes time to clone + # and prepare the repository, therefore unless it is needed we just use an + # empty double. (If anything tries to use the "repo" an error will be raised) + let(:repository) { double } + + let(:log_output) do + StringIO.new + end + + let(:logger) do + Logger.new(log_output) + end + + let(:template) { '' } + + describe '#percentage' do + include_context 'with a mocked template for Dragnet::Exporters::HTMLExporter' + + let(:template) do + <<~ERB + <%= percentage(0, 0) %> + <%= percentage(10, 0) %> + <%= percentage(0, 20) %> + <%= percentage(20, 100) %> + <%= percentage(9, 16) %> + <%= percentage(42, 26) %> + <%= percentage(6.555, 15) %> + ERB + end + + let(:expected_output) do + <<~TEXT + 0.0 + 0.0 + 0.0 + 20.0 + 56.25 + 161.54 + 43.7 + TEXT + end + + include_examples 'Dragnet::Exporters::HTMLExporter#export returns the expected output' + end + + describe '#software_branches' do + include_context 'with a mocked template for Dragnet::Exporters::HTMLExporter' + + let(:template) do + <<~ERB + <%= software_branches(repository).sort.join(', ') %> + ERB + end + + include_context 'with a test repository for Dragnet::Exporters::HTMLExporter' + + context 'when the current head is only in one branch' do + let(:expected_output) do + <<~TEXT + master + TEXT + end + + include_examples 'Dragnet::Exporters::HTMLExporter#export returns the expected output' + end + + context 'when the current head is in multiple branches' do + include_context 'with a mocked template for Dragnet::Exporters::HTMLExporter' + + let(:expected_output) do + <<~TEXT + basics, master + TEXT + end + + before { git.checkout('basics') } + + include_examples 'Dragnet::Exporters::HTMLExporter#export returns the expected output' + end + end + + describe '#test_records_by_requirement' do + include_context 'with a mocked template for Dragnet::Exporters::HTMLExporter' + + let(:test_records) do + [ + Dragnet::TestRecord.new( + id: 'ERS_REQ_4028', + name: 'John S.' + ), + Dragnet::TestRecord.new( + id: 'ERS_REQ_4488', + name: 'Alice P.' + ), + Dragnet::TestRecord.new( + id: 'ERS_REQ_4488', + name: 'Gregor J.' + ), + Dragnet::TestRecord.new( + id: 'ERS_REQ_2508', + name: 'Rick L.' + ), + Dragnet::TestRecord.new( + id: %w[ERS_REQ_4968 ESR_REQ_8481], + name: 'Natalie E.' + ), + Dragnet::TestRecord.new( + id: %w[ESR_REQ_2430 ERS_REQ_2508], + name: 'Andrea F.' + ) + ] + end + + let(:template) do + <<~ERB + <% test_records_by_requirement.sort.each do |req_id, test_records| %> + <%= req_id %> => <%= test_records.map(&:name).sort.join(' ') %> + <% end %> + ERB + end + + let(:expected_output) do + <<~TEXT + + ERS_REQ_2508 => Andrea F. Rick L. + + ERS_REQ_4028 => John S. + + ERS_REQ_4488 => Alice P. Gregor J. + + ERS_REQ_4968 => Natalie E. + + ESR_REQ_2430 => Andrea F. + + ESR_REQ_8481 => Natalie E. + + TEXT + end + + include_examples 'Dragnet::Exporters::HTMLExporter#export returns the expected output' + end + + describe '#review_status_badge' do + include_context 'with a mocked template for Dragnet::Exporters::HTMLExporter' + + let(:template) do + <<~ERB + <%= review_status_badge(test_records.first) %> + ERB + end + + context 'when the test record has no review status' do + let(:test_records) { [Dragnet::TestRecord.new({})] } + + let(:expected_output) do + <<~HTML + (unknown) + HTML + end + + include_examples 'Dragnet::Exporters::HTMLExporter#export returns the expected output' + end + + context 'when the test record has been reviewed' do + let(:test_records) do + [ + Dragnet::TestRecord.new( + reviewstatus: 'reviewed' + ) + ] + end + + let(:expected_output) do + <<~HTML + Reviewed + HTML + end + + include_examples 'Dragnet::Exporters::HTMLExporter#export returns the expected output' + end + + context "when the test record hasn't been reviewed" do + let(:test_records) do + [ + Dragnet::TestRecord.new( + reviewstatus: 'inReview' + ) + ] + end + + let(:expected_output) do + <<~HTML + Inreview + HTML + end + + include_examples 'Dragnet::Exporters::HTMLExporter#export returns the expected output' + end + end + + describe 'colors from verification results', requirements: ['DRAGNET_0024'] do + include_context 'with a mocked template for Dragnet::Exporters::HTMLExporter' + + let(:test_record) do + Dragnet::TestRecord.new({}).tap do |record| + record.verification_result = Dragnet::VerificationResult.new(status: status) + end + end + + let(:test_records) { [test_record] } + + describe '#verification_result_badge' do + let(:template) do + <<~ERB + <%= verification_result_badge(test_records.first.verification_result) %> + ERB + end + + context 'when the verification result is passed' do + let(:status) { :passed } + + let(:expected_output) do + <<~HTML + Passed + HTML + end + + include_examples 'Dragnet::Exporters::HTMLExporter#export returns the expected output' + end + + context 'when the verification result is skipped' do + let(:status) { :skipped } + + let(:expected_output) do + <<~HTML + Skipped + HTML + end + + include_examples 'Dragnet::Exporters::HTMLExporter#export returns the expected output' + end + + context 'when the verification result is failed' do + let(:status) { :failed } + + let(:expected_output) do + <<~HTML + Failed + HTML + end + + include_examples 'Dragnet::Exporters::HTMLExporter#export returns the expected output' + end + end + + describe '#card_color' do + let(:template) do + <<~ERB + <%= card_color(test_records.first.verification_result) %> + ERB + end + + context 'when the verification result is passed' do + let(:status) { :passed } + + let(:expected_output) do + <<~TEXT + green + TEXT + end + + include_examples 'Dragnet::Exporters::HTMLExporter#export returns the expected output' + end + + context 'when the verification result is skipped' do + let(:status) { :skipped } + + let(:expected_output) do + <<~TEXT + yellow + TEXT + end + + include_examples 'Dragnet::Exporters::HTMLExporter#export returns the expected output' + end + + context 'when the verification result is failed' do + let(:status) { :failed } + + let(:expected_output) do + <<~TEXT + red + TEXT + end + + include_examples 'Dragnet::Exporters::HTMLExporter#export returns the expected output' + end + end + end + + describe '#relative_to_repo' do + include_context 'with a mocked template for Dragnet::Exporters::HTMLExporter' + include_context 'with a test repository for Dragnet::Exporters::HTMLExporter' + + context "when the repository's path is absolute" do + let(:full_path) { temp_dir / 'hello_world.rb' } + + let(:template) do + <<~ERB + <%= relative_to_repo(Pathname.new('#{full_path}')) %> + ERB + end + + let(:expected_output) do + <<~TEXT + hello_world.rb + TEXT + end + + include_examples 'Dragnet::Exporters::HTMLExporter#export returns the expected output' + end + + context "when the repository's path is the current working directory" do + let(:repository) { Dragnet::Repository.new(path: Pathname.new('.')) } + let(:full_path) { './Test/Manual/cryptographic_functions.yaml' } + + let(:template) do + <<~ERB + <%= relative_to_repo(Pathname.new('#{full_path}')) %> + ERB + end + + let(:expected_output) do + <<~TEXT + Test/Manual/cryptographic_functions.yaml + TEXT + end + + include_examples 'Dragnet::Exporters::HTMLExporter#export returns the expected output' + end + end + + describe '#test_record_id_to_string' do + include_context 'with a mocked template for Dragnet::Exporters::HTMLExporter' + + let(:test_records) do + [ + Dragnet::TestRecord.new( + id: 'ERS_REQ_6583' + ), + Dragnet::TestRecord.new( + id: %w[ESR_REQ_1785 ERS_REQ_9846] + ), + Dragnet::TestRecord.new( + id: %w[ESR_REQ_7925] + ) + ] + end + + context 'when the ID of the TestRecord object is a String' do + let(:template) do + <<~ERB + <%= test_record_id_to_string(test_records.first) %> + ERB + end + + let(:expected_output) do + <<~TEXT + ERS_REQ_6583 + TEXT + end + + include_examples 'Dragnet::Exporters::HTMLExporter#export returns the expected output' + end + + context 'when the ID of the TestRecord object is an Array' do + let(:template) do + <<~ERB + <%= test_record_id_to_string(test_records.second) %> + ERB + end + + let(:expected_output) do + <<~TEXT + ESR_REQ_1785, ERS_REQ_9846 + TEXT + end + + include_examples 'Dragnet::Exporters::HTMLExporter#export returns the expected output' + end + + context 'when the ID of the TestRecord object is an single-element Array' do + let(:template) do + <<~ERB + <%= test_record_id_to_string(test_records.third) %> + ERB + end + + let(:expected_output) do + <<~TEXT + ESR_REQ_7925 + TEXT + end + + include_examples 'Dragnet::Exporters::HTMLExporter#export returns the expected output' + end + end + + describe 'report contents' do + include_context 'with a test repository for Dragnet::Exporters::HTMLExporter' + + let(:test_records) do + [ + Dragnet::TestRecord.new(sha1: '04aec23' ).tap do |test_record| + test_record.source_file = temp_dir / 'source' / 'tests' / 'manual' / 'safe_e2e.yaml' + test_record.verification_result = Dragnet::VerificationResult.new(status: :passed) + end, + Dragnet::TestRecord.new(sha1: 'f13dbbc' ).tap do |test_record| + test_record.source_file = temp_dir / 'source' / 'tests' / 'manual/io_vectors.yaml' + test_record.verification_result = Dragnet::VerificationResult.new( + status: :skipped, + reason: 'changes detected in the repository f13dbbc..6e94407' + ) + end, + Dragnet::TestRecord.new(sha1: '6e94407').tap do |test_record| + test_record.source_file = temp_dir / 'source' / 'tests' / 'manual' / 'signals.yaml' + test_record.verification_result = Dragnet::VerificationResult.new( + status: :failed, + reason: "result key has the value 'failed'" + ) + end + ] + end + + let(:errors) do + [ + { + file: temp_dir / 'source' / 'tests' / 'manual' / 'entry_points.yaml', + message: 'YAML Parsing Error', + exception: Exception.new('Unknown character on line 7') + }, + { + file: temp_dir / 'source' / 'tests' / 'manual' / 'watchdog.yaml', + message: 'Unable to read file', + exception: Exception.new('Permission Denied') + } + ] + end + + it 'does not include the full repository path' do + expect(output).not_to include(temp_dir.to_s) + end + + describe 'list of MTR files', requirements: ['DRAGNET_0023'] do + it 'lists the MTR files that were successfully loaded' do + expect(output).to include('source/tests/manual/safe_e2e.yaml') + .and include('source/tests/manual/io_vectors.yaml') + .and include('source/tests/manual/signals.yaml') + end + + it "lists the MTR files that couldn't be loaded" do + expect(output).to include('source/tests/manual/entry_points.yaml') + .and include('source/tests/manual/watchdog.yaml') + end + end + + it 'lists the reasons for the failure/skipping of the test records', requirements: ['DRAGNET_0025'] do + expect(output).to include('changes detected in the repository f13dbbc..6e94407') + .and include("result key has the value 'failed'") + end + end +end + diff --git a/spec/integration/dragnet/exporters/json_exporter_spec.rb b/spec/integration/dragnet/exporters/json_exporter_spec.rb new file mode 100644 index 0000000..1abd6bd --- /dev/null +++ b/spec/integration/dragnet/exporters/json_exporter_spec.rb @@ -0,0 +1,274 @@ +# frozen_string_literal: true + +require 'dragnet/exporters/json_exporter' + +RSpec.describe Dragnet::Exporters::JSONExporter do + subject(:json_exporter) do + described_class.new(test_records: test_records, errors: errors, repository: repository, logger: logger) + end + + let(:test_records) { [] } + let(:errors) { [] } + + let(:workspace) { Pathname.new(Dir.pwd) } + + let(:repository) do + Dragnet::MultiRepository.new(path: workspace) + end + + let(:log_output) { StringIO.new } + let(:logger) { Logger.new(log_output) } + + describe '#export' do + subject(:method_call) { json_exporter.export } + + let(:re_parsed_json) { JSON.parse(method_call) } + + shared_context 'with errors' do + let(:errors) do + [ + { + file: 'manual_verification/crypto/checksum_checker.yaml', + message: 'Referenced repository not found', + error: Errno::ENOENT.new('lib/crypto/difi') + } + ] + end + end + + shared_examples_for '#export' do + it 'returns a String' do + expect(method_call).to be_a(String) + end + + it 'produces parseable JSON', requirements: %w[DRAGNET_0060] do + expect { re_parsed_json }.not_to raise_error + end + end + + context 'when no TestRecords are given' do + let(:test_records) { [] } + + it_behaves_like '#export' + + shared_examples_for '#export when no TestRecords are given' do + it 'produces an empty array' do + expect(re_parsed_json).to be_an(Array).and be_empty + end + end + + context 'when errors are present', requirements: %w[DRAGNET_0063] do + include_context 'with errors' + + it_behaves_like '#export when no TestRecords are given' + + it 'does not include the validation errors' do + expect(method_call).not_to include('manual_verification/crypto/checksum_checker.yaml') + end + end + end + + context 'when test records are given' do + let(:test_records) do + [ + Dragnet::TestRecord.new( + id: 'ESR_REQ_9126', + result: 'passed', + sha1: 'c99204563e5337e48ab7b3689d8ec1b1a0f45cb7', + description: <<~TEXT + Use an oscilloscope to verify that pin 3 on the PD-3234 chip is high + when the cycle starts, goes low during the first 250ms of the cycle + and then switches between high and low every 333ms for the rest of + the cycle. + TEXT + ).tap do |test_record| + test_record.source_file = workspace / 'MTR' / 'PD_3234_voltage.yaml' + test_record.verification_result = Dragnet::VerificationResult.new( + status: :skipped, + reason: 'Changes detected in the repository: c99204563e..fc5aaddf52' + ).tap do |verification_result| + verification_result.started_at = Time.new(2024, 2, 27, 14, 36, 7, 'UTC') + verification_result.finished_at = Time.new(2024, 2, 27, 14, 36, 9, 'UTC') + end + end, + Dragnet::TestRecord.new( + id: %w[ESR_REQ_7817 ESR_REQ_3636], + sha1: '354aa24ffcc9c8baae28fec14eabd469169d87b2', + result: 'passed', + files: [ + workspace / 'lib' / 'cli' / 'master.cpp', + workspace / 'validators' / 'sha1_validator.cpp', + workspace / 'validators' / 'id_validator.cpp' + ], + name: 'Carl Sagan', + review_status: 'reviewed', + review_comments: 'Reviewed on 1970-01-01. No findings.' + ).tap do |test_record| + test_record.source_file = workspace / 'MTR' / 'validators.yaml' + test_record.verification_result = Dragnet::VerificationResult.new( + status: :passed + ).tap do |verification_result| + verification_result.started_at = Time.new(2024, 2, 27, 14, 21, 16, 'UTC') + verification_result.finished_at = Time.new(2024, 2, 27, 14, 22, 4, 'UTC') + end + end, + Dragnet::TestRecord.new( + id: 'ESR_REQ_7661', + name: 'Ada Lovelace', + result: 'failed', + repos: [ + Dragnet::Repo.new( + path: 'lib/crypto/diffie', + sha1: '5606bc61ab2560ecbc54ae1fe5272cdd8ad8a083', + files: %w[ + key_scheduling/key_scheduler.cpp + key_scheduling/key_scheduler.h + key_generator/generator.cpp + ] + ) + ], + findings: 'The key scheduler repeats a key when both cycles match (++p == pe)', + review_status: 'in-review' + ).tap do |test_record| + test_record.source_file = workspace / 'MTR' / 'crypto' / 'diffie.yaml' + test_record.verification_result = Dragnet::VerificationResult.new( + status: :failed, + reason: "'result' field has the status 'failed'" + ).tap do |verification_result| + verification_result.started_at = Time.new(2024, 2, 27, 14, 22, 4, 'UTC') + verification_result.finished_at = Time.new(2024, 2, 27, 14, 22, 11, 'UTC') + end + end + ] + end + + let(:expected_json) do + '['\ + '{' \ + '"refs":["ESR_REQ_9126"],' \ + '"result":"passed",' \ + '"review_status":"not_reviewed",' \ + '"verification_result":{' \ + '"status":"skipped",' \ + '"started_at":"2024-02-27 14:36:07 +0000",' \ + '"finished_at":"2024-02-27 14:36:09 +0000",' \ + '"runtime":2.0,' \ + '"reason":"Changes detected in the repository: c99204563e..fc5aaddf52"' \ + '},' \ + '"started_at":"2024-02-27 14:36:07 +0000",' \ + '"finished_at":"2024-02-27 14:36:09 +0000",' \ + '"sha1":"c99204563e5337e48ab7b3689d8ec1b1a0f45cb7",' \ + '"description":"Use an oscilloscope to verify that pin 3 on the PD-3234 chip is high\n'\ + 'when the cycle starts, goes low during the first 250ms of the cycle\n'\ + 'and then switches between high and low every 333ms for the rest of\n'\ + 'the cycle.\n",' \ + '"id":"2de4fadc0e37faff"' \ + '},'\ + '{' \ + '"refs":["ESR_REQ_7817","ESR_REQ_3636"],' \ + '"result":"passed",' \ + '"review_status":"reviewed",' \ + '"verification_result":{' \ + '"status":"passed",' \ + '"started_at":"2024-02-27 14:21:16 +0000",' \ + '"finished_at":"2024-02-27 14:22:04 +0000",' \ + '"runtime":48.0' \ + '},' \ + '"started_at":"2024-02-27 14:21:16 +0000",' \ + '"finished_at":"2024-02-27 14:22:04 +0000",' \ + '"sha1":"354aa24ffcc9c8baae28fec14eabd469169d87b2",' \ + '"owner":"Carl Sagan",' \ + '"review_comments":"Reviewed on 1970-01-01. No findings.",' \ + '"files":['\ + '"lib/cli/master.cpp",'\ + '"validators/sha1_validator.cpp",'\ + '"validators/id_validator.cpp"' \ + '],' \ + '"id":"02c3a37bb344f280"' \ + '},' \ + '{' \ + '"refs":["ESR_REQ_7661"],' \ + '"result":"failed",' \ + '"review_status":"not_reviewed",' \ + '"verification_result":{' \ + '"status":"failed",' \ + '"started_at":"2024-02-27 14:22:04 +0000",' \ + '"finished_at":"2024-02-27 14:22:11 +0000",' \ + '"runtime":7.0,' \ + '"reason":"\'result\' field has the status \'failed\'"' \ + '},' \ + '"started_at":"2024-02-27 14:22:04 +0000",' \ + '"finished_at":"2024-02-27 14:22:11 +0000",' \ + '"owner":"Ada Lovelace",' \ + '"findings":"The key scheduler repeats a key when both cycles match (++p == pe)",' \ + '"repos":[' \ + '{' \ + '"path":"lib/crypto/diffie",' \ + '"sha1":"5606bc61ab2560ecbc54ae1fe5272cdd8ad8a083",' \ + '"files":[' \ + '"key_scheduling/key_scheduler.cpp",' \ + '"key_scheduling/key_scheduler.h",' \ + '"key_generator/generator.cpp"' \ + ']' \ + '}' \ + '],' \ + '"id":"77ac686a8f4b46dd"' \ + '}' \ + ']' + end + + it_behaves_like '#export' + + shared_examples_for '#export when test records are given' do + let(:verification_results) do + re_parsed_json.map { |object| object['verification_result'] } + end + + it 'produces an array with an element for each Test Record object', requirements: %w[DRAGNET_0061] do + expect(re_parsed_json.size).to eq(test_records.size) + end + + it 'produces an array of Hashes', requirements: %w[DRAGNET_0061] do + expect(re_parsed_json).to all(be_a(Hash)) + end + + it 'produces the expected JSON' do + expect(method_call).to eq(expected_json) + end + + it 'includes all the MTRs', requirements: %w[DRAGNET_0061] do + ids = re_parsed_json.flat_map { |object| object['id'] } + expect(ids).to eq(%w[2de4fadc0e37faff 02c3a37bb344f280 77ac686a8f4b46dd]) + end + + it 'includes the Verification Result for each MTR', requirements: %w[DRAGNET_0062] do + expect(verification_results).to all(be_a(Hash)) + end + + it 'includes the start_at attribute in each Verification Result', requirements: %w[DRAGNET_0078] do + expect(verification_results).to all(have_key('started_at')) + end + + it 'includes the finished_at attribute in each Verification Result', requirements: %w[DRAGNET_0078] do + expect(verification_results).to all(have_key('finished_at')) + end + + it 'includes the runtime attribute in each Verification Result', requirements: %w[DRAGNET_0078] do + expect(verification_results).to all(have_key('runtime')) + end + end + + it_behaves_like '#export when test records are given' + + context 'when errors are present', requirements: %w[DRAGNET_0063] do + include_context 'with errors' + + it_behaves_like '#export when test records are given' + + it 'does not include the validation errors' do + expect(method_call).not_to include('Referenced repository not found') + end + end + end + end +end diff --git a/spec/integration/dragnet/exporters/test_files/repo.git b/spec/integration/dragnet/exporters/test_files/repo.git new file mode 100644 index 0000000000000000000000000000000000000000..2eecc304503ec4e4b273755d3b106c451a25340f GIT binary patch literal 1724 zcma)+Yh2Q26vzKy!}?E57F6mqDl?syAQz!YH=Cx+5Kw8}3KW8JDxyYS+C(S0v}Ts0 z!u(`9C9yZd zNI-KEW1^zDAdySP<1ro>HW}~1^}w-l7z~bx$3$`oSROZ$gJ<)IBqGn<9Uaf*iQM>H zc9h8NYqltX8xLaeY;L4GE(${=b0Xa_?om->0+)*?;3A1w9+871a|mPt8AtecDTgf* zM2bK#V22kK005}zd{ST~mRIUEpcaG7dQ4#nlP)@J^zW4%BatVE^ zP4b*`9a&!Y)$Wh&(Yo z^3aSF*~sv-wr?l_gc%PaZ0CUcMmpy`C^p7xtp(6i$P`~ivWK-kmy3zamlkKSvX$AH z-_xECmNR01cma>~4=Qg0gX-EY2V^_PY|Ydn^EQ}+!RxFt}N(MKWdKKiCJ?>hQ92*p|fJzL9U5qlkVj=b%= zlyyi~<@8xT+D6wt=OXc_N^7$%w8nGykZp>tJ5c$WntQP|r@_jkUV4&2u#z_T3JVbxX{AC-P|gP%UfC9p}0^ z`;s7>pVYerhARI1sV1lSoAOp|Em3_fV#R55c|pF|%*-laT(*d5P?-jA)jma`2^-PA z=kP2m#73Xy=2x3F2hqe+?alS|OPkUsm%m-JuVNkMpnMBrQawAsCnZl(REZa``|$-z z^^Tlm#+e4l+7&RnB|g%EIYXnsCPzugGJNqn2U#3(t73rq-Em{+XK}9b_&p4EeJZzW z8@Yplo2t$oRhi!oE%V=wyWt&L*?0M*@!T7>U!lV|w4X7(RFE~Dq9Ii*U#DaAzn}d( z)^8ubXFZR%KXxp?#?sI*w#Q77hqp^jIX+~oKDzBqrF%yG@QJp>XirNLr>fb~l~1sC zF&;kTJq&vRo+*OwZM_6nooxR>MAqw%5K?duEb?BBA`q8?RIq z{Zd_8^y!f+jqz&7>|3Q;`NzpUKvYW=Nuzow4AmM)I5HxzG zy!Q3ekmRy$fxpdguEZ&{OGhC-FJMVXuU6%9u^fjt{U%s?$L?Qsx|43*Zk@ijsJy*h z;V(0{d3wG~jfcz%8&U>;&J9d~V^J%kkQjbMm^%Ja%Xq7d@j!8pO$$@1uh;EohUlv9 z%uH;_pPUs9@D`|=`SJO#6Xu+0Rk^Dl=PshHcxIvLtC@jEngb)}pMEE>0%%TOVZfjz9s%8`wn6yYMFG;18ltpnz8kjMV@Y%c)(=52#E|IvvyaL3&{C z$mLNeU@>M9sxp-@gN?LK{cW0`t6}KLf8hd6?mx{hyDO0F5X f0tDT;Jnit##&mnHuQpzIsCcUybF+>@J&*kdKfWjN literal 0 HcmV?d00001 diff --git a/spec/shared/cli_master.rb b/spec/shared/cli_master.rb new file mode 100644 index 0000000..887065a --- /dev/null +++ b/spec/shared/cli_master.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +RSpec.shared_context "with the default CLI's --version output" do + let(:expected_output) do + <<~TEXT + Dragnet #{Dragnet::VERSION} + Copyright (c) #{Time.now.year} ESR Labs GmbH esrlabs.com + TEXT + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..c21fca7 --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +require "bundler/setup" +require 'pry' + +if ENV.fetch('COVERAGE', 'false') == 'true' + require 'simplecov' + SimpleCov.start do + add_filter "/spec/" + end +end + +require "dragnet" + +RSpec.configure do |config| + # Enable flags like --only-failures and --next-failure + config.example_status_persistence_file_path = ".rspec_status" + + # Disable RSpec exposing methods globally on `Module` and `main` + config.disable_monkey_patching! + + # Run the tests in random order to ensure no tests dependencies + config.order = :random + + config.expect_with :rspec do |c| + c.syntax = :expect + end +end