Module: Restless::Conformance
- Defined in:
- lib/restless/conformance.rb
Overview
The shared operation table behind the conformance driver.
Both exe/restless-conformance (the stdio driver the cross-language
harness drives) and test/test_vectors.rb (the in-process replay) go
through this one file, so it is impossible for the vectors to describe
behaviour the driver does not exhibit.
See sdk/node/spec/driver/PROTOCOL.md. Internal: never part of the public API, never shipped behaviour a customer depends on.
Defined Under Namespace
Classes: UnknownOp, UnsupportedDialect
Class Method Summary collapse
-
.debug_injection(input) ⇒ Object
The observable surface only: the headers, and the
debugobject the adapter would merge (nil when there is nothing to merge). - .dispatch(op, input) ⇒ Object
- .fingerprint(input) ⇒ Object
- .hash(value) ⇒ Object
- .int(value) ⇒ Object
- .stack_text(raw) ⇒ Object
-
.str(value) ⇒ Object
--- input coercion ----------------------------------------------------- The protocol represents absence as JSON null.
- .str_or_nil(value) ⇒ Object
- .strs(value) ⇒ Object
-
.v8_dialect?(stack) ⇒ Boolean
A v8 frame is
at fn (/file.js:12:34).
Class Method Details
.debug_injection(input) ⇒ Object
The observable surface only: the headers, and the debug object the
adapter would merge (nil when there is nothing to merge).
96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/restless/conformance.rb', line 96 def debug_injection(input) built = Injection.build( status: input["status"].to_i, request_id: str(input["requestId"]), prefix: str_or_nil(input["prefix"]), recovery: str_or_nil(input["recovery"]), method: str_or_nil(input["method"]), path: str_or_nil(input["path"]), portal_url: str_or_nil(input["portalUrl"]) ) { "headers" => built[:headers], "debug" => built[:debug] } end |
.dispatch(op, input) ⇒ Object
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/restless/conformance.rb', line 31 def dispatch(op, input) input ||= {} case op # --- masking (section 3) --- when "mask" Mask.mask(str_or_nil(input["apiKey"])) # --- redaction (section 4) --- when "redactValue" Redact.redact_value(str(input["value"])) when "redactHeaders" Redact.redact_headers(hash(input["headers"]), strs(input["extra"])) when "redactUrl" Redact.redact_url(str(input["url"]), strs(input["extra"])) when "redactBody" body = str_or_nil(input["body"]) # An empty string is a VALUE here, distinct from an absent body, so # this is deliberately not collapsed to nil. body.nil? ? nil : Redact.redact_body(body, str_or_nil(input["contentType"]), strs(input["extra"])) when "truncateBody" body = str_or_nil(input["body"]) body.nil? ? nil : Redact.truncate_body(body, int(input["maxBytes"])) # --- fingerprinting (section 5) --- when "fingerprint" fingerprint(input) when "normalizeRoute" Fingerprint.normalize_route(str_or_nil(input["route"])) when "normalizeMessage" Fingerprint.(str(input["message"])) when "projectRelative" # FP-042 is shared across every SDK even though frame PARSING is not # (FP-044/FP-046), so path normalization gets its own dialect-free op. Fingerprint.project_relative(str(input["file"])) # --- request ids (section 6) --- when "formatRequestId" RequestId.format_request_id(str(input["rawId"]), str_or_nil(input["prefix"])) when "stripRequestIdPrefix" RequestId.strip_request_id_prefix(str(input["requestId"])) when "requestIdHeaders" RequestId.response_headers( str(input["ourId"]), hash(input["incomingHeaders"]), str_or_nil(input["prefix"]), input.key?("hasApiKey") ? input["hasApiKey"] == true : true ) # --- injection (section 10) --- when "recoverySlug" Injection.recovery_slug(str_or_nil(input["method"]), str_or_nil(input["path"])) when "debugInjection" debug_injection(input) # --- HAR (section 7) --- when "harEntry" Har.to_har_entry(hash(input["captured"])) else raise UnknownOp, "unknown op: #{op}" end end |
.fingerprint(input) ⇒ Object
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/restless/conformance.rb', line 109 def fingerprint(input) stack = stack_text(input["stackTrace"]) if !stack.empty? && v8_dialect?(stack) raise UnsupportedDialect, "unsupported stack dialect: v8 (this SDK parses Ruby backtraces; FP-044/FP-046)" end # Parse the stack the way the Rack adapter does. This used to pass # nil, which made the driver structurally incapable of reaching the # stack strategy: the whole path was dead through the harness while # the SDK's own tests, which call StackFrames directly, still passed. # Nothing caught it, because every v8-shaped stack vector is skipped # under FP-046 so the harness never exercises this branch. A driver # that short-circuits the SDK is testing itself. result = Fingerprint.compute( status: int(input["status"]), method: str_or_nil(input["method"]), route: str_or_nil(input["route"]), response_headers: input["responseHeaders"].is_a?(Hash) ? input["responseHeaders"] : nil, response_body: input["responseBody"], stack_frame: stack.empty? ? nil : StackFrames.top_user_frame(stack.split("\n")) ) # FP-003: `reason` is human-facing prose, explicitly not contract # surface, so drivers must not emit it. { "strategy" => result.strategy, "key" => result.key } end |
.hash(value) ⇒ Object
168 169 170 |
# File 'lib/restless/conformance.rb', line 168 def hash(value) value.is_a?(Hash) ? value : {} end |
.int(value) ⇒ Object
172 173 174 175 176 177 178 179 |
# File 'lib/restless/conformance.rb', line 172 def int(value) case value when Integer then value when Float then value.to_i when String then value.to_i else 0 end end |
.stack_text(raw) ⇒ Object
136 137 138 139 140 141 142 |
# File 'lib/restless/conformance.rb', line 136 def stack_text(raw) case raw when String then raw when Array then raw.map(&:to_s).join("\n") else "" end end |
.str(value) ⇒ Object
--- input coercion ----------------------------------------------------- The protocol represents absence as JSON null.
154 155 156 |
# File 'lib/restless/conformance.rb', line 154 def str(value) value.is_a?(String) ? value : "" end |
.str_or_nil(value) ⇒ Object
158 159 160 |
# File 'lib/restless/conformance.rb', line 158 def str_or_nil(value) value.is_a?(String) ? value : nil end |
.strs(value) ⇒ Object
162 163 164 165 166 |
# File 'lib/restless/conformance.rb', line 162 def strs(value) return [] unless value.is_a?(Array) value.select { |v| v.is_a?(String) } end |
.v8_dialect?(stack) ⇒ Boolean
A v8 frame is at fn (/file.js:12:34). Ruby backtraces are
/file.rb:12:in 'fn', so anything shaped like the former is out of
dialect and the driver says so rather than guessing.
147 148 149 |
# File 'lib/restless/conformance.rb', line 147 def v8_dialect?(stack) stack.split("\n").any? { |line| line.strip.start_with?("at ") } end |