Skip to content

Commit 38b14c1

Browse files
committed
Add phase 4 API stabilization edge-contract tests
Introduce stabilization tests for alias error parity, empty-structure edge behavior, and strict comparable contracts to lock final API guarantees.
1 parent 6d68e9b commit 38b14c1

2 files changed

Lines changed: 95 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ Changes section to scan for breaking or behavioral changes.
2424
`Tree::Utils::BinarySearchNodeAccessors` and use it in
2525
`BinarySearchTreeNode`, `AvlTreeNode`, `RedBlackTreeNode`,
2626
`SplayTreeNode`, and `TreapNode` without changing public behavior.
27+
* Add Phase 4 stabilization tests covering alias error-parity, empty-structure
28+
edge behavior, and strict comparable contracts across tree families.
2729
* Make `Tree::TrieNode#<<` use trie word-insert semantics (`insert(word)`)
2830
instead of generic child-node attachment semantics.
2931
* Add `<<` insertion shorthand to `Tree::AATree` and `Tree::BTree` for
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# test_api_stabilization_contracts.rb - This file is part of the RubyTree package.
2+
#
3+
# Copyright (c) 2026 Anupam Sengupta
4+
#
5+
# All rights reserved.
6+
#
7+
# Redistribution and use in source and binary forms, with or without modification,
8+
# are permitted provided that the following conditions are met:
9+
#
10+
# - Redistributions of source code must retain the above copyright notice, this
11+
# list of conditions and the following disclaimer.
12+
#
13+
# - Redistributions in binary form must reproduce the above copyright notice, this
14+
# list of conditions and the following disclaimer in the documentation and/or
15+
# other materials provided with the distribution.
16+
#
17+
# - Neither the name of the organization nor the names of its contributors may
18+
# be used to endorse or promote products derived from this software without
19+
# specific prior written permission.
20+
#
21+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24+
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
25+
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26+
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27+
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
28+
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29+
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30+
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31+
#
32+
# frozen_string_literal: true
33+
34+
require 'test/unit'
35+
require_relative '../lib/tree/aatree'
36+
require_relative '../lib/tree/binaryheap'
37+
require_relative '../lib/tree/binarymaxheap'
38+
require_relative '../lib/tree/btree'
39+
require_relative '../lib/tree/fenwicktree'
40+
require_relative '../lib/tree/segmenttree'
41+
require_relative '../lib/tree/trie'
42+
43+
module TestTree
44+
# Stabilization-focused edge-contract tests for public APIs.
45+
class TestApiStabilizationContracts < Test::Unit::TestCase
46+
def test_key_value_lookup_alias_error_parity
47+
aa = Tree::AATree.new
48+
bt = Tree::BTree.new(2)
49+
50+
assert_raise(ArgumentError) { aa.search(nil) }
51+
assert_raise(ArgumentError) { aa.lookup(nil) }
52+
assert_raise(ArgumentError) { bt.search(nil) }
53+
assert_raise(ArgumentError) { bt.lookup(nil) }
54+
end
55+
56+
def test_aggregate_query_alias_error_parity
57+
fenwick = Tree::FenwickTree.new(3, [1, 2, 3])
58+
segment = Tree::SegmentTree.new(3, [1, 2, 3])
59+
60+
assert_raise(ArgumentError) { fenwick.range_sum(2, 1) }
61+
assert_raise(ArgumentError) { fenwick.query(2, 1) }
62+
assert_raise(ArgumentError) { segment.range_sum(2, 1) }
63+
assert_raise(ArgumentError) { segment.query(2, 1) }
64+
end
65+
66+
def test_heap_pop_extract_empty_contract
67+
min_heap = Tree::BinaryHeapNode.new('root')
68+
max_heap = Tree::BinaryMaxHeapNode.new('root')
69+
70+
assert_nil(min_heap.extract)
71+
assert_nil(min_heap.pop)
72+
assert_nil(max_heap.extract)
73+
assert_nil(max_heap.pop)
74+
end
75+
76+
def test_trie_search_alias_validation_parity
77+
trie = Tree::TrieNode.new('')
78+
79+
assert_raise(ArgumentError) { trie.include?('') }
80+
assert_raise(ArgumentError) { trie.search('') }
81+
assert_raise(ArgumentError) { trie.include?(123) }
82+
assert_raise(ArgumentError) { trie.search(123) }
83+
end
84+
85+
def test_comparable_contract_for_array_backed_trees
86+
fenwick = Tree::FenwickTree.new(2, [1, 2])
87+
segment = Tree::SegmentTree.new(2, [1, 2])
88+
89+
assert_nil(fenwick <=> segment)
90+
assert_nil(segment <=> fenwick)
91+
end
92+
end
93+
end

0 commit comments

Comments
 (0)