pinspec 0.2.0 → 0.3.0
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/CHANGELOG.md +128 -0
- data/README.md +24 -3
- data/lib/pinspec/analyzer/discovery.rb +162 -0
- data/lib/pinspec/analyzer/factory_registry.rb +13 -4
- data/lib/pinspec/analyzer/target_parser.rb +266 -33
- data/lib/pinspec/cli.rb +143 -22
- data/lib/pinspec/config.rb +13 -2
- data/lib/pinspec/emit/spec_writer.rb +26 -22
- data/lib/pinspec/errors.rb +0 -4
- data/lib/pinspec/inputs/boundary.rb +2 -3
- data/lib/pinspec/inputs/sample_runner.rb +16 -3
- data/lib/pinspec/inputs/sampler.rb +0 -32
- data/lib/pinspec/report/summary.rb +30 -0
- data/lib/pinspec/runner/capture.rb +3 -1
- data/lib/pinspec/runner/probe_generator.rb +4 -1
- data/lib/pinspec/runner/sandbox.rb +19 -9
- data/lib/pinspec/setup/context_builder.rb +10 -7
- data/lib/pinspec/types.rb +2 -55
- data/lib/pinspec/verify/verifier.rb +37 -2
- data/lib/pinspec/version.rb +1 -1
- data/templates/factory_build.rb +10 -11
- metadata +2 -2
- data/lib/pinspec/emit/namer.rb +0 -103
data/lib/pinspec/emit/namer.rb
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "json"
|
|
4
|
-
|
|
5
|
-
module Pinspec
|
|
6
|
-
module Emit
|
|
7
|
-
class Namer
|
|
8
|
-
MAX_DESCRIPTION = 120
|
|
9
|
-
|
|
10
|
-
Facts = Data.define(:case_id, :origin, :outcome, :method_name, :class_name, :parameters)
|
|
11
|
-
|
|
12
|
-
def initialize(target:, enabled: false, client: nil)
|
|
13
|
-
@target = target
|
|
14
|
-
@enabled = enabled
|
|
15
|
-
@client = client
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def enabled?
|
|
19
|
-
@enabled && !@client.nil?
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def describe(cases)
|
|
23
|
-
facts = cases.map { |input_case, observation| facts_for(input_case, observation) }
|
|
24
|
-
fallback = facts.to_h { |fact| [fact.case_id, deterministic(fact)] }
|
|
25
|
-
|
|
26
|
-
return fallback unless enabled?
|
|
27
|
-
|
|
28
|
-
improved = request(facts)
|
|
29
|
-
fallback.merge(sanitize(improved, fallback))
|
|
30
|
-
rescue StandardError
|
|
31
|
-
fallback
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def payload(facts)
|
|
35
|
-
{
|
|
36
|
-
"task" => "Describe each characterization test case in one short phrase.",
|
|
37
|
-
"constraints" => [
|
|
38
|
-
"Describe only the INPUTS and the kind of outcome.",
|
|
39
|
-
"Never invent or state a concrete expected value.",
|
|
40
|
-
"One phrase per case, at most #{MAX_DESCRIPTION} characters."
|
|
41
|
-
],
|
|
42
|
-
"cases" => facts.map do |fact|
|
|
43
|
-
{
|
|
44
|
-
"id" => fact.case_id,
|
|
45
|
-
"origin" => fact.origin.to_s,
|
|
46
|
-
"outcome_kind" => fact.outcome.to_s,
|
|
47
|
-
"method" => fact.method_name.to_s,
|
|
48
|
-
"class" => fact.class_name.to_s,
|
|
49
|
-
"parameter_names" => fact.parameters.map(&:to_s)
|
|
50
|
-
}
|
|
51
|
-
end
|
|
52
|
-
}
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
private
|
|
56
|
-
|
|
57
|
-
def facts_for(input_case, observation)
|
|
58
|
-
Facts.new(
|
|
59
|
-
case_id: input_case.id,
|
|
60
|
-
origin: input_case.origin,
|
|
61
|
-
outcome: observation["status"] == "raised" ? :raises : :returns,
|
|
62
|
-
method_name: @target.method_name,
|
|
63
|
-
class_name: @target.class_name,
|
|
64
|
-
parameters: @target.input_params.map(&:name)
|
|
65
|
-
)
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def deterministic(fact)
|
|
69
|
-
verb = fact.outcome == :raises ? "raises" : "returns the pinned value"
|
|
70
|
-
|
|
71
|
-
"#{fact.method_name} #{verb} (#{fact.case_id}, #{fact.origin})"
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
def request(facts)
|
|
75
|
-
response = @client.call(payload(facts))
|
|
76
|
-
|
|
77
|
-
parsed = response.is_a?(String) ? JSON.parse(response) : response
|
|
78
|
-
Array(parsed["cases"]).to_h { |entry| [entry["id"], entry["description"]] }
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def sanitize(improved, fallback)
|
|
82
|
-
improved.each_with_object({}) do |(case_id, description), out|
|
|
83
|
-
next unless fallback.key?(case_id)
|
|
84
|
-
next unless description.is_a?(String)
|
|
85
|
-
|
|
86
|
-
text = description.strip
|
|
87
|
-
next if text.empty? || text.length > MAX_DESCRIPTION
|
|
88
|
-
next if suspicious?(text)
|
|
89
|
-
|
|
90
|
-
out[case_id] = "#{text} (#{case_id})"
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
def suspicious?(text)
|
|
95
|
-
return true if text.match?(/=>|\{"t"|\bexpect\b|\beq\(/)
|
|
96
|
-
return true if text.match?(/\d{3,}/)
|
|
97
|
-
return true if text.count('"') > 2
|
|
98
|
-
|
|
99
|
-
false
|
|
100
|
-
end
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
end
|