familia 2.0.0.pre15 → 2.0.0.pre17
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/.github/workflows/ci.yml +2 -2
- data/.github/workflows/code-quality.yml +138 -0
- data/.github/workflows/code-smells.yml +85 -0
- data/.github/workflows/docs.yml +31 -8
- data/.gitignore +3 -1
- data/.pre-commit-config.yaml +7 -1
- data/.reek.yml +98 -0
- data/.rubocop.yml +54 -10
- data/.talismanrc +9 -0
- data/.yardopts +18 -13
- data/CHANGELOG.rst +86 -4
- data/CLAUDE.md +39 -1
- data/Gemfile +6 -5
- data/Gemfile.lock +99 -23
- data/LICENSE.txt +1 -1
- data/README.md +285 -85
- data/changelog.d/README.md +2 -2
- data/docs/archive/FAMILIA_RELATIONSHIPS.md +22 -22
- data/docs/archive/FAMILIA_TECHNICAL.md +42 -42
- data/docs/archive/FAMILIA_UPDATE.md +3 -3
- data/docs/archive/README.md +3 -2
- data/docs/{guides/API-Reference.md → archive/api-reference.md} +87 -101
- data/docs/conf.py +29 -0
- data/docs/guides/{Field-System-Guide.md → core-field-system.md} +9 -9
- data/docs/guides/feature-encrypted-fields.md +785 -0
- data/docs/guides/{Expiration-Feature-Guide.md → feature-expiration.md} +11 -2
- data/docs/guides/feature-external-identifiers.md +637 -0
- data/docs/guides/feature-object-identifiers.md +435 -0
- data/docs/guides/{Quantization-Feature-Guide.md → feature-quantization.md} +94 -29
- data/docs/guides/feature-relationships-methods.md +684 -0
- data/docs/guides/feature-relationships.md +200 -0
- data/docs/guides/{Features-System-Developer-Guide.md → feature-system-devs.md} +4 -4
- data/docs/guides/{Feature-System-Guide.md → feature-system.md} +5 -5
- data/docs/guides/{Transient-Fields-Guide.md → feature-transient-fields.md} +2 -2
- data/docs/guides/{Implementation-Guide.md → implementation.md} +3 -3
- data/docs/guides/index.md +176 -0
- data/docs/guides/{Security-Model.md → security-model.md} +1 -1
- data/docs/migrating/v2.0.0-pre.md +1 -1
- data/docs/migrating/v2.0.0-pre11.md +2 -2
- data/docs/migrating/v2.0.0-pre12.md +2 -2
- data/docs/migrating/v2.0.0-pre5.md +33 -12
- data/docs/migrating/v2.0.0-pre6.md +2 -2
- data/docs/migrating/v2.0.0-pre7.md +8 -8
- data/docs/overview.md +624 -20
- data/docs/reference/api-technical.md +1365 -0
- data/examples/autoloader/mega_customer/features/deprecated_fields.rb +7 -0
- data/examples/autoloader/mega_customer/safe_dump_fields.rb +1 -1
- data/examples/autoloader/mega_customer.rb +3 -1
- data/examples/encrypted_fields.rb +378 -0
- data/examples/json_usage_patterns.rb +144 -0
- data/examples/relationships.rb +13 -13
- data/examples/safe_dump.rb +7 -7
- data/examples/single_connection_transaction_confusions.rb +379 -0
- data/lib/familia/base.rb +51 -10
- data/lib/familia/connection/handlers.rb +223 -0
- data/lib/familia/connection/individual_command_proxy.rb +64 -0
- data/lib/familia/connection/middleware.rb +75 -0
- data/lib/familia/connection/operation_core.rb +93 -0
- data/lib/familia/connection/operations.rb +277 -0
- data/lib/familia/connection/pipeline_core.rb +87 -0
- data/lib/familia/connection/transaction_core.rb +100 -0
- data/lib/familia/connection.rb +60 -186
- data/lib/familia/data_type/class_methods.rb +63 -0
- data/lib/familia/data_type/commands.rb +53 -51
- data/lib/familia/data_type/connection.rb +83 -0
- data/lib/familia/data_type/serialization.rb +108 -107
- data/lib/familia/data_type/settings.rb +96 -0
- data/lib/familia/data_type/types/counter.rb +1 -1
- data/lib/familia/data_type/types/hashkey.rb +15 -11
- data/lib/familia/data_type/types/{list.rb → listkey.rb} +13 -5
- data/lib/familia/data_type/types/lock.rb +3 -2
- data/lib/familia/data_type/types/sorted_set.rb +128 -14
- data/lib/familia/data_type/types/{string.rb → stringkey.rb} +7 -9
- data/lib/familia/data_type/types/unsorted_set.rb +20 -27
- data/lib/familia/data_type.rb +12 -171
- data/lib/familia/distinguisher.rb +85 -0
- data/lib/familia/encryption/encrypted_data.rb +15 -24
- data/lib/familia/encryption/manager.rb +6 -4
- data/lib/familia/encryption/providers/aes_gcm_provider.rb +1 -1
- data/lib/familia/encryption/providers/secure_xchacha20_poly1305_provider.rb +7 -9
- data/lib/familia/encryption/providers/xchacha20_poly1305_provider.rb +4 -5
- data/lib/familia/encryption/request_cache.rb +7 -7
- data/lib/familia/encryption.rb +2 -3
- data/lib/familia/errors.rb +9 -3
- data/lib/familia/features/autoloader.rb +30 -12
- data/lib/familia/features/encrypted_fields/concealed_string.rb +3 -4
- data/lib/familia/features/encrypted_fields/encrypted_field_type.rb +13 -14
- data/lib/familia/features/encrypted_fields.rb +71 -66
- data/lib/familia/features/expiration/extensions.rb +1 -1
- data/lib/familia/features/expiration.rb +31 -26
- data/lib/familia/features/external_identifier.rb +57 -19
- data/lib/familia/features/object_identifier.rb +134 -25
- data/lib/familia/features/quantization.rb +16 -21
- data/lib/familia/features/relationships/README.md +97 -0
- data/lib/familia/features/relationships/collection_operations.rb +104 -0
- data/lib/familia/features/relationships/indexing/multi_index_generators.rb +202 -0
- data/lib/familia/features/relationships/indexing/unique_index_generators.rb +306 -0
- data/lib/familia/features/relationships/indexing.rb +182 -256
- data/lib/familia/features/relationships/indexing_relationship.rb +35 -0
- data/lib/familia/features/relationships/participation/participant_methods.rb +164 -0
- data/lib/familia/features/relationships/participation/target_methods.rb +225 -0
- data/lib/familia/features/relationships/participation.rb +656 -0
- data/lib/familia/features/relationships/participation_relationship.rb +31 -0
- data/lib/familia/features/relationships/score_encoding.rb +20 -20
- data/lib/familia/features/relationships.rb +65 -266
- data/lib/familia/features/safe_dump.rb +127 -130
- data/lib/familia/features/transient_fields/redacted_string.rb +6 -6
- data/lib/familia/features/transient_fields/transient_field_type.rb +5 -5
- data/lib/familia/features/transient_fields.rb +10 -7
- data/lib/familia/features.rb +10 -14
- data/lib/familia/field_type.rb +6 -4
- data/lib/familia/horreum/connection.rb +297 -0
- data/lib/familia/horreum/{core/database_commands.rb → database_commands.rb} +27 -17
- data/lib/familia/horreum/{subclass/definition.rb → definition.rb} +139 -74
- data/lib/familia/horreum/{subclass/management.rb → management.rb} +73 -27
- data/lib/familia/horreum/{core/serialization.rb → persistence.rb} +108 -185
- data/lib/familia/horreum/{subclass/related_fields_management.rb → related_fields.rb} +104 -23
- data/lib/familia/horreum/serialization.rb +172 -0
- data/lib/familia/horreum/{shared/settings.rb → settings.rb} +2 -1
- data/lib/familia/horreum/{core/utils.rb → utils.rb} +2 -1
- data/lib/familia/horreum.rb +222 -119
- data/lib/familia/json_serializer.rb +0 -1
- data/lib/familia/logging.rb +11 -114
- data/lib/familia/refinements/dear_json.rb +122 -0
- data/lib/familia/refinements/logger_trace.rb +20 -17
- data/lib/familia/refinements/stylize_words.rb +65 -0
- data/lib/familia/refinements/time_literals.rb +60 -52
- data/lib/familia/refinements.rb +2 -1
- data/lib/familia/secure_identifier.rb +60 -28
- data/lib/familia/settings.rb +83 -7
- data/lib/familia/utils.rb +5 -87
- data/lib/familia/verifiable_identifier.rb +4 -4
- data/lib/familia/version.rb +1 -1
- data/lib/familia.rb +72 -14
- data/lib/middleware/database_middleware.rb +56 -14
- data/lib/{familia/multi_result.rb → multi_result.rb} +23 -16
- data/try/configuration/scenarios_try.rb +2 -2
- data/try/connection/fiber_context_preservation_try.rb +250 -0
- data/try/connection/handler_constraints_try.rb +59 -0
- data/try/connection/operation_mode_guards_try.rb +208 -0
- data/try/connection/pipeline_fallback_integration_try.rb +128 -0
- data/try/connection/responsibility_chain_tracking_try.rb +72 -0
- data/try/connection/transaction_fallback_integration_try.rb +288 -0
- data/try/connection/transaction_mode_permissive_try.rb +153 -0
- data/try/connection/transaction_mode_strict_try.rb +98 -0
- data/try/connection/transaction_mode_warn_try.rb +131 -0
- data/try/connection/transaction_modes_try.rb +249 -0
- data/try/core/autoloader_try.rb +120 -2
- data/try/core/connection_try.rb +10 -10
- data/try/core/conventional_inheritance_try.rb +130 -0
- data/try/core/create_method_try.rb +15 -23
- data/try/core/database_consistency_try.rb +11 -10
- data/try/core/errors_try.rb +11 -14
- data/try/core/familia_extended_try.rb +2 -2
- data/try/core/familia_members_methods_try.rb +76 -0
- data/try/core/familia_try.rb +1 -1
- data/try/core/isolated_dbclient_try.rb +165 -0
- data/try/core/middleware_try.rb +16 -16
- data/try/core/persistence_operations_try.rb +4 -4
- data/try/core/pools_try.rb +42 -26
- data/try/core/secure_identifier_try.rb +28 -24
- data/try/core/time_utils_try.rb +10 -10
- data/try/core/tools_try.rb +3 -3
- data/try/core/utils_try.rb +2 -2
- data/try/data_types/boolean_try.rb +4 -4
- data/try/data_types/datatype_base_try.rb +0 -2
- data/try/data_types/list_try.rb +10 -10
- data/try/data_types/sorted_set_try.rb +5 -5
- data/try/data_types/sorted_set_zadd_options_try.rb +625 -0
- data/try/data_types/string_try.rb +12 -12
- data/try/data_types/unsortedset_try.rb +33 -0
- data/try/debugging/cache_behavior_tracer.rb +7 -7
- data/try/debugging/debug_aad_process.rb +1 -1
- data/try/debugging/debug_concealed_internal.rb +1 -1
- data/try/debugging/debug_cross_context.rb +1 -1
- data/try/debugging/debug_fresh_cross_context.rb +1 -1
- data/try/debugging/encryption_method_tracer.rb +10 -10
- data/try/edge_cases/hash_symbolization_try.rb +1 -1
- data/try/edge_cases/ttl_side_effects_try.rb +1 -1
- data/try/encryption/config_persistence_try.rb +2 -2
- data/try/encryption/encryption_core_try.rb +19 -19
- data/try/encryption/instance_variable_scope_try.rb +1 -1
- data/try/encryption/module_loading_try.rb +2 -2
- data/try/encryption/providers/aes_gcm_provider_try.rb +1 -1
- data/try/encryption/providers/xchacha20_poly1305_provider_try.rb +1 -1
- data/try/encryption/secure_memory_handling_try.rb +1 -1
- data/try/features/encrypted_fields/concealed_string_core_try.rb +11 -7
- data/try/features/encrypted_fields/encrypted_fields_core_try.rb +1 -1
- data/try/features/encrypted_fields/encrypted_fields_integration_try.rb +3 -3
- data/try/features/encrypted_fields/encrypted_fields_no_cache_security_try.rb +10 -10
- data/try/features/encrypted_fields/encrypted_fields_security_try.rb +14 -14
- data/try/features/encrypted_fields/error_conditions_try.rb +7 -7
- data/try/features/encrypted_fields/fresh_key_try.rb +1 -1
- data/try/features/encrypted_fields/nonce_uniqueness_try.rb +1 -1
- data/try/features/encrypted_fields/secure_by_default_behavior_try.rb +7 -7
- data/try/features/encrypted_fields/universal_serialization_safety_try.rb +13 -20
- data/try/features/external_identifier/external_identifier_try.rb +1 -1
- data/try/features/feature_dependencies_try.rb +3 -3
- data/try/features/field_groups_try.rb +244 -0
- data/try/features/object_identifier/object_identifier_integration_try.rb +28 -34
- data/try/features/object_identifier/object_identifier_try.rb +10 -0
- data/try/features/quantization/quantization_try.rb +1 -1
- data/try/features/relationships/indexing_commands_verification_try.rb +136 -0
- data/try/features/relationships/indexing_try.rb +443 -0
- data/try/features/relationships/participation_commands_verification_spec.rb +102 -0
- data/try/features/relationships/participation_commands_verification_try.rb +105 -0
- data/try/features/relationships/participation_performance_improvements_try.rb +124 -0
- data/try/features/relationships/participation_reverse_index_try.rb +196 -0
- data/try/features/relationships/relationships_api_changes_try.rb +72 -71
- data/try/features/relationships/relationships_edge_cases_try.rb +15 -18
- data/try/features/relationships/relationships_performance_minimal_try.rb +2 -2
- data/try/features/relationships/relationships_performance_simple_try.rb +8 -8
- data/try/features/relationships/relationships_performance_try.rb +20 -20
- data/try/features/relationships/relationships_try.rb +27 -38
- data/try/features/safe_dump/safe_dump_advanced_try.rb +2 -2
- data/try/features/transient_fields/refresh_reset_try.rb +3 -1
- data/try/features/transient_fields/simple_refresh_test.rb +1 -1
- data/try/helpers/test_cleanup.rb +86 -0
- data/try/helpers/test_helpers.rb +6 -7
- data/try/horreum/auto_indexing_on_save_try.rb +212 -0
- data/try/horreum/base_try.rb +3 -2
- data/try/horreum/commands_try.rb +3 -1
- data/try/horreum/defensive_initialization_try.rb +86 -0
- data/try/horreum/destroy_related_fields_cleanup_try.rb +332 -0
- data/try/horreum/initialization_try.rb +11 -7
- data/try/horreum/relations_try.rb +21 -13
- data/try/horreum/serialization_try.rb +12 -11
- data/try/horreum/settings_try.rb +2 -0
- data/try/integration/cross_component_try.rb +3 -3
- data/try/memory/memory_basic_test.rb +1 -1
- data/try/memory/memory_docker_ruby_dump.sh +2 -2
- data/try/models/customer_safe_dump_try.rb +1 -1
- data/try/models/customer_try.rb +13 -15
- data/try/models/datatype_base_try.rb +3 -3
- data/try/models/familia_object_try.rb +9 -8
- data/try/performance/benchmarks_try.rb +2 -2
- data/try/prototypes/atomic_saves_v1_context_proxy.rb +2 -2
- data/try/prototypes/atomic_saves_v3_connection_pool.rb +3 -3
- data/try/prototypes/atomic_saves_v4.rb +1 -1
- data/try/prototypes/lib/atomic_saves_v2_connection_switching_helpers.rb +4 -4
- data/try/prototypes/lib/atomic_saves_v3_connection_pool_helpers.rb +4 -4
- data/try/prototypes/pooling/lib/atomic_saves_v3_connection_pool_helpers.rb +4 -4
- data/try/prototypes/pooling/lib/connection_pool_metrics.rb +5 -5
- data/try/prototypes/pooling/lib/connection_pool_stress_test.rb +26 -26
- data/try/prototypes/pooling/lib/connection_pool_threading_models.rb +7 -7
- data/try/prototypes/pooling/lib/visualize_stress_results.rb +1 -1
- data/try/prototypes/pooling/pool_siege.rb +11 -11
- data/try/prototypes/pooling/run_stress_tests.rb +7 -7
- data/try/refinements/dear_json_array_methods_try.rb +53 -0
- data/try/refinements/dear_json_hash_methods_try.rb +54 -0
- data/try/refinements/logger_trace_methods_try.rb +44 -0
- data/try/refinements/time_literals_numeric_methods_try.rb +141 -0
- data/try/refinements/time_literals_string_methods_try.rb +80 -0
- data/try/valkey.conf +26 -0
- metadata +92 -52
- data/.rubocop_todo.yml +0 -208
- data/docs/connection_pooling.md +0 -192
- data/docs/guides/Connection-Pooling-Guide.md +0 -437
- data/docs/guides/Encrypted-Fields-Overview.md +0 -101
- data/docs/guides/Feature-System-Autoloading.md +0 -198
- data/docs/guides/Home.md +0 -116
- data/docs/guides/Relationships-Guide.md +0 -737
- data/docs/guides/relationships-methods.md +0 -266
- data/docs/reference/auditing_database_commands.rb +0 -228
- data/examples/permissions.rb +0 -240
- data/lib/familia/features/relationships/cascading.rb +0 -437
- data/lib/familia/features/relationships/membership.rb +0 -497
- data/lib/familia/features/relationships/permission_management.rb +0 -264
- data/lib/familia/features/relationships/querying.rb +0 -615
- data/lib/familia/features/relationships/redis_operations.rb +0 -274
- data/lib/familia/features/relationships/tracking.rb +0 -418
- data/lib/familia/horreum/core/connection.rb +0 -73
- data/lib/familia/horreum/core.rb +0 -21
- data/lib/familia/refinements/snake_case.rb +0 -40
- data/lib/familia/validation/command_recorder.rb +0 -336
- data/lib/familia/validation/expectations.rb +0 -519
- data/lib/familia/validation/validation_helpers.rb +0 -443
- data/lib/familia/validation/validator.rb +0 -412
- data/lib/familia/validation.rb +0 -140
- data/try/data_types/set_try.rb +0 -33
- data/try/features/relationships/categorical_permissions_try.rb +0 -515
- data/try/features/safe_dump/module_based_extensions_try.rb +0 -100
- data/try/features/safe_dump/safe_dump_autoloading_try.rb +0 -107
- data/try/validation/atomic_operations_try.rb.disabled +0 -320
- data/try/validation/command_validation_try.rb.disabled +0 -207
- data/try/validation/performance_validation_try.rb.disabled +0 -324
- data/try/validation/real_world_scenarios_try.rb.disabled +0 -390
@@ -0,0 +1,625 @@
|
|
1
|
+
# try/features/data_type/sorted_set_zadd_options_try.rb
|
2
|
+
|
3
|
+
require_relative '../helpers/test_helpers'
|
4
|
+
|
5
|
+
# Test class for ZADD options testing
|
6
|
+
class MetricsTest < Familia::Horreum
|
7
|
+
identifier_field :name
|
8
|
+
|
9
|
+
field :name
|
10
|
+
sorted_set :metrics
|
11
|
+
|
12
|
+
def initialize(name = nil)
|
13
|
+
super(name: name || SecureRandom.hex(4))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
## Store the zset in convenience var
|
18
|
+
@metricstest = MetricsTest.new('test')
|
19
|
+
@zset = @metricstest.metrics
|
20
|
+
#=:> Familia::SortedSet
|
21
|
+
|
22
|
+
# ============================================================
|
23
|
+
# NX Option Tests
|
24
|
+
# ============================================================
|
25
|
+
|
26
|
+
## ZADD NX: Add new element
|
27
|
+
@zset.clear
|
28
|
+
@zset.add('member1', 100, nx: true)
|
29
|
+
#=> true
|
30
|
+
|
31
|
+
## ZADD NX: Prevent update of existing element
|
32
|
+
@zset.add('member1', 200, nx: true)
|
33
|
+
#=> false
|
34
|
+
|
35
|
+
## ZADD NX: Verify score unchanged
|
36
|
+
@zset.score('member1')
|
37
|
+
#=> 100.0
|
38
|
+
|
39
|
+
## ZADD NX: Allow adding different member
|
40
|
+
@zset.add('member2', 150, nx: true)
|
41
|
+
#=> true
|
42
|
+
|
43
|
+
# ============================================================
|
44
|
+
# XX Option Tests
|
45
|
+
# ============================================================
|
46
|
+
|
47
|
+
## ZADD XX: Prevent adding new element
|
48
|
+
@zset.clear
|
49
|
+
@zset.add('member1', 100, xx: true)
|
50
|
+
#=> false
|
51
|
+
|
52
|
+
## ZADD XX: Verify element not added
|
53
|
+
@zset.member?('member1')
|
54
|
+
#=> false
|
55
|
+
|
56
|
+
## ZADD XX: Update existing element
|
57
|
+
@zset.add('member1', 100)
|
58
|
+
@zset.add('member1', 200, xx: true)
|
59
|
+
#=> false
|
60
|
+
|
61
|
+
## ZADD XX: Verify score updated
|
62
|
+
@zset.score('member1')
|
63
|
+
#=> 200.0
|
64
|
+
|
65
|
+
# ============================================================
|
66
|
+
# GT Option Tests
|
67
|
+
# ============================================================
|
68
|
+
|
69
|
+
## ZADD GT: Allow adding new element
|
70
|
+
@zset.clear
|
71
|
+
@zset.add('member1', 100, gt: true)
|
72
|
+
#=> true
|
73
|
+
|
74
|
+
## ZADD GT: Update when new score greater
|
75
|
+
@zset.add('member1', 200, gt: true)
|
76
|
+
#=> false
|
77
|
+
|
78
|
+
## ZADD GT: Verify score updated
|
79
|
+
@zset.score('member1')
|
80
|
+
#=> 200.0
|
81
|
+
|
82
|
+
## ZADD GT: Prevent update when new score not greater
|
83
|
+
@zset.add('member1', 150, gt: true)
|
84
|
+
#=> false
|
85
|
+
|
86
|
+
## ZADD GT: Verify score unchanged
|
87
|
+
@zset.score('member1')
|
88
|
+
#=> 200.0
|
89
|
+
|
90
|
+
## ZADD GT: Allow update when new score greater again
|
91
|
+
@zset.add('member1', 300, gt: true)
|
92
|
+
#=> false
|
93
|
+
|
94
|
+
## ZADD GT: Verify score updated again
|
95
|
+
@zset.score('member1')
|
96
|
+
#=> 300.0
|
97
|
+
|
98
|
+
# ============================================================
|
99
|
+
# LT Option Tests
|
100
|
+
# ============================================================
|
101
|
+
|
102
|
+
## ZADD LT: Allow adding new element
|
103
|
+
@zset.clear
|
104
|
+
@zset.add('member1', 100, lt: true)
|
105
|
+
#=> true
|
106
|
+
|
107
|
+
## ZADD LT: Update when new score lesser
|
108
|
+
@zset.add('member1', 50, lt: true)
|
109
|
+
#=> false
|
110
|
+
|
111
|
+
## ZADD LT: Verify score updated
|
112
|
+
@zset.score('member1')
|
113
|
+
#=> 50.0
|
114
|
+
|
115
|
+
## ZADD LT: Prevent update when new score not lesser
|
116
|
+
@zset.add('member1', 75, lt: true)
|
117
|
+
#=> false
|
118
|
+
|
119
|
+
## ZADD LT: Verify score unchanged
|
120
|
+
@zset.score('member1')
|
121
|
+
#=> 50.0
|
122
|
+
|
123
|
+
## ZADD LT: Allow update when new score lesser again
|
124
|
+
@zset.add('member1', 25, lt: true)
|
125
|
+
#=> false
|
126
|
+
|
127
|
+
## ZADD LT: Verify score updated again
|
128
|
+
@zset.score('member1')
|
129
|
+
#=> 25.0
|
130
|
+
|
131
|
+
# ============================================================
|
132
|
+
# CH Option Tests
|
133
|
+
# ============================================================
|
134
|
+
|
135
|
+
## ZADD CH: Return count for new element
|
136
|
+
@zset.clear
|
137
|
+
@zset.add('member1', 100, ch: true)
|
138
|
+
#=> true
|
139
|
+
|
140
|
+
## ZADD CH: Return count for update (without CH would be 0)
|
141
|
+
@zset.add('member1', 200, ch: true)
|
142
|
+
#=> true
|
143
|
+
|
144
|
+
## ZADD CH without update: Return 0
|
145
|
+
@zset.add('member1', 200, ch: true)
|
146
|
+
#=> false
|
147
|
+
|
148
|
+
## ZADD CH with GT: Count changes only
|
149
|
+
@zset.add('member1', 300, gt: true, ch: true)
|
150
|
+
#=> true
|
151
|
+
|
152
|
+
## ZADD CH with GT: No change when score not greater
|
153
|
+
@zset.add('member1', 250, gt: true, ch: true)
|
154
|
+
#=> false
|
155
|
+
|
156
|
+
## ZADD CH with LT: Count changes only
|
157
|
+
@zset.add('member1', 100, lt: true, ch: true)
|
158
|
+
#=> true
|
159
|
+
|
160
|
+
## ZADD CH with LT: No change when score not lesser
|
161
|
+
@zset.add('member1', 150, lt: true, ch: true)
|
162
|
+
#=> false
|
163
|
+
|
164
|
+
# ============================================================
|
165
|
+
# Combined Options Tests
|
166
|
+
# ============================================================
|
167
|
+
|
168
|
+
## ZADD XX+GT: Update only if exists and score greater
|
169
|
+
@zset.clear
|
170
|
+
@zset.add('member1', 100)
|
171
|
+
@zset.add('member1', 200, xx: true, gt: true)
|
172
|
+
#=> false
|
173
|
+
|
174
|
+
## ZADD XX+GT: Verify score updated
|
175
|
+
@zset.score('member1')
|
176
|
+
#=> 200.0
|
177
|
+
|
178
|
+
## ZADD XX+GT: Prevent update when score not greater
|
179
|
+
@zset.add('member1', 150, xx: true, gt: true)
|
180
|
+
#=> false
|
181
|
+
|
182
|
+
## ZADD XX+GT: Verify score unchanged
|
183
|
+
@zset.score('member1')
|
184
|
+
#=> 200.0
|
185
|
+
|
186
|
+
## ZADD XX+GT: Prevent adding new element
|
187
|
+
@zset.add('member2', 500, xx: true, gt: true)
|
188
|
+
#=> false
|
189
|
+
|
190
|
+
## ZADD XX+GT: Verify element not added
|
191
|
+
@zset.member?('member2')
|
192
|
+
#=> false
|
193
|
+
|
194
|
+
## ZADD XX+LT: Update only if exists and score lesser
|
195
|
+
@zset.clear
|
196
|
+
@zset.add('member1', 100)
|
197
|
+
@zset.add('member1', 50, xx: true, lt: true)
|
198
|
+
#=> false
|
199
|
+
|
200
|
+
## ZADD XX+LT: Verify score updated
|
201
|
+
@zset.score('member1')
|
202
|
+
#=> 50.0
|
203
|
+
|
204
|
+
## ZADD XX+LT: Prevent update when score not lesser
|
205
|
+
@zset.add('member1', 75, xx: true, lt: true)
|
206
|
+
#=> false
|
207
|
+
|
208
|
+
## ZADD XX+LT: Verify score unchanged
|
209
|
+
@zset.score('member1')
|
210
|
+
#=> 50.0
|
211
|
+
|
212
|
+
## ZADD XX+CH: Track updates for existing elements
|
213
|
+
@zset.clear
|
214
|
+
@zset.add('member1', 100)
|
215
|
+
@zset.add('member1', 200, xx: true, ch: true)
|
216
|
+
#=> true
|
217
|
+
|
218
|
+
## ZADD XX+GT+CH: Combined tracking
|
219
|
+
@zset.add('member1', 300, xx: true, gt: true, ch: true)
|
220
|
+
#=> true
|
221
|
+
|
222
|
+
## ZADD XX+GT+CH: No change when conditions not met
|
223
|
+
@zset.add('member1', 250, xx: true, gt: true, ch: true)
|
224
|
+
#=> false
|
225
|
+
|
226
|
+
# ============================================================
|
227
|
+
# Mutual Exclusivity Validation Tests
|
228
|
+
# ============================================================
|
229
|
+
|
230
|
+
## ZADD NX+XX: Raise ArgumentError
|
231
|
+
@zset.clear
|
232
|
+
begin
|
233
|
+
@zset.add('member1', 100, nx: true, xx: true)
|
234
|
+
false
|
235
|
+
rescue ArgumentError => e
|
236
|
+
e.message.include?('mutually exclusive')
|
237
|
+
end
|
238
|
+
#=> true
|
239
|
+
|
240
|
+
## ZADD GT+LT: Raise ArgumentError
|
241
|
+
begin
|
242
|
+
@zset.add('member1', 100, gt: true, lt: true)
|
243
|
+
false
|
244
|
+
rescue ArgumentError => e
|
245
|
+
e.message.include?('mutually exclusive')
|
246
|
+
end
|
247
|
+
#=> true
|
248
|
+
|
249
|
+
## ZADD NX+GT: Raise ArgumentError
|
250
|
+
begin
|
251
|
+
@zset.add('member1', 100, nx: true, gt: true)
|
252
|
+
false
|
253
|
+
rescue ArgumentError => e
|
254
|
+
e.message.include?('mutually exclusive')
|
255
|
+
end
|
256
|
+
#=> true
|
257
|
+
|
258
|
+
## ZADD NX+LT: Raise ArgumentError
|
259
|
+
begin
|
260
|
+
@zset.add('member1', 100, nx: true, lt: true)
|
261
|
+
false
|
262
|
+
rescue ArgumentError => e
|
263
|
+
e.message.include?('mutually exclusive')
|
264
|
+
end
|
265
|
+
#=> true
|
266
|
+
|
267
|
+
# ============================================================
|
268
|
+
# Backward Compatibility Tests
|
269
|
+
# ============================================================
|
270
|
+
|
271
|
+
## ZADD: No options specified (default behavior)
|
272
|
+
@zset.clear
|
273
|
+
@zset.add('member1', 100)
|
274
|
+
#=> true
|
275
|
+
|
276
|
+
## ZADD: Update without options
|
277
|
+
@zset.add('member1', 200)
|
278
|
+
#=> false
|
279
|
+
|
280
|
+
## ZADD: Verify score updated
|
281
|
+
@zset.score('member1')
|
282
|
+
#=> 200.0
|
283
|
+
|
284
|
+
## ZADD: Verify default score (Familia.now)
|
285
|
+
@zset.clear
|
286
|
+
@zset.add('member2')
|
287
|
+
@zset.score('member2') > 0
|
288
|
+
#=> true
|
289
|
+
|
290
|
+
# ============================================================
|
291
|
+
# Serialization Integration Tests
|
292
|
+
# ============================================================
|
293
|
+
|
294
|
+
## ZADD with symbol values and NX
|
295
|
+
@zset.clear
|
296
|
+
@zset.add(:member1, 100, nx: true)
|
297
|
+
#=> true
|
298
|
+
|
299
|
+
## ZADD with symbol values: Verify membership
|
300
|
+
@zset.member?(:member1)
|
301
|
+
#=> true
|
302
|
+
|
303
|
+
## ZADD with symbol values: NX prevents update
|
304
|
+
@zset.add(:member1, 200, nx: true)
|
305
|
+
#=> false
|
306
|
+
|
307
|
+
## ZADD with symbol values: XX updates
|
308
|
+
@zset.add(:member1, 300, xx: true)
|
309
|
+
#=> false
|
310
|
+
|
311
|
+
## ZADD with symbol values: Verify score
|
312
|
+
@zset.score(:member1)
|
313
|
+
#=> 300.0
|
314
|
+
|
315
|
+
## ZADD with object values and NX
|
316
|
+
@metrics_test3 = MetricsTest.new('object_value_test')
|
317
|
+
@zset.add(@metrics_test3, 100, nx: true)
|
318
|
+
#=> true
|
319
|
+
|
320
|
+
## ZADD with object values: Verify membership
|
321
|
+
@zset.member?(@metrics_test3)
|
322
|
+
#=> true
|
323
|
+
|
324
|
+
# ============================================================
|
325
|
+
# Edge Cases
|
326
|
+
# ============================================================
|
327
|
+
|
328
|
+
## ZADD with nil score defaults to Familia.now (NX option)
|
329
|
+
@zset.clear
|
330
|
+
result = @zset.add('member1', nil, nx: true)
|
331
|
+
result == true && @zset.score('member1') > 0
|
332
|
+
#=> true
|
333
|
+
|
334
|
+
## ZADD with nil score defaults to Familia.now (XX option)
|
335
|
+
@zset.add('member2', 100)
|
336
|
+
result = @zset.add('member2', nil, xx: true)
|
337
|
+
result == false && @zset.score('member2') > 100
|
338
|
+
#=> true
|
339
|
+
|
340
|
+
## ZADD GT with equal score: No update
|
341
|
+
@zset.clear
|
342
|
+
@zset.add('member1', 100)
|
343
|
+
@zset.add('member1', 100, gt: true)
|
344
|
+
#=> false
|
345
|
+
|
346
|
+
## ZADD LT with equal score: No update
|
347
|
+
@zset.clear
|
348
|
+
@zset.add('member1', 100)
|
349
|
+
@zset.add('member1', 100, lt: true)
|
350
|
+
#=> false
|
351
|
+
|
352
|
+
## ZADD NX with CH: Return count correctly
|
353
|
+
@zset.clear
|
354
|
+
@zset.add('member1', 100, nx: true, ch: true)
|
355
|
+
#=> true
|
356
|
+
|
357
|
+
## ZADD NX with CH: Return 0 when exists
|
358
|
+
@zset.add('member1', 200, nx: true, ch: true)
|
359
|
+
#=> false
|
360
|
+
|
361
|
+
# ============================================================
|
362
|
+
# Multiple Elements Tests (Redis 6.2+ ZADD behavior)
|
363
|
+
# ============================================================
|
364
|
+
|
365
|
+
## Multiple elements: Add multiple elements at once (simulate with array)
|
366
|
+
@zset.clear
|
367
|
+
result1 = @zset.add('member1', 100)
|
368
|
+
result2 = @zset.add('member2', 200)
|
369
|
+
[result1, result2]
|
370
|
+
#=> [true, true]
|
371
|
+
|
372
|
+
## Multiple elements: Verify both elements exist
|
373
|
+
[@zset.member?('member1'), @zset.member?('member2')]
|
374
|
+
#=> [true, true]
|
375
|
+
|
376
|
+
## Multiple elements: Update one existing, add one new (simulate)
|
377
|
+
result1 = @zset.add('member1', 150) # update existing
|
378
|
+
result2 = @zset.add('member3', 300) # add new
|
379
|
+
[result1, result2]
|
380
|
+
#=> [false, true]
|
381
|
+
|
382
|
+
## Multiple elements with CH: Track all changes (simulate behavior)
|
383
|
+
@zset.clear
|
384
|
+
@zset.add('member1', 100) # existing element
|
385
|
+
result1 = @zset.add('member1', 150, ch: true) # update existing
|
386
|
+
result2 = @zset.add('member2', 200, ch: true) # add new
|
387
|
+
[result1, result2]
|
388
|
+
#=> [true, true]
|
389
|
+
|
390
|
+
## Multiple elements with CH: No changes
|
391
|
+
result1 = @zset.add('member1', 150, ch: true) # same score
|
392
|
+
result2 = @zset.add('member2', 200, ch: true) # same score
|
393
|
+
[result1, result2]
|
394
|
+
#=> [false, false]
|
395
|
+
|
396
|
+
## Multiple elements with NX: Mixed new and existing
|
397
|
+
@zset.clear
|
398
|
+
@zset.add('member1', 100) # pre-existing
|
399
|
+
result1 = @zset.add('member1', 150, nx: true) # existing, should not update
|
400
|
+
result2 = @zset.add('member2', 200, nx: true) # new, should add
|
401
|
+
[result1, result2]
|
402
|
+
#=> [false, true]
|
403
|
+
|
404
|
+
## Multiple elements with NX: Verify scores unchanged for existing
|
405
|
+
@zset.score('member1')
|
406
|
+
#=> 100.0
|
407
|
+
|
408
|
+
## Multiple elements with NX: Verify new element added
|
409
|
+
@zset.score('member2')
|
410
|
+
#=> 200.0
|
411
|
+
|
412
|
+
## Multiple elements with XX: Mixed existing and new
|
413
|
+
@zset.clear
|
414
|
+
@zset.add('member1', 100) # pre-existing
|
415
|
+
result1 = @zset.add('member1', 150, xx: true) # existing, should update
|
416
|
+
result2 = @zset.add('member2', 200, xx: true) # new, should not add
|
417
|
+
[result1, result2]
|
418
|
+
#=> [false, false]
|
419
|
+
|
420
|
+
## Multiple elements with XX: Verify existing updated
|
421
|
+
@zset.score('member1')
|
422
|
+
#=> 150.0
|
423
|
+
|
424
|
+
## Multiple elements with XX: Verify new element not added
|
425
|
+
@zset.member?('member2')
|
426
|
+
#=> false
|
427
|
+
|
428
|
+
## Multiple elements with GT: Mixed score conditions
|
429
|
+
@zset.clear
|
430
|
+
@zset.add('member1', 100)
|
431
|
+
@zset.add('member2', 200)
|
432
|
+
result1 = @zset.add('member1', 150, gt: true) # 150 > 100, should update
|
433
|
+
result2 = @zset.add('member2', 150, gt: true) # 150 < 200, should not update
|
434
|
+
[result1, result2]
|
435
|
+
#=> [false, false]
|
436
|
+
|
437
|
+
## Multiple elements with GT: Verify selective updates
|
438
|
+
[@zset.score('member1'), @zset.score('member2')]
|
439
|
+
#=> [150.0, 200.0]
|
440
|
+
|
441
|
+
## Multiple elements with LT: Mixed score conditions
|
442
|
+
@zset.clear
|
443
|
+
@zset.add('member1', 100)
|
444
|
+
@zset.add('member2', 200)
|
445
|
+
result1 = @zset.add('member1', 150, lt: true) # 150 > 100, should not update
|
446
|
+
result2 = @zset.add('member2', 150, lt: true) # 150 < 200, should update
|
447
|
+
[result1, result2]
|
448
|
+
#=> [false, false]
|
449
|
+
|
450
|
+
## Multiple elements with LT: Verify selective updates
|
451
|
+
[@zset.score('member1'), @zset.score('member2')]
|
452
|
+
#=> [100.0, 150.0]
|
453
|
+
|
454
|
+
## Multiple elements with XX+CH: Track updates only
|
455
|
+
@zset.clear
|
456
|
+
@zset.add('member1', 100)
|
457
|
+
@zset.add('member2', 200)
|
458
|
+
result1 = @zset.add('member1', 150, xx: true, ch: true) # existing, updated
|
459
|
+
result2 = @zset.add('member3', 300, xx: true, ch: true) # new, not added
|
460
|
+
[result1, result2]
|
461
|
+
#=> [true, false]
|
462
|
+
|
463
|
+
## Multiple elements with XX+GT+CH: Complex conditions
|
464
|
+
@zset.clear
|
465
|
+
@zset.add('member1', 100)
|
466
|
+
@zset.add('member2', 200)
|
467
|
+
result1 = @zset.add('member1', 150, xx: true, gt: true, ch: true) # update: 150 > 100
|
468
|
+
result2 = @zset.add('member2', 150, xx: true, gt: true, ch: true) # no update: 150 < 200
|
469
|
+
[result1, result2]
|
470
|
+
#=> [true, false]
|
471
|
+
|
472
|
+
## Multiple elements with NX+CH: Only new elements tracked
|
473
|
+
@zset.clear
|
474
|
+
@zset.add('member1', 100)
|
475
|
+
result1 = @zset.add('member1', 150, nx: true, ch: true) # existing, no change
|
476
|
+
result2 = @zset.add('member2', 200, nx: true, ch: true) # new, added
|
477
|
+
[result1, result2]
|
478
|
+
#=> [false, true]
|
479
|
+
|
480
|
+
# ============================================================
|
481
|
+
# Large Batch Operations Simulation
|
482
|
+
# ============================================================
|
483
|
+
|
484
|
+
## Batch operation: Add multiple elements with different options
|
485
|
+
@zset.clear
|
486
|
+
batch_results = []
|
487
|
+
5.times do |i|
|
488
|
+
member = "member#{i}"
|
489
|
+
score = (i + 1) * 100
|
490
|
+
result = @zset.add(member, score, ch: true)
|
491
|
+
batch_results << result
|
492
|
+
end
|
493
|
+
batch_results
|
494
|
+
#=> [true, true, true, true, true]
|
495
|
+
|
496
|
+
## Batch operation: Update all with GT option
|
497
|
+
update_results = []
|
498
|
+
5.times do |i|
|
499
|
+
member = "member#{i}"
|
500
|
+
new_score = (i + 1) * 100 + 50 # Increase all scores
|
501
|
+
result = @zset.add(member, new_score, gt: true, ch: true)
|
502
|
+
update_results << result
|
503
|
+
end
|
504
|
+
update_results
|
505
|
+
#=> [true, true, true, true, true]
|
506
|
+
|
507
|
+
## Batch operation: Try to decrease all with GT (should fail)
|
508
|
+
decrease_results = []
|
509
|
+
5.times do |i|
|
510
|
+
member = "member#{i}"
|
511
|
+
new_score = (i + 1) * 100 + 25 # Lower than current
|
512
|
+
result = @zset.add(member, new_score, gt: true, ch: true)
|
513
|
+
decrease_results << result
|
514
|
+
end
|
515
|
+
decrease_results
|
516
|
+
#=> [false, false, false, false, false]
|
517
|
+
|
518
|
+
## Batch operation: Mixed NX operations on existing set
|
519
|
+
mixed_results = []
|
520
|
+
# Try to add existing members (should fail with NX)
|
521
|
+
3.times do |i|
|
522
|
+
member = "member#{i}"
|
523
|
+
result = @zset.add(member, 999, nx: true, ch: true)
|
524
|
+
mixed_results << result
|
525
|
+
end
|
526
|
+
# Try to add new members (should succeed with NX)
|
527
|
+
2.times do |i|
|
528
|
+
member = "new_member#{i}"
|
529
|
+
result = @zset.add(member, 999, nx: true, ch: true)
|
530
|
+
mixed_results << result
|
531
|
+
end
|
532
|
+
mixed_results
|
533
|
+
#=> [false, false, false, true, true]
|
534
|
+
|
535
|
+
# ============================================================
|
536
|
+
# Explicit Return Value Verification Tests
|
537
|
+
# ============================================================
|
538
|
+
|
539
|
+
## Return value: Add new element (should return true)
|
540
|
+
@zset.clear
|
541
|
+
@zset.add('member1', 100)
|
542
|
+
#=> true
|
543
|
+
|
544
|
+
## Return value: Update existing element (should return false)
|
545
|
+
@zset.add('member1', 200)
|
546
|
+
#=> false
|
547
|
+
|
548
|
+
## Return value: Add with NX for new element (should return true)
|
549
|
+
@zset.add('member2', 100, nx: true)
|
550
|
+
#=> true
|
551
|
+
|
552
|
+
## Return value: Add with NX for existing element (should return false)
|
553
|
+
@zset.add('member2', 200, nx: true)
|
554
|
+
#=> false
|
555
|
+
|
556
|
+
## Return value: Add with XX for non-existing element (should return false)
|
557
|
+
@zset.clear
|
558
|
+
@zset.add('member1', 100, xx: true)
|
559
|
+
#=> false
|
560
|
+
|
561
|
+
## Return value: Add with XX for existing element update (should return false)
|
562
|
+
@zset.add('member1', 100)
|
563
|
+
@zset.add('member1', 200, xx: true)
|
564
|
+
#=> false
|
565
|
+
|
566
|
+
## Return value: Add with CH for new element (should return true)
|
567
|
+
@zset.clear
|
568
|
+
@zset.add('member1', 100, ch: true)
|
569
|
+
#=> true
|
570
|
+
|
571
|
+
## Return value: Add with CH for element update (should return true)
|
572
|
+
@zset.add('member1', 200, ch: true)
|
573
|
+
#=> true
|
574
|
+
|
575
|
+
## Return value: Add with CH for no change (should return false)
|
576
|
+
@zset.add('member1', 200, ch: true)
|
577
|
+
#=> false
|
578
|
+
|
579
|
+
## Return value: Add with GT for new element (should return true)
|
580
|
+
@zset.clear
|
581
|
+
@zset.add('member1', 100, gt: true)
|
582
|
+
#=> true
|
583
|
+
|
584
|
+
## Return value: Add with GT for score increase (should return false - update)
|
585
|
+
@zset.add('member1', 200, gt: true)
|
586
|
+
#=> false
|
587
|
+
|
588
|
+
## Return value: Add with GT for score decrease (should return false - no change)
|
589
|
+
@zset.add('member1', 150, gt: true)
|
590
|
+
#=> false
|
591
|
+
|
592
|
+
## Return value: Add with LT for new element (should return true)
|
593
|
+
@zset.clear
|
594
|
+
@zset.add('member1', 100, lt: true)
|
595
|
+
#=> true
|
596
|
+
|
597
|
+
## Return value: Add with LT for score decrease (should return false - update)
|
598
|
+
@zset.add('member1', 50, lt: true)
|
599
|
+
#=> false
|
600
|
+
|
601
|
+
## Return value: Add with LT for score increase (should return false - no change)
|
602
|
+
@zset.add('member1', 75, lt: true)
|
603
|
+
#=> false
|
604
|
+
|
605
|
+
## Return value: Add with XX+GT+CH for valid update (should return true)
|
606
|
+
@zset.clear
|
607
|
+
@zset.add('member1', 100)
|
608
|
+
@zset.add('member1', 200, xx: true, gt: true, ch: true)
|
609
|
+
#=> true
|
610
|
+
|
611
|
+
## Return value: Add with XX+GT+CH for invalid update (should return false)
|
612
|
+
@zset.add('member1', 150, xx: true, gt: true, ch: true)
|
613
|
+
#=> false
|
614
|
+
|
615
|
+
## Return value: All return values are Boolean type (not Integer)
|
616
|
+
@zset.clear
|
617
|
+
results = []
|
618
|
+
results << @zset.add('member1', 100) # new
|
619
|
+
results << @zset.add('member1', 200) # update
|
620
|
+
results << @zset.add('member2', 100, nx: true) # new with NX
|
621
|
+
results << @zset.add('member2', 200, nx: true) # existing with NX
|
622
|
+
results << @zset.add('member3', 100, xx: true) # non-existing with XX
|
623
|
+
results << @zset.add('member1', 300, ch: true) # update with CH
|
624
|
+
results.all? { |r| r.is_a?(TrueClass) || r.is_a?(FalseClass) }
|
625
|
+
#=> true
|
@@ -8,24 +8,24 @@ require_relative '../helpers/test_helpers'
|
|
8
8
|
@a.dbkey
|
9
9
|
#=> 'bone:atoken2:object'
|
10
10
|
|
11
|
-
## Familia::
|
11
|
+
## Familia::StringKey#value should give default value
|
12
12
|
@a.value.value
|
13
13
|
#=> 'GREAT!'
|
14
14
|
|
15
|
-
## Familia::
|
15
|
+
## Familia::StringKey#value=
|
16
16
|
@a.value.value = 'DECENT!'
|
17
17
|
#=> 'DECENT!'
|
18
18
|
|
19
|
-
## Familia::
|
19
|
+
## Familia::StringKey#to_s
|
20
20
|
@a.value.to_s
|
21
21
|
#=> 'DECENT!'
|
22
22
|
|
23
|
-
## Familia::
|
23
|
+
## Familia::StringKey#destroy!
|
24
24
|
@a.value.delete!
|
25
25
|
#=> true
|
26
26
|
|
27
|
-
## Familia::
|
28
|
-
@ret = Familia::
|
27
|
+
## Familia::StringKey.new
|
28
|
+
@ret = Familia::StringKey.new 'arbitrary:key'
|
29
29
|
@ret.dbkey
|
30
30
|
#=> 'arbitrary:key'
|
31
31
|
|
@@ -37,27 +37,27 @@ require_relative '../helpers/test_helpers'
|
|
37
37
|
@ret.value
|
38
38
|
#=> '1000'
|
39
39
|
|
40
|
-
## Familia::
|
40
|
+
## Familia::StringKey#increment
|
41
41
|
@ret.increment
|
42
42
|
#=> 1001
|
43
43
|
|
44
|
-
## Familia::
|
44
|
+
## Familia::StringKey#incrementby
|
45
45
|
@ret.incrementby 99
|
46
46
|
#=> 1100
|
47
47
|
|
48
|
-
## Familia::
|
48
|
+
## Familia::StringKey#decrement
|
49
49
|
@ret.decrement
|
50
50
|
#=> 1099
|
51
51
|
|
52
|
-
## Familia::
|
52
|
+
## Familia::StringKey#decrementby
|
53
53
|
@ret.decrementby 49
|
54
54
|
#=> 1050
|
55
55
|
|
56
|
-
## Familia::
|
56
|
+
## Familia::StringKey#append
|
57
57
|
@ret.append 'bytes'
|
58
58
|
#=> 9
|
59
59
|
|
60
|
-
## Familia::
|
60
|
+
## Familia::StringKey#value after append
|
61
61
|
@ret.value
|
62
62
|
#=> '1050bytes'
|
63
63
|
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# try/data_types/unsortedset_try.rb
|
2
|
+
|
3
|
+
require_relative '../helpers/test_helpers'
|
4
|
+
|
5
|
+
@a = Bone.new 'atoken'
|
6
|
+
|
7
|
+
## Familia::UnsortedSet#add
|
8
|
+
ret = @a.tags.add :a
|
9
|
+
ret.class
|
10
|
+
#=> Familia::UnsortedSet
|
11
|
+
|
12
|
+
## Familia::UnsortedSet#<<
|
13
|
+
ret = @a.tags << :a << :b << :c
|
14
|
+
ret.class
|
15
|
+
#=> Familia::UnsortedSet
|
16
|
+
|
17
|
+
## Familia::UnsortedSet#members
|
18
|
+
@a.tags.members.sort
|
19
|
+
#=> ['a', 'b', 'c']
|
20
|
+
|
21
|
+
## Familia::UnsortedSet#member? knows when a value exists
|
22
|
+
@a.tags.member? :a
|
23
|
+
#=> true
|
24
|
+
|
25
|
+
## Familia::UnsortedSet#member? knows when a value doesn't exist
|
26
|
+
@a.tags.member? :x
|
27
|
+
#=> false
|
28
|
+
|
29
|
+
## Familia::UnsortedSet#member? knows when a value doesn't exist
|
30
|
+
@a.tags.size
|
31
|
+
#=> 3
|
32
|
+
|
33
|
+
@a.tags.delete!
|