ace-support-test-helpers 0.14.3 → 0.14.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
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f964e2cbd1eb428c260e5190ddaefbef7905d1ee86e894cbcab9a2d2b985b628
|
|
4
|
+
data.tar.gz: 6b8e0b1f8c3e0e88638d99b8d4abaea0a8378262bbae3c3784ae519d5859ecc2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8da847ee96be275ce048c97e55d3a0c6c659c2bf73ac472fbf4001fd3ca6eabc907658a2d2c333843f65dc059bb69b87cdec2ed1afa4965a8608ba4ccad5e174
|
|
7
|
+
data.tar.gz: 6f5b8c776f80d9a799e06c64cc0238cefc346fec2f98715e92767369f56e2222a24dc84c4ff1070dc210ba54b09f3244f751de978ef695b4839604a4ca3a276b
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.14.5] - 2026-09-24
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Accept bundle loader options in shared test mocks.
|
|
15
|
+
|
|
16
|
+
## [0.14.4] - 2026-09-02
|
|
17
|
+
|
|
18
|
+
### Technical
|
|
19
|
+
- Included in the coordinated all-package patch release preparation for ACE monorepo review.
|
|
10
20
|
## [0.14.3] - 2026-08-12
|
|
11
21
|
|
|
12
22
|
### Technical
|
|
@@ -152,7 +152,7 @@ module Ace
|
|
|
152
152
|
|
|
153
153
|
original_method_holder[:load_file] = Ace::Bundle.method(:load_file) if Ace::Bundle.respond_to?(:load_file)
|
|
154
154
|
|
|
155
|
-
Ace::Bundle.define_singleton_method(:load_file) do |path|
|
|
155
|
+
Ace::Bundle.define_singleton_method(:load_file) do |path, _options = {}|
|
|
156
156
|
BundleMocks.mock_load_file_result(path)
|
|
157
157
|
end
|
|
158
158
|
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ace
|
|
4
|
+
module TestSupport
|
|
5
|
+
# Shared provider-contract parity suite.
|
|
6
|
+
#
|
|
7
|
+
# Provider packages (ace-git-github, ace-git-forgejo) include this module
|
|
8
|
+
# in a test class backed by a scripted fake command runner and assert that
|
|
9
|
+
# their implementation produces identical normalized evidence and the
|
|
10
|
+
# exact classified failure taxonomy. Identical assertions run against every
|
|
11
|
+
# provider, which proves contract parity without any network or CLI.
|
|
12
|
+
#
|
|
13
|
+
# Host test class contract:
|
|
14
|
+
# - #build_provider(runner) -> Ace::Git::Providers::Base wired to the runner
|
|
15
|
+
# - #ok_runner -> successful scripted runner
|
|
16
|
+
# - #version_fail_runner -> provider CLI presence probe fails
|
|
17
|
+
# - #auth_fail_runner -> provider CLI auth probe fails
|
|
18
|
+
# - #not_found_runner -> object lookup command fails as "not found"
|
|
19
|
+
# - #malformed_runner -> object lookup returns unparseable output
|
|
20
|
+
# - #unreachable_runner -> object lookup fails as unreachable/timeout
|
|
21
|
+
#
|
|
22
|
+
# Runners are callables receiving kwargs (args:, timeout:, env:) and
|
|
23
|
+
# returning {stdout:, stderr:, exit_code:}.
|
|
24
|
+
module ProviderContract
|
|
25
|
+
# Essential normalized evidence: fields every provider must supply.
|
|
26
|
+
# Provider-optional fields (url, draft, merged_at) are asserted as
|
|
27
|
+
# present or left unchecked where a provider cannot supply them.
|
|
28
|
+
EXPECTED_PR = {
|
|
29
|
+
server_name: "forge-server",
|
|
30
|
+
number: 25,
|
|
31
|
+
title: "Ship the provider contract",
|
|
32
|
+
state: :merged,
|
|
33
|
+
head_ref: "lab/W675-ace",
|
|
34
|
+
base_ref: "main",
|
|
35
|
+
head_sha: "fc14c43d3660ac6c133959a6dec29603413f0e8a",
|
|
36
|
+
author: "lab-builder"
|
|
37
|
+
}.freeze
|
|
38
|
+
|
|
39
|
+
EXPECTED_BRANCH_PR = {
|
|
40
|
+
server_name: "forge-server",
|
|
41
|
+
number: 31,
|
|
42
|
+
title: "Wire status to providers",
|
|
43
|
+
state: :open,
|
|
44
|
+
head_ref: "lab/W676-ace",
|
|
45
|
+
base_ref: "main",
|
|
46
|
+
head_sha: "a1b2c3d4e5f60718293a4b5c6d7e8f9012345678",
|
|
47
|
+
author: "lab-builder"
|
|
48
|
+
}.freeze
|
|
49
|
+
|
|
50
|
+
EXPECTED_ISSUE = {
|
|
51
|
+
server_name: "forge-server",
|
|
52
|
+
number: 9,
|
|
53
|
+
title: "Broken diff on detached HEAD",
|
|
54
|
+
state: :open,
|
|
55
|
+
author: "lab-admin"
|
|
56
|
+
}.freeze
|
|
57
|
+
|
|
58
|
+
EXPECTED_CHECK = {server_name: "forge-server", name: "test-suite", state: :success, conclusion: :success}.freeze
|
|
59
|
+
|
|
60
|
+
EXPECTED_REPO = {
|
|
61
|
+
server_name: "forge-server",
|
|
62
|
+
full_name: "owner/repo",
|
|
63
|
+
url: "https://forge.example.com/owner/repo"
|
|
64
|
+
}.freeze
|
|
65
|
+
|
|
66
|
+
def test_contract_reports_available_and_authenticated
|
|
67
|
+
provider = build_provider(ok_runner)
|
|
68
|
+
assert_equal true, provider.available?
|
|
69
|
+
assert_equal true, provider.authenticated?
|
|
70
|
+
provider.check_available!
|
|
71
|
+
provider.check_authenticated!
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def test_contract_pull_request_evidence_matches_normalized_shape
|
|
75
|
+
pr = build_provider(ok_runner).pull_request(number: 25)
|
|
76
|
+
assert_instance_of Ace::Git::ProviderPullRequest, pr
|
|
77
|
+
assert_normalized_fields(EXPECTED_PR, pr)
|
|
78
|
+
refute_nil pr.url
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def test_contract_pull_request_for_branch_evidence_matches_normalized_shape
|
|
82
|
+
pr = build_provider(ok_runner).pull_request_for_branch(branch: "lab/W676-ace")
|
|
83
|
+
assert_instance_of Ace::Git::ProviderPullRequest, pr
|
|
84
|
+
assert_normalized_fields(EXPECTED_BRANCH_PR, pr)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def test_contract_pull_request_for_branch_returns_nil_without_match
|
|
88
|
+
assert_nil build_provider(ok_runner).pull_request_for_branch(branch: "no-such-branch")
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def test_contract_pull_request_diff_returns_raw_text
|
|
92
|
+
diff = build_provider(ok_runner).pull_request_diff(number: 25)
|
|
93
|
+
assert_instance_of String, diff
|
|
94
|
+
assert_includes diff, "diff --git"
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def test_contract_recent_pull_requests_returns_normalized_list
|
|
98
|
+
prs = build_provider(ok_runner).recent_pull_requests(limit: 30)
|
|
99
|
+
assert_instance_of Array, prs
|
|
100
|
+
assert_equal 2, prs.length
|
|
101
|
+
assert prs.all? { |pr| pr.instance_of?(Ace::Git::ProviderPullRequest) }
|
|
102
|
+
# Newest first (descending PR number), identical across providers
|
|
103
|
+
assert_equal [31, 25], prs.map(&:number)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def test_contract_issue_evidence_matches_normalized_shape
|
|
107
|
+
issue = build_provider(ok_runner).issue(number: 9)
|
|
108
|
+
assert_instance_of Ace::Git::ProviderIssue, issue
|
|
109
|
+
assert_normalized_fields(EXPECTED_ISSUE, issue)
|
|
110
|
+
refute_nil issue.url
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def test_contract_checks_return_normalized_list
|
|
114
|
+
checks = build_provider(ok_runner).checks(ref: "fc14c43d3660ac6c133959a6dec29603413f0e8a")
|
|
115
|
+
assert_instance_of Array, checks
|
|
116
|
+
assert_equal 1, checks.length
|
|
117
|
+
check = checks.first
|
|
118
|
+
assert_instance_of Ace::Git::ProviderCheck, check
|
|
119
|
+
assert_equal EXPECTED_CHECK[:server_name], check.server_name
|
|
120
|
+
assert_equal EXPECTED_CHECK[:name], check.name
|
|
121
|
+
assert_equal EXPECTED_CHECK[:state], check.state
|
|
122
|
+
assert_equal EXPECTED_CHECK[:conclusion], check.conclusion
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def test_contract_repository_evidence_matches_normalized_shape
|
|
126
|
+
repo = build_provider(ok_runner).repository
|
|
127
|
+
assert_instance_of Ace::Git::ProviderRepository, repo
|
|
128
|
+
assert_equal EXPECTED_REPO[:server_name], repo.server_name
|
|
129
|
+
assert_equal EXPECTED_REPO[:full_name], repo.full_name
|
|
130
|
+
assert_equal EXPECTED_REPO[:url], repo.url
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def test_contract_cli_missing_failure_is_classified
|
|
134
|
+
provider = build_provider(version_fail_runner)
|
|
135
|
+
error = assert_raises(Ace::Git::ProviderCliMissingError) { provider.check_available! }
|
|
136
|
+
assert_match(/cli/i, error.message)
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def test_contract_authentication_failure_is_classified
|
|
140
|
+
provider = build_provider(auth_fail_runner)
|
|
141
|
+
error = assert_raises(Ace::Git::ProviderAuthenticationError) { provider.check_authenticated! }
|
|
142
|
+
assert_match(/auth/i, error.message)
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def test_contract_object_not_found_failure_is_classified
|
|
146
|
+
provider = build_provider(not_found_runner)
|
|
147
|
+
error = assert_raises(Ace::Git::ProviderObjectNotFoundError) { provider.pull_request(number: 999) }
|
|
148
|
+
assert_match(/999/, error.message)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def test_contract_malformed_output_failure_is_classified
|
|
152
|
+
provider = build_provider(malformed_runner)
|
|
153
|
+
error = assert_raises(Ace::Git::ProviderMalformedOutputError) { provider.pull_request(number: 25) }
|
|
154
|
+
assert_match(/malformed|parse|unrecognized/i, error.message)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def test_contract_unreachable_failure_is_classified
|
|
158
|
+
provider = build_provider(unreachable_runner)
|
|
159
|
+
error = assert_raises(Ace::Git::ProviderUnreachableError) { provider.pull_request(number: 25) }
|
|
160
|
+
assert_match(/unreachable|timed out|failed/i, error.message)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
private
|
|
164
|
+
|
|
165
|
+
def assert_normalized_fields(expected, evidence)
|
|
166
|
+
expected.each do |field, value|
|
|
167
|
+
assert_equal value, evidence.public_send(field),
|
|
168
|
+
"#{field} must be normalized identically across providers"
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
@@ -38,6 +38,35 @@ module Ace
|
|
|
38
38
|
end
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
+
# Returns true when mode-0000/DAC permission bits are enforced against
|
|
42
|
+
# the current process. Root and processes with CAP_DAC_OVERRIDE bypass
|
|
43
|
+
# these checks, so chmod-based permission tests must be skipped there.
|
|
44
|
+
def permission_denial_enforced?
|
|
45
|
+
return false if Gem.win_platform?
|
|
46
|
+
|
|
47
|
+
Tempfile.create("ace_perm_probe") do |probe|
|
|
48
|
+
probe.write("probe")
|
|
49
|
+
probe.flush
|
|
50
|
+
begin
|
|
51
|
+
File.chmod(0o000, probe.path)
|
|
52
|
+
rescue NotImplementedError, SystemCallError
|
|
53
|
+
return false
|
|
54
|
+
end
|
|
55
|
+
begin
|
|
56
|
+
File.read(probe.path)
|
|
57
|
+
false
|
|
58
|
+
rescue SystemCallError
|
|
59
|
+
true
|
|
60
|
+
ensure
|
|
61
|
+
begin
|
|
62
|
+
File.chmod(0o600, probe.path)
|
|
63
|
+
rescue StandardError
|
|
64
|
+
nil
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
41
70
|
def create_config_file(path, content)
|
|
42
71
|
FileUtils.mkdir_p(File.dirname(path))
|
|
43
72
|
File.write(path, content)
|
data/lib/ace/test_support.rb
CHANGED
|
@@ -21,6 +21,7 @@ require_relative "test_support/fixtures/git_mocks" # Shared git mocks
|
|
|
21
21
|
require_relative "test_support/fixtures/http_mocks" # Shared HTTP mocks for LLM testing
|
|
22
22
|
require_relative "test_support/fixtures/prompt_helpers" # Shared prompt stubbing helpers
|
|
23
23
|
require_relative "test_support/fixtures/test_runner_mocks" # Shared test runner mocks
|
|
24
|
+
require_relative "test_support/provider_contract" # Provider contract parity suite for forge provider gems
|
|
24
25
|
|
|
25
26
|
# Configure Minitest reporters by default
|
|
26
27
|
Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ace-support-test-helpers
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.14.
|
|
4
|
+
version: 0.14.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Michal Czyz
|
|
8
8
|
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-
|
|
10
|
+
date: 2026-09-24 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: minitest
|
|
@@ -62,6 +62,7 @@ files:
|
|
|
62
62
|
- lib/ace/test_support/fixtures/prompt_helpers.rb
|
|
63
63
|
- lib/ace/test_support/fixtures/test_runner_mocks.rb
|
|
64
64
|
- lib/ace/test_support/performance_helpers.rb
|
|
65
|
+
- lib/ace/test_support/provider_contract.rb
|
|
65
66
|
- lib/ace/test_support/sandbox_package_copy.rb
|
|
66
67
|
- lib/ace/test_support/subprocess_runner.rb
|
|
67
68
|
- lib/ace/test_support/test_environment.rb
|