png_conform 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +101 -80
- data/CONTRIBUTING.md +22 -0
- data/Gemfile +4 -0
- data/README.adoc +7 -0
- data/Rakefile +8 -1
- data/TODO.structured-diagnostics/00-overview.md +98 -0
- data/TODO.structured-diagnostics/01-shared-contract.md +36 -0
- data/TODO.structured-diagnostics/02-requirement-catalog.md +37 -0
- data/TODO.structured-diagnostics/03a-png-apng-emitters.md +45 -0
- data/TODO.structured-diagnostics/03b-mng-jng-emitters.md +34 -0
- data/TODO.structured-diagnostics/03c-format-aware-orchestration.md +38 -0
- data/TODO.structured-diagnostics/04-report-migration.md +40 -0
- data/TODO.structured-diagnostics/05-corpus-goldens.md +42 -0
- data/TODO.structured-diagnostics/90-progress.md +22 -0
- data/benchmarks/lib/benchmark_runner.rb +1 -1
- data/benchmarks/lib/metrics_collector.rb +3 -3
- data/benchmarks/lib/report_generator.rb +8 -9
- data/config/diagnostics.yml +2906 -0
- data/docs/ARCHITECTURE.adoc +13 -4
- data/docs/CLI_OPTIONS.adoc +126 -0
- data/lib/png_conform/analyzers/comparison_analyzer.rb +5 -5
- data/lib/png_conform/analyzers/optimization_analyzer.rb +6 -6
- data/lib/png_conform/bindata/chunk_structure.rb +8 -1
- data/lib/png_conform/cli.rb +0 -7
- data/lib/png_conform/commands/check_command.rb +3 -2
- data/lib/png_conform/diagnostics/builder.rb +52 -0
- data/lib/png_conform/diagnostics/catalog.rb +242 -0
- data/lib/png_conform/diagnostics/golden_generator.rb +92 -0
- data/lib/png_conform/diagnostics/location.rb +45 -0
- data/lib/png_conform/models/chunk_info.rb +1 -1
- data/lib/png_conform/models/file_analysis.rb +2 -0
- data/lib/png_conform/models/validation_error.rb +96 -1
- data/lib/png_conform/models/validation_result.rb +20 -2
- data/lib/png_conform/readers/chunk_framing.rb +79 -0
- data/lib/png_conform/readers/format_dispatch.rb +49 -0
- data/lib/png_conform/readers/full_load_reader.rb +51 -1
- data/lib/png_conform/readers/streaming_reader.rb +25 -5
- data/lib/png_conform/reporters/summary_reporter.rb +1 -1
- data/lib/png_conform/reporters/verbose_reporter.rb +3 -1
- data/lib/png_conform/services/chunk_processor.rb +11 -11
- data/lib/png_conform/services/file_signature.rb +2 -2
- data/lib/png_conform/services/profile_manager.rb +77 -28
- data/lib/png_conform/services/result_builder.rb +9 -14
- data/lib/png_conform/services/validation_orchestrator.rb +175 -49
- data/lib/png_conform/services/zlib_validator.rb +2 -2
- data/lib/png_conform/validators/ancillary/bkgd_validator.rb +12 -12
- data/lib/png_conform/validators/ancillary/chrm_validator.rb +10 -10
- data/lib/png_conform/validators/ancillary/cicp_validator.rb +15 -9
- data/lib/png_conform/validators/ancillary/gama_validator.rb +10 -10
- data/lib/png_conform/validators/ancillary/hist_validator.rb +17 -17
- data/lib/png_conform/validators/ancillary/iccp_validator.rb +27 -27
- data/lib/png_conform/validators/ancillary/idot_validator.rb +5 -5
- data/lib/png_conform/validators/ancillary/itxt_validator.rb +24 -24
- data/lib/png_conform/validators/ancillary/mdcv_validator.rb +15 -7
- data/lib/png_conform/validators/ancillary/offs_validator.rb +10 -10
- data/lib/png_conform/validators/ancillary/pcal_validator.rb +28 -28
- data/lib/png_conform/validators/ancillary/phys_validator.rb +8 -8
- data/lib/png_conform/validators/ancillary/sbit_validator.rb +13 -13
- data/lib/png_conform/validators/ancillary/scal_validator.rb +13 -13
- data/lib/png_conform/validators/ancillary/splt_validator.rb +21 -21
- data/lib/png_conform/validators/ancillary/srgb_validator.rb +9 -9
- data/lib/png_conform/validators/ancillary/ster_validator.rb +9 -9
- data/lib/png_conform/validators/ancillary/text_validator.rb +12 -12
- data/lib/png_conform/validators/ancillary/time_validator.rb +11 -11
- data/lib/png_conform/validators/ancillary/trns_validator.rb +15 -15
- data/lib/png_conform/validators/ancillary/ztxt_validator.rb +16 -16
- data/lib/png_conform/validators/apng/actl_validator.rb +5 -5
- data/lib/png_conform/validators/apng/fctl_validator.rb +13 -11
- data/lib/png_conform/validators/apng/fdat_validator.rb +9 -9
- data/lib/png_conform/validators/base_validator.rb +72 -39
- data/lib/png_conform/validators/critical/idat_validator.rb +7 -4
- data/lib/png_conform/validators/critical/iend_validator.rb +8 -5
- data/lib/png_conform/validators/critical/ihdr_validator.rb +18 -18
- data/lib/png_conform/validators/critical/plte_validator.rb +10 -10
- data/lib/png_conform/validators/jng/jdat_validator.rb +5 -5
- data/lib/png_conform/validators/jng/jhdr_validator.rb +10 -10
- data/lib/png_conform/validators/jng/jsep_validator.rb +7 -7
- data/lib/png_conform/validators/mng/back_validator.rb +7 -13
- data/lib/png_conform/validators/mng/clip_validator.rb +5 -7
- data/lib/png_conform/validators/mng/clon_validator.rb +4 -6
- data/lib/png_conform/validators/mng/defi_validator.rb +9 -15
- data/lib/png_conform/validators/mng/dhdr_validator.rb +11 -17
- data/lib/png_conform/validators/mng/disc_validator.rb +5 -7
- data/lib/png_conform/validators/mng/endl_validator.rb +8 -10
- data/lib/png_conform/validators/mng/fram_validator.rb +5 -7
- data/lib/png_conform/validators/mng/loop_validator.rb +5 -9
- data/lib/png_conform/validators/mng/mend_validator.rb +3 -3
- data/lib/png_conform/validators/mng/mhdr_validator.rb +4 -4
- data/lib/png_conform/validators/mng/move_validator.rb +5 -7
- data/lib/png_conform/validators/mng/save_validator.rb +4 -4
- data/lib/png_conform/validators/mng/seek_validator.rb +5 -5
- data/lib/png_conform/validators/mng/show_validator.rb +4 -6
- data/lib/png_conform/validators/mng/term_validator.rb +8 -14
- data/lib/png_conform/version.rb +1 -1
- data/lib/png_conform.rb +44 -0
- data/script/generate_mng_jng_fixtures +90 -0
- data/script/regenerate_diagnostic_goldens +9 -0
- metadata +37 -5
- data/png_conform.gemspec +0 -44
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# 03c — Make orchestration format-aware
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Route complete PNG, MNG, and JNG files through their own signatures and top-level sequence requirements so valid non-PNG inputs do not receive false PNG diagnostics.
|
|
6
|
+
|
|
7
|
+
## Work
|
|
8
|
+
|
|
9
|
+
- Give the active reader/orchestrator path one exact signature-to-format dispatch table for PNG (`89 50 4e 47 0d 0a 1a 0a`), MNG (`8a 4d 4e 47 0d 0a 1a 0a`), and JNG (`8b 4a 4e 47 0d 0a 1a 0a`). Preserve the detected format in validation context/result construction; an unknown signature emits its own cataloged signature diagnostic and does not trigger an arbitrary format's required-chunk findings.
|
|
10
|
+
- Refactor `lib/png_conform/services/validation_orchestrator.rb` to dispatch top-level rules by detected format: PNG/APNG requires first `IHDR`, last `IEND`, and at least one `IDAT`; MNG requires first `MHDR` and last `MEND`; JNG requires first `JHDR`, last `IEND`, and at least one `JDAT`. Check actual first/last positions as well as presence, and emit the card 02 catalog IDs and format-specific citations through the canonical constructor.
|
|
11
|
+
- Make `lib/png_conform/readers/streaming_reader.rb` recognize all three signatures and stop at the detected format's outer terminator (`IEND` for PNG/JNG, `MEND` for MNG), rather than rejecting or truncating an otherwise valid MNG/JNG stream. Keep `FullLoadReader` behavior covered so path-based validation continues to parse all three generic chunk streams.
|
|
12
|
+
- Extend `spec/png_conform/services/validation_orchestrator_spec.rb` for each recognized and unknown signature, each format's missing/misplaced header and terminator, PNG's missing `IDAT`, JNG's missing `JDAT`, and the absence of irrelevant cross-format findings.
|
|
13
|
+
- Add proposed `spec/png_conform/readers/format_dispatch_spec.rb`, `spec/integration/mng_validation_spec.rb`, and `spec/integration/jng_validation_spec.rb`. Build minimal complete files with valid CRCs in the focused specs; prove the public full-file path accepts valid `MHDR`/`MEND` and `JHDR`/`JDAT`/`IEND` streams with an empty diagnostic set. Keep `spec/integration/png_validation_spec.rb` as the PNG behavior-preservation proof.
|
|
14
|
+
|
|
15
|
+
## Dependencies
|
|
16
|
+
|
|
17
|
+
- Cards 01, 02, 03a, and 03b. This card owns `ValidationOrchestrator` and the reader format-dispatch specs after the shared diagnostic constructor and format validators are available.
|
|
18
|
+
- Card 04 consumes the detected format and canonical top-level findings; card 05 consumes the full-file MNG/JNG integration path for goldens.
|
|
19
|
+
|
|
20
|
+
## Done when
|
|
21
|
+
|
|
22
|
+
- Exact PNG, MNG, and JNG signatures select the correct format, while an unknown signature yields a cataloged signature diagnostic without unrelated PNG/MNG/JNG missing-chunk findings.
|
|
23
|
+
- Valid minimal PNG, MNG, and JNG files pass through the public full-file validation path with no diagnostics and the correct reported format.
|
|
24
|
+
- Missing or misplaced PNG `IHDR`/`IEND`/`IDAT`, MNG `MHDR`/`MEND`, and JNG `JHDR`/`IEND`/`JDAT` produce only the applicable stable IDs, citations, severities, and chunk locations.
|
|
25
|
+
- Streaming validation recognizes all three signatures, reads through the applicable outer terminator, and does not stop at an embedded MNG `IEND` before `MEND`.
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
bundle exec rspec spec/png_conform/services/validation_orchestrator_spec.rb \
|
|
29
|
+
spec/png_conform/readers/format_dispatch_spec.rb \
|
|
30
|
+
spec/integration/png_validation_spec.rb \
|
|
31
|
+
spec/integration/mng_validation_spec.rb \
|
|
32
|
+
spec/integration/jng_validation_spec.rb
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Status
|
|
36
|
+
|
|
37
|
+
State: done
|
|
38
|
+
PR: https://github.com/claricle/png_conform/pull/18
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# 04 — Unify Ruby, JSON, YAML, and text reports
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Make the canonical diagnostic the only source for public machine and human output while adding it to existing report shapes with compatibility aliases for one documented transition.
|
|
6
|
+
|
|
7
|
+
## Work
|
|
8
|
+
|
|
9
|
+
- Update `PngConform::Models::ValidationResult` and `FileAnalysis#to_h` to expose the shared diagnostic projection without rebuilding or discarding fields. Add the upstream schema version at the contract-defined report location.
|
|
10
|
+
- Update `JsonReporter` and `YamlReporter` to serialize that projection with stable diagnostic ordering and explicit absent-field policy. Normalize or omit volatile timestamps and host-specific paths as prescribed by the shared contract.
|
|
11
|
+
- Update `TextReporter`, `SummaryReporter`, `VerboseReporter`, `VeryVerboseReporter`, `QuietReporter`, and `ColorReporter` to call the diagnostic’s human renderer, with reporter-specific filtering/color outside the diagnostic model.
|
|
12
|
+
- Preserve check-command exit behavior: error-severity diagnostics make a result invalid; warnings/info do not. Keep missing-file and unexpected-process failures on the operational error path.
|
|
13
|
+
- Preserve the existing Ruby readers `severity`, `message`, `chunk_type`, `chunk_offset`, `error_type`, `expected`, and `actual` as compatibility aliases for one documented transition.
|
|
14
|
+
- Preserve the JSON fields actually emitted by `FileAnalysis#to_h` today: `severity` and `message`, with optional `chunk_type`, `expected`, and `actual`. Add the canonical diagnostic projection without removing or repurposing those fields. Treat any flattened `chunk_offset` or `error_type` JSON fields as deliberate new additive projections—not legacy keys—and document and pin their exact placement if they are introduced in addition to the canonical location/kind fields.
|
|
15
|
+
- Update `README.adoc`, `docs/CLI_OPTIONS.adoc`, and `docs/ARCHITECTURE.adoc` with the schema/version, a structured example, location/citation semantics, and migration notes.
|
|
16
|
+
|
|
17
|
+
## Dependencies
|
|
18
|
+
|
|
19
|
+
- Cards 01 and 03a–03c.
|
|
20
|
+
|
|
21
|
+
## Done when
|
|
22
|
+
|
|
23
|
+
- Ruby API, JSON, and YAML expose the same diagnostic identity, severity, kind, citation, location, message, and context with JSON-safe values.
|
|
24
|
+
- Focused model/reporter specs preserve every existing Ruby reader and the current five-field legacy JSON projection, and explicitly assert any newly added flattened `chunk_offset` or `error_type` projection as additive.
|
|
25
|
+
- Text-family reporters render from the same object and preserve their documented filtering/color responsibilities.
|
|
26
|
+
- Error/warning validity and CLI exit status remain covered, including operational failures that are not conformance diagnostics.
|
|
27
|
+
- The documented examples match executable reporter output, identify every compatibility alias, define the transition boundary, and state the schema version.
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
bundle exec rspec spec/png_conform/models/validation_error_spec.rb \
|
|
31
|
+
spec/png_conform/models/validation_result_spec.rb \
|
|
32
|
+
spec/png_conform/models/file_analysis_spec.rb \
|
|
33
|
+
spec/png_conform/reporters \
|
|
34
|
+
spec/png_conform/commands/check_command_spec.rb
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Status
|
|
38
|
+
|
|
39
|
+
State: done
|
|
40
|
+
PR: https://github.com/claricle/png_conform/pull/19
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# 05 — Pin corpus JSON and the release gate
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
|
|
5
|
+
Make the one-time schema transition reviewable and ensure future rule/report changes cannot silently alter diagnostics across the fixture corpus.
|
|
6
|
+
|
|
7
|
+
## Work
|
|
8
|
+
|
|
9
|
+
- Add `script/regenerate_diagnostic_goldens` with explicit `--write` and non-mutating `--check` modes. Process fixtures in bytewise sorted repo-relative order and reject unknown options or a dirty/partial target set.
|
|
10
|
+
- Mirror all 180 PNG inputs under `spec/fixtures/diagnostics/pngsuite/` as canonical pretty JSON. Normalize input names to repo-relative paths and follow LensCore's timestamp/optional-field policy so repeated generation is byte-identical.
|
|
11
|
+
- Add a small redistributable fixture set under the proposed `spec/fixtures/mng/` and `spec/fixtures/jng/` paths, with source, license, and expected-validity metadata recorded beside the fixtures. Include representative valid and invalid MNG/JNG structures that exercise their format-specific citations.
|
|
12
|
+
- Mirror the MNG/JNG inputs under proposed `spec/fixtures/diagnostics/mng/` and `spec/fixtures/diagnostics/jng/` paths, and add proposed `spec/structured_diagnostics/corpus_spec.rb` to assert one-to-one cross-format input/golden coverage, parseability, schema version, deterministic ordering, and exact output equality. Include valid files with empty findings and invalid/edge files, using card 03c's format-aware full-file path rather than bypassing orchestration.
|
|
13
|
+
- Perform exactly one intentional `--write` regeneration after cards 01, 02, 03a–03c, and 04 have `State: done` and the shared schema, format dispatch, and rendering policy are frozen. Then review the complete artifact diff once as a dedicated transition step; subsequent CI uses `--check` and never rewrites files.
|
|
14
|
+
- Add the check to the existing Rake/CI path only after its runtime and memory usage are measured. Keep a targeted representative fixture subset for fast local development if the full corpus is too slow, but do not weaken the full CI acceptance gate.
|
|
15
|
+
- Document regeneration and review procedure in `CONTRIBUTING.md`; update fixture counts only through the coverage assertion, not a hand-maintained magic number.
|
|
16
|
+
|
|
17
|
+
## Dependencies
|
|
18
|
+
|
|
19
|
+
- Cards 01–04, including card 03c's full-file format dispatch, and a frozen shared schema/ordering policy.
|
|
20
|
+
- Suitable redistributable MNG/JNG samples and recorded license/provenance; the current checked-in corpus contains 180 PNG fixtures and no MNG/JNG fixtures.
|
|
21
|
+
|
|
22
|
+
## Done when
|
|
23
|
+
|
|
24
|
+
- Every checked-in PNG fixture and every newly licensed MNG/JNG fixture has exactly one deterministic structured JSON golden, including valid fixtures with no findings.
|
|
25
|
+
- The MNG/JNG fixture metadata records a redistribution-compatible license, source, format, and expected validity, and the set exercises both format-specific diagnostic citations.
|
|
26
|
+
- `--check` detects missing, extra, stale, reordered, schema-incompatible, or host-dependent golden output without writing files.
|
|
27
|
+
- The one-time transition regeneration is isolated for human review, and later CI proves no unreviewed drift.
|
|
28
|
+
- Contributor documentation explains targeted checks, full-corpus verification, and the controlled regeneration command.
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
bundle exec rspec spec/integration/png_validation_spec.rb \
|
|
32
|
+
spec/integration/mng_validation_spec.rb \
|
|
33
|
+
spec/integration/jng_validation_spec.rb
|
|
34
|
+
script/regenerate_diagnostic_goldens --check
|
|
35
|
+
bundle exec rspec spec/structured_diagnostics/corpus_spec.rb
|
|
36
|
+
bundle exec rubocop
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Status
|
|
40
|
+
|
|
41
|
+
State: done
|
|
42
|
+
PR: https://github.com/claricle/png_conform/pull/12
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Progress and handoff
|
|
2
|
+
|
|
3
|
+
## Current state
|
|
4
|
+
|
|
5
|
+
- Cards 01–05 are `done`. The structured diagnostics format from claricle/png_conform#9 is adopted end to end.
|
|
6
|
+
- Reports are built on the shared LensCore contract, with the requirement catalog, format-aware orchestration (PNG/MNG/JNG) and canonical report output in place.
|
|
7
|
+
- The corpus has one golden per checked-in fixture under `spec/fixtures/diagnostics/{pngsuite,idot,mng,jng}/`. Each golden is `ValidationResult#to_lens_report(filename: ...).to_h`, with every emitted diagnostic kept and no timestamp.
|
|
8
|
+
- `script/regenerate_diagnostic_goldens` has `--write` and `--check` modes. `bundle exec rake diagnostics:check` runs `--check` and is part of the default `rake` task (spec, rubocop, check), so CI catches drift.
|
|
9
|
+
- `spec/structured_diagnostics/corpus_spec.rb` asserts one-to-one fixture/golden coverage and exact output equality.
|
|
10
|
+
- `CONTRIBUTING.md` documents targeted checks, full-corpus verification and the controlled `--write` regeneration and review steps.
|
|
11
|
+
|
|
12
|
+
## Next executable action
|
|
13
|
+
|
|
14
|
+
None for this effort. Regenerate goldens with `--write` only for an intended rule, report or schema change, review the full golden diff, then confirm with `bundle exec rake diagnostics:check`.
|
|
15
|
+
|
|
16
|
+
## Blockers
|
|
17
|
+
|
|
18
|
+
None.
|
|
19
|
+
|
|
20
|
+
## Remaining gaps and risks
|
|
21
|
+
|
|
22
|
+
- Dormant sources (`Services::ZlibValidator`, `Validators::StreamingIdatValidator`, `lib/png_conform/pipelines/`) remain excluded from the catalog unless a public contract is documented for them.
|
|
@@ -165,7 +165,7 @@ class BenchmarkRunner
|
|
|
165
165
|
pct = (current.to_f / total * 100).round(1)
|
|
166
166
|
bar_width = 40
|
|
167
167
|
filled = (bar_width * current / total).to_i
|
|
168
|
-
bar = "=" * filled + " " * (bar_width - filled)
|
|
168
|
+
bar = ("=" * filled) + (" " * (bar_width - filled))
|
|
169
169
|
|
|
170
170
|
print "\r [#{bar}] #{pct}% (#{current}/#{total}) #{label} "
|
|
171
171
|
$stdout.flush
|
|
@@ -46,8 +46,8 @@ class MetricsCollector
|
|
|
46
46
|
tool_runs = runs_for_tool(tool)
|
|
47
47
|
return nil if tool_runs.empty?
|
|
48
48
|
|
|
49
|
-
execution_times = tool_runs.
|
|
50
|
-
memory_values = tool_runs.
|
|
49
|
+
execution_times = tool_runs.filter_map { |r| r[:execution_time] }
|
|
50
|
+
memory_values = tool_runs.filter_map { |r| r[:peak_memory] }
|
|
51
51
|
|
|
52
52
|
{
|
|
53
53
|
tool: tool,
|
|
@@ -118,7 +118,7 @@ class MetricsCollector
|
|
|
118
118
|
total_runs: @runs.size,
|
|
119
119
|
tools: tools,
|
|
120
120
|
files_tested: @runs.map { |r| r[:file] }.uniq.size,
|
|
121
|
-
tool_statistics: tools.
|
|
121
|
+
tool_statistics: tools.filter_map { |tool| calculate_statistics(tool) },
|
|
122
122
|
}
|
|
123
123
|
end
|
|
124
124
|
|
|
@@ -42,9 +42,9 @@ class ReportGenerator
|
|
|
42
42
|
return "No benchmark data available.\n" if tools.empty?
|
|
43
43
|
|
|
44
44
|
output = []
|
|
45
|
-
output << "=" * 80
|
|
45
|
+
output << ("=" * 80)
|
|
46
46
|
output << "PNG Validation Tool Benchmark Comparison"
|
|
47
|
-
output << "=" * 80
|
|
47
|
+
output << ("=" * 80)
|
|
48
48
|
output << ""
|
|
49
49
|
output << "Configuration:"
|
|
50
50
|
output << " Files tested: #{summary[:files_tested]} PNG files"
|
|
@@ -62,9 +62,9 @@ class ReportGenerator
|
|
|
62
62
|
# Performance comparison (if we have 2 tools)
|
|
63
63
|
if tools.size == 2
|
|
64
64
|
comparison = metrics_collector.compare_tools(tools[0], tools[1])
|
|
65
|
-
output << "-" * 80
|
|
65
|
+
output << ("-" * 80)
|
|
66
66
|
output << "PERFORMANCE SUMMARY"
|
|
67
|
-
output << "-" * 80
|
|
67
|
+
output << ("-" * 80)
|
|
68
68
|
output << ""
|
|
69
69
|
output << format_comparison_table(comparison)
|
|
70
70
|
output << ""
|
|
@@ -73,9 +73,9 @@ class ReportGenerator
|
|
|
73
73
|
end
|
|
74
74
|
|
|
75
75
|
# Detailed statistics per tool
|
|
76
|
-
output << "-" * 80
|
|
76
|
+
output << ("-" * 80)
|
|
77
77
|
output << "DETAILED STATISTICS"
|
|
78
|
-
output << "-" * 80
|
|
78
|
+
output << ("-" * 80)
|
|
79
79
|
output << ""
|
|
80
80
|
|
|
81
81
|
tools.each do |tool|
|
|
@@ -176,9 +176,8 @@ class ReportGenerator
|
|
|
176
176
|
# Format comparison table for text output.
|
|
177
177
|
def format_comparison_table(comparison)
|
|
178
178
|
lines = []
|
|
179
|
-
lines <<
|
|
180
|
-
|
|
181
|
-
lines << "-" * 80
|
|
179
|
+
lines << "Tool Avg Time Files/sec Peak Memory Winner"
|
|
180
|
+
lines << ("-" * 80)
|
|
182
181
|
|
|
183
182
|
[comparison[:tool1], comparison[:tool2]].each do |tool|
|
|
184
183
|
stats = comparison[:stats][tool]
|