synthra 0.1.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 +7 -0
- data/.rspec +4 -0
- data/.rubocop.yml +40 -0
- data/.yardopts +18 -0
- data/ACCESS_DOCS.md +116 -0
- data/ADVANCED_FEATURES_SUMMARY.md +245 -0
- data/CHANGELOG.md +498 -0
- data/CODE_OF_CONDUCT.md +122 -0
- data/CONTRIBUTING.md +307 -0
- data/DOCUMENTATION.md +204 -0
- data/DOCUMENTATION_GUIDE.md +194 -0
- data/LICENSE +22 -0
- data/README.md +1458 -0
- data/Rakefile +128 -0
- data/benchmark/README.md +591 -0
- data/benchmark/batch_generation.rb +63 -0
- data/benchmark/engine_comparison.rb +295 -0
- data/benchmark/single_record.rb +108 -0
- data/benchmark/streaming.rb +74 -0
- data/docs/ACTIVERECORD_INFERENCE.md +524 -0
- data/docs/API_SERVER.md +278 -0
- data/docs/CONFIG_FILE.md +315 -0
- data/docs/DATA_CONTRACTS.md +312 -0
- data/docs/ENHANCED_REPL.md +304 -0
- data/docs/FACTORY_BOT.md +271 -0
- data/docs/GITHUB_ACTION.md +420 -0
- data/docs/GRAPHQL_EXPORT.md +303 -0
- data/docs/GRAPHQL_FEDERATION.md +651 -0
- data/docs/HOW_TO_GENERATE_DOCS.md +252 -0
- data/docs/LSP.md +189 -0
- data/docs/MIGRATION_GENERATOR.md +547 -0
- data/docs/MOCK_SERVER.md +280 -0
- data/docs/NATIVE_ENGINE.md +298 -0
- data/docs/OPENAPI_EXPORT.md +252 -0
- data/docs/PERFORMANCE_MODE.md +228 -0
- data/docs/PERSONAS.md +547 -0
- data/docs/PROPERTY_TESTING.md +284 -0
- data/docs/PROTOBUF_EXPORT.md +276 -0
- data/docs/QUALITY_METRICS.md +555 -0
- data/docs/QUICK_REFERENCE.md +88 -0
- data/docs/RAILS_ENGINE.md +404 -0
- data/docs/RAILS_INTEGRATION.md +454 -0
- data/docs/README.md +175 -0
- data/docs/REPL_QUICK_REFERENCE.md +149 -0
- data/docs/RUST_INTEGRATION_GUIDE.md +1376 -0
- data/docs/SCENARIOS.md +576 -0
- data/docs/SECURITY_TESTING.md +318 -0
- data/docs/SNAPSHOT_TESTING.md +308 -0
- data/docs/STRING_TEXT_TYPES_REFERENCE.md +512 -0
- data/docs/TERRAFORM_EXPORT.md +447 -0
- data/docs/TIME_TRAVEL.md +507 -0
- data/docs/USAGE_GUIDE.md +980 -0
- data/docs/WEBHOOK_SIMULATOR.md +579 -0
- data/docs/advanced_features.md +183 -0
- data/docs/api_reference.md +153 -0
- data/docs/behaviors.md +138 -0
- data/docs/best_practices.md +191 -0
- data/docs/dsl_reference.md +172 -0
- data/docs/examples.md +162 -0
- data/docs/generation_modes.md +125 -0
- data/docs/getting_started.md +92 -0
- data/docs/index.html +177 -0
- data/docs/strategic/CLOUD_REGISTRY_ARCHITECTURE.md +268 -0
- data/docs/strategic/SIMD_OPTIMIZATION_STRATEGY.md +153 -0
- data/docs/troubleshooting.md +215 -0
- data/docs/type_reference.md +224 -0
- data/examples/hostile_mode_demo.rb +64 -0
- data/exe/synthra +6 -0
- data/ext/synthra_native/Cargo.lock +972 -0
- data/ext/synthra_native/Cargo.toml +46 -0
- data/ext/synthra_native/extconf.rb +41 -0
- data/ext/synthra_native/src/generator.rs +397 -0
- data/ext/synthra_native/src/lib.rs +229 -0
- data/ext/synthra_native/src/types.rs +1485 -0
- data/lib/generators/synthra/install_generator.rb +86 -0
- data/lib/generators/synthra/templates/api_response.dsl +15 -0
- data/lib/generators/synthra/templates/fake_data.rake +116 -0
- data/lib/generators/synthra/templates/synthra.yml +31 -0
- data/lib/generators/synthra/templates/synthra_support.rb +19 -0
- data/lib/generators/synthra/templates/user.dsl +11 -0
- data/lib/synthra/activerecord_inference.rb +394 -0
- data/lib/synthra/api.rb +381 -0
- data/lib/synthra/api_server.rb +718 -0
- data/lib/synthra/behaviors/applicator.rb +165 -0
- data/lib/synthra/behaviors/base.rb +155 -0
- data/lib/synthra/behaviors/close_connection.rb +60 -0
- data/lib/synthra/behaviors/deprecated.rb +100 -0
- data/lib/synthra/behaviors/failure.rb +69 -0
- data/lib/synthra/behaviors/latency.rb +103 -0
- data/lib/synthra/behaviors/partial_data.rb +83 -0
- data/lib/synthra/behaviors/randomize_order.rb +74 -0
- data/lib/synthra/behaviors/registry.rb +238 -0
- data/lib/synthra/behaviors/simulate_error.rb +79 -0
- data/lib/synthra/cli/commands/base.rb +105 -0
- data/lib/synthra/cli/commands/diff.rb +227 -0
- data/lib/synthra/cli/commands/docs.rb +67 -0
- data/lib/synthra/cli/commands/export.rb +150 -0
- data/lib/synthra/cli/commands/generate.rb +72 -0
- data/lib/synthra/cli/commands/import.rb +80 -0
- data/lib/synthra/cli/commands/lint.rb +53 -0
- data/lib/synthra/cli/commands/live.rb +57 -0
- data/lib/synthra/cli/commands/seed.rb +99 -0
- data/lib/synthra/cli/commands/validate.rb +28 -0
- data/lib/synthra/cli.rb +2471 -0
- data/lib/synthra/config_file.rb +129 -0
- data/lib/synthra/configuration.rb +281 -0
- data/lib/synthra/contracts_registry.rb +408 -0
- data/lib/synthra/database_seeder.rb +268 -0
- data/lib/synthra/deterministic_ids.rb +218 -0
- data/lib/synthra/documentation_generator.rb +414 -0
- data/lib/synthra/engine.rb +251 -0
- data/lib/synthra/errors.rb +1169 -0
- data/lib/synthra/export/base.rb +85 -0
- data/lib/synthra/export/csv.rb +101 -0
- data/lib/synthra/export/graphql.rb +266 -0
- data/lib/synthra/export/graphql_federation.rb +377 -0
- data/lib/synthra/export/graphviz.rb +258 -0
- data/lib/synthra/export/javascript.rb +327 -0
- data/lib/synthra/export/json_data.rb +61 -0
- data/lib/synthra/export/json_schema.rb +290 -0
- data/lib/synthra/export/openapi.rb +514 -0
- data/lib/synthra/export/protobuf.rb +483 -0
- data/lib/synthra/export/python.rb +560 -0
- data/lib/synthra/export/sql.rb +381 -0
- data/lib/synthra/export/sql_insert.rb +152 -0
- data/lib/synthra/export/terraform.rb +501 -0
- data/lib/synthra/export/type_mapping.rb +389 -0
- data/lib/synthra/export/typescript.rb +300 -0
- data/lib/synthra/export/xml_data.rb +104 -0
- data/lib/synthra/export/yaml_data.rb +56 -0
- data/lib/synthra/export.rb +404 -0
- data/lib/synthra/factory_bot_integration.rb +157 -0
- data/lib/synthra/field.rb +440 -0
- data/lib/synthra/functions/registry.rb +104 -0
- data/lib/synthra/generator/context.rb +372 -0
- data/lib/synthra/generator/engine.rb +336 -0
- data/lib/synthra/generator/faker_adapter.rb +425 -0
- data/lib/synthra/generator/modes.rb +444 -0
- data/lib/synthra/generator/resolver.rb +256 -0
- data/lib/synthra/generator/rng.rb +273 -0
- data/lib/synthra/generator/streamer.rb +63 -0
- data/lib/synthra/generator/uniqueness.rb +118 -0
- data/lib/synthra/initializer.rb +97 -0
- data/lib/synthra/limits.rb +279 -0
- data/lib/synthra/live_preview.rb +518 -0
- data/lib/synthra/loader_config.rb +78 -0
- data/lib/synthra/lsp/server.rb +689 -0
- data/lib/synthra/migration_generator.rb +301 -0
- data/lib/synthra/mixin.rb +174 -0
- data/lib/synthra/mock_server.rb +458 -0
- data/lib/synthra/native_engine.rb +304 -0
- data/lib/synthra/openapi_importer.rb +228 -0
- data/lib/synthra/output/json_formatter.rb +40 -0
- data/lib/synthra/output/ndjson_formatter.rb +55 -0
- data/lib/synthra/parser/ast.rb +1287 -0
- data/lib/synthra/parser/lexer.rb +1152 -0
- data/lib/synthra/parser/parser.rb +1664 -0
- data/lib/synthra/parser/tokens.rb +461 -0
- data/lib/synthra/performance_mode.rb +364 -0
- data/lib/synthra/personas.rb +397 -0
- data/lib/synthra/property_testing.rb +172 -0
- data/lib/synthra/quality_metrics.rb +405 -0
- data/lib/synthra/rails_test_helper.rb +248 -0
- data/lib/synthra/registry.rb +533 -0
- data/lib/synthra/relationships.rb +193 -0
- data/lib/synthra/repl/enhanced_repl.rb +607 -0
- data/lib/synthra/repl/formatter.rb +191 -0
- data/lib/synthra/scenarios.rb +423 -0
- data/lib/synthra/schema.rb +605 -0
- data/lib/synthra/schema_inheritance.rb +104 -0
- data/lib/synthra/schema_versioning.rb +212 -0
- data/lib/synthra/snapshot_testing.rb +199 -0
- data/lib/synthra/time_travel.rb +338 -0
- data/lib/synthra/type_definitions.rb +274 -0
- data/lib/synthra/types/address_location/addresses.rb +125 -0
- data/lib/synthra/types/address_location/airports.rb +200 -0
- data/lib/synthra/types/address_location/banks_hospitals.rb +207 -0
- data/lib/synthra/types/address_location/locations.rb +406 -0
- data/lib/synthra/types/base.rb +48 -0
- data/lib/synthra/types/commerce_products/commerce.rb +119 -0
- data/lib/synthra/types/commerce_products/companies.rb +71 -0
- data/lib/synthra/types/commerce_products/construction.rb +126 -0
- data/lib/synthra/types/commerce_products/products.rb +205 -0
- data/lib/synthra/types/core/collections.rb +513 -0
- data/lib/synthra/types/core/defaults.rb +76 -0
- data/lib/synthra/types/core/enums.rb +102 -0
- data/lib/synthra/types/core/identifiers.rb +445 -0
- data/lib/synthra/types/core/primitives.rb +586 -0
- data/lib/synthra/types/core/references.rb +466 -0
- data/lib/synthra/types/core/sequences.rb +304 -0
- data/lib/synthra/types/crypto/crypto.rb +162 -0
- data/lib/synthra/types/date_time/dates.rb +387 -0
- data/lib/synthra/types/finance_banking/banking.rb +424 -0
- data/lib/synthra/types/finance_banking/credit_cards.rb +24 -0
- data/lib/synthra/types/finance_banking/identifiers.rb +93 -0
- data/lib/synthra/types/formula.rb +184 -0
- data/lib/synthra/types/health_medical/medical.rb +150 -0
- data/lib/synthra/types/hostile_payloads.rb +122 -0
- data/lib/synthra/types/json_array.rb +51 -0
- data/lib/synthra/types/media_entertainment/media.rb +62 -0
- data/lib/synthra/types/naughty_string.rb +30 -0
- data/lib/synthra/types/personal_names/chinese.rb +41 -0
- data/lib/synthra/types/personal_names/identifiers.rb +187 -0
- data/lib/synthra/types/personal_names/names.rb +246 -0
- data/lib/synthra/types/personal_names/national_id.rb +89 -0
- data/lib/synthra/types/personal_names/titles_suffixes.rb +41 -0
- data/lib/synthra/types/regex.rb +248 -0
- data/lib/synthra/types/registry.rb +182 -0
- data/lib/synthra/types/repeating_element.rb +50 -0
- data/lib/synthra/types/scenario.rb +29 -0
- data/lib/synthra/types/technology_internet/apps.rb +67 -0
- data/lib/synthra/types/technology_internet/communication.rb +162 -0
- data/lib/synthra/types/technology_internet/devices.rb +80 -0
- data/lib/synthra/types/technology_internet/formats.rb +139 -0
- data/lib/synthra/types/technology_internet/networking.rb +143 -0
- data/lib/synthra/types/template.rb +92 -0
- data/lib/synthra/types/text_content/business.rb +128 -0
- data/lib/synthra/types/text_content/colors.rb +70 -0
- data/lib/synthra/types/text_content/misc.rb +237 -0
- data/lib/synthra/types/text_content/security.rb +130 -0
- data/lib/synthra/types/text_content/text_generation.rb +532 -0
- data/lib/synthra/types/travel/travel.rb +150 -0
- data/lib/synthra/utils/string_distance.rb +133 -0
- data/lib/synthra/validator/dsl_validator.rb +339 -0
- data/lib/synthra/validator/path_validator.rb +615 -0
- data/lib/synthra/version.rb +35 -0
- data/lib/synthra/webhook_simulator.rb +341 -0
- data/lib/synthra.rb +259 -0
- data/schemas/address.dsl +16 -0
- data/schemas/api_response.dsl +8 -0
- data/schemas/error_payload.dsl +9 -0
- data/schemas/order.dsl +10 -0
- data/schemas/order_item.dsl +8 -0
- data/schemas/payment.dsl +11 -0
- data/schemas/social_post.dsl +13 -0
- data/schemas/user.dsl +10 -0
- data/scripts/batch_fix_all.rb +96 -0
- data/scripts/delete_old_files.rb +32 -0
- data/scripts/fix_all_grouped_files.rb +137 -0
- data/scripts/fix_all_indentation.rb +48 -0
- data/scripts/fix_all_syntax.rb +124 -0
- data/scripts/fix_grouped_files.rb +184 -0
- data/scripts/fix_syntax_errors.rb +108 -0
- data/scripts/group_domain_types.rb +112 -0
- data/scripts/group_domain_types_fixed.rb +150 -0
- data/scripts/merge_domains_to_one_file.rb +68 -0
- data/scripts/move_existing_types.rb +130 -0
- data/scripts/split_grouped_types.rb +142 -0
- data/tech_docs/README.md +134 -0
- data/tech_docs/advanced/streaming.md +405 -0
- data/tech_docs/advanced/thread_safety.md +253 -0
- data/tech_docs/api/overview.md +485 -0
- data/tech_docs/appendices/type_chart.md +193 -0
- data/tech_docs/basic_concepts.md +383 -0
- data/tech_docs/behaviors/overview.md +346 -0
- data/tech_docs/dsl/complex_types.md +790 -0
- data/tech_docs/dsl/core_types.md +464 -0
- data/tech_docs/dsl/datetime_types.md +325 -0
- data/tech_docs/dsl/field_modifiers.md +414 -0
- data/tech_docs/dsl/grammar.md +431 -0
- data/tech_docs/dsl/schema_definition.md +399 -0
- data/tech_docs/export/README.md +276 -0
- data/tech_docs/installation.md +273 -0
- data/tech_docs/integration/ci_cd.md +707 -0
- data/tech_docs/integration/ci_cd_guide.md +579 -0
- data/tech_docs/integration/factory_bot.md +485 -0
- data/tech_docs/integration/rails.md +630 -0
- data/tech_docs/integration/rspec.md +449 -0
- data/tech_docs/modes/overview.md +350 -0
- data/tech_docs/performance/NATIVE_RUST_EXTENSION.md +1270 -0
- data/tech_docs/performance/OPTIMIZATION_GUIDE.md +901 -0
- data/tech_docs/quick_start.md +256 -0
- data/tech_docs/templates/README.md +805 -0
- data/tech_docs/tutorials/advanced.md +371 -0
- data/tech_docs/tutorials/getting_started.md +189 -0
- data/tech_docs/tutorials/intermediate.md +231 -0
- data/tech_docs/tutorials/template_gallery.md +569 -0
- data/tech_example/01_basic_usage.rb +238 -0
- data/tech_example/02_types_demo.rb +336 -0
- data/tech_example/04_cli_usage.md +429 -0
- data/tech_example/05_database_seeding.rb +283 -0
- data/tech_example/07_rspec_integration.rb +359 -0
- data/tech_example/10_custom_types.rb +387 -0
- data/tech_example/12_behaviors.rb +372 -0
- data/tech_example/13_twitter_dm_example.rb +120 -0
- data/tech_example/14_exact_json_structure.rb +253 -0
- data/tech_example/16_lsp_server.rb +56 -0
- data/tech_example/17_property_testing.rb +92 -0
- data/tech_example/18_enhanced_repl.rb +120 -0
- data/tech_example/19_security_fuzzing.rb +145 -0
- data/tech_example/NEW_FEATURES.md +169 -0
- data/tech_example/README.md +118 -0
- data/tech_example/schemas/api_response.dsl +123 -0
- data/tech_example/schemas/ecommerce.dsl +121 -0
- data/tech_example/schemas/twitter_dm.dsl +109 -0
- data/tech_example/schemas/user.dsl +36 -0
- data/vscode-extension/README.md +246 -0
- data/vscode-extension/language-configuration.json +31 -0
- data/vscode-extension/package.json +55 -0
- data/vscode-extension/snippets/fakedatadsl.json +198 -0
- data/vscode-extension/syntaxes/fakedatadsl.tmLanguage.json +128 -0
- metadata +478 -0
|
@@ -0,0 +1,1169 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# =============================================================================
|
|
4
|
+
|
|
5
|
+
# Synthra Error Classes
|
|
6
|
+
# =============================================================================
|
|
7
|
+
#
|
|
8
|
+
# This file defines all error classes used throughout Synthra.
|
|
9
|
+
# Errors are organized into categories:
|
|
10
|
+
#
|
|
11
|
+
# 1. **Parsing Errors** - Raised during DSL parsing (syntax, type, indentation)
|
|
12
|
+
# 2. **Generation Errors** - Raised during data generation (uniqueness, references)
|
|
13
|
+
# 3. **Resource Limit Errors** - Raised when configured limits are exceeded
|
|
14
|
+
# 4. **Simulated Errors** - Intentionally raised by behaviors for testing
|
|
15
|
+
#
|
|
16
|
+
# All errors inherit from Synthra::Errors::Error which inherits from StandardError.
|
|
17
|
+
#
|
|
18
|
+
# =============================================================================
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
module Synthra
|
|
22
|
+
|
|
23
|
+
# Container module for all Synthra error classes
|
|
24
|
+
#
|
|
25
|
+
# This module provides a namespace for error organization. All errors
|
|
26
|
+
# are also aliased at the Synthra module level for convenience.
|
|
27
|
+
#
|
|
28
|
+
# @example Catching any Synthra error
|
|
29
|
+
# begin
|
|
30
|
+
# schema.generate
|
|
31
|
+
# rescue Synthra::Error => e
|
|
32
|
+
# puts "Synthra error: #{e.message}"
|
|
33
|
+
# end
|
|
34
|
+
#
|
|
35
|
+
# @example Catching specific error types
|
|
36
|
+
# begin
|
|
37
|
+
# registry.load_file("schema.dsl")
|
|
38
|
+
# rescue Synthra::ParseError => e
|
|
39
|
+
# puts "Parse error at line #{e.line}: #{e.message}"
|
|
40
|
+
# rescue Synthra::GenerationError => e
|
|
41
|
+
# puts "Generation error: #{e.message}"
|
|
42
|
+
# end
|
|
43
|
+
#
|
|
44
|
+
|
|
45
|
+
module Errors
|
|
46
|
+
|
|
47
|
+
# Base error class for all Synthra errors
|
|
48
|
+
#
|
|
49
|
+
# All Synthra errors inherit from this class, allowing you to
|
|
50
|
+
# catch all gem-related errors with a single rescue clause.
|
|
51
|
+
#
|
|
52
|
+
# @example Catch all Synthra errors
|
|
53
|
+
# begin
|
|
54
|
+
# Synthra.load("schema.dsl").generate
|
|
55
|
+
# rescue Synthra::Errors::Error => e
|
|
56
|
+
# logger.error("Synthra error: #{e.message}")
|
|
57
|
+
# end
|
|
58
|
+
#
|
|
59
|
+
|
|
60
|
+
class Error < StandardError
|
|
61
|
+
|
|
62
|
+
# Machine-readable error code for programmatic error handling
|
|
63
|
+
ERROR_CODE = "SYNTHRA_ERROR"
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# ============================================================================
|
|
67
|
+
|
|
68
|
+
# Parsing Errors
|
|
69
|
+
# ============================================================================
|
|
70
|
+
#
|
|
71
|
+
# These errors are raised when there are problems parsing DSL files.
|
|
72
|
+
# They include location information (line, column) to help identify
|
|
73
|
+
# the source of the problem.
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
# Base class for parsing errors with location information
|
|
78
|
+
#
|
|
79
|
+
# ParseError and its subclasses include line and column numbers
|
|
80
|
+
# to help locate the source of syntax problems in DSL files.
|
|
81
|
+
# The error message is automatically formatted to include this
|
|
82
|
+
# location information.
|
|
83
|
+
#
|
|
84
|
+
# @!attribute [r] line
|
|
85
|
+
# @return [Integer, nil] the line number where the error occurred (1-based)
|
|
86
|
+
#
|
|
87
|
+
# @!attribute [r] column
|
|
88
|
+
# @return [Integer, nil] the column number where the error occurred (1-based)
|
|
89
|
+
#
|
|
90
|
+
# @!attribute [r] source_line
|
|
91
|
+
# @return [String, nil] the content of the source line with the error
|
|
92
|
+
#
|
|
93
|
+
# @!attribute [r] source_context
|
|
94
|
+
# @return [Array<String>, nil] lines before/after for context
|
|
95
|
+
#
|
|
96
|
+
# @!attribute [r] suggestions
|
|
97
|
+
# @return [Array<String>, nil] "did you mean" suggestions
|
|
98
|
+
#
|
|
99
|
+
# @example Error with location
|
|
100
|
+
# begin
|
|
101
|
+
# Synthra.load("bad.dsl")
|
|
102
|
+
# rescue Synthra::ParseError => e
|
|
103
|
+
# puts "Error at line #{e.line}, column #{e.column}"
|
|
104
|
+
# puts e.message
|
|
105
|
+
# # Output:
|
|
106
|
+
# # Error at line 5, column 10
|
|
107
|
+
# #
|
|
108
|
+
# # 3 | User:
|
|
109
|
+
# # 4 | id: uuid
|
|
110
|
+
# # > 5 | name: strng
|
|
111
|
+
# # ^^^^^
|
|
112
|
+
# # 6 | email: email
|
|
113
|
+
# #
|
|
114
|
+
# # Unknown type 'strng'. Did you mean: string, text?
|
|
115
|
+
# end
|
|
116
|
+
#
|
|
117
|
+
|
|
118
|
+
# Raised when a schema references an unknown mixin. Was referenced in mixin.rb but never
|
|
119
|
+
# defined, so the unknown-mixin path raised NameError instead of this clean error.
|
|
120
|
+
class MixinError < Error
|
|
121
|
+
ERROR_CODE = "MIXIN_ERROR"
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
class ParseError < Error
|
|
125
|
+
ERROR_CODE = "PARSE_ERROR"
|
|
126
|
+
attr_reader :line, :column, :source_line, :source_context, :suggestions
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
# Create a new ParseError with location information
|
|
130
|
+
#
|
|
131
|
+
# @param message [String] the error message describing the problem
|
|
132
|
+
# @param line [Integer, nil] line number where error occurred (1-based)
|
|
133
|
+
# @param column [Integer, nil] column number where error occurred (1-based)
|
|
134
|
+
# @param source_line [String, nil] the source line content for context
|
|
135
|
+
# @param source_context [Array<String>, nil] surrounding lines for context
|
|
136
|
+
# @param suggestions [Array<String>, nil] "did you mean" suggestions
|
|
137
|
+
#
|
|
138
|
+
# @example
|
|
139
|
+
# raise ParseError.new("Unexpected token", line: 5, column: 10, source_line: " bad: ^invalid")
|
|
140
|
+
#
|
|
141
|
+
|
|
142
|
+
def initialize(message, line: nil, column: nil, source_line: nil, source_context: nil, suggestions: nil)
|
|
143
|
+
@line = line
|
|
144
|
+
@column = column
|
|
145
|
+
@source_line = source_line
|
|
146
|
+
@source_context = source_context
|
|
147
|
+
@suggestions = suggestions
|
|
148
|
+
|
|
149
|
+
full_message = build_message(message)
|
|
150
|
+
super(full_message)
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
private
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
# Build a formatted error message with location context
|
|
157
|
+
#
|
|
158
|
+
# Creates a user-friendly error message that includes:
|
|
159
|
+
# - The base error message
|
|
160
|
+
# - Line and column numbers
|
|
161
|
+
# - Source context with line numbers and pointer
|
|
162
|
+
# - "Did you mean" suggestions
|
|
163
|
+
#
|
|
164
|
+
# @param message [String] the base error message
|
|
165
|
+
# @return [String] the formatted message with location context
|
|
166
|
+
#
|
|
167
|
+
|
|
168
|
+
def build_message(message)
|
|
169
|
+
parts = [message]
|
|
170
|
+
parts << "at line #{line}" if line
|
|
171
|
+
parts << "column #{column}" if column
|
|
172
|
+
|
|
173
|
+
# Add source context if available
|
|
174
|
+
if source_context&.any?
|
|
175
|
+
parts << "\n\n#{format_source_context}"
|
|
176
|
+
elsif source_line
|
|
177
|
+
parts << "\n #{source_line}"
|
|
178
|
+
parts << "\n #{" " * ([column.to_i - 1, 0].max)}^" if column
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# Add suggestions if available
|
|
182
|
+
if suggestions&.any?
|
|
183
|
+
parts << "\n\n#{Utils::StringDistance.format_suggestions(suggestions)}"
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
parts.join(" ").strip
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
# Format source context with line numbers
|
|
191
|
+
#
|
|
192
|
+
# @return [String] formatted source context
|
|
193
|
+
#
|
|
194
|
+
# :nocov:
|
|
195
|
+
def format_source_context
|
|
196
|
+
return "" unless source_context&.any?
|
|
197
|
+
|
|
198
|
+
lines = []
|
|
199
|
+
context_start_line = [line.to_i - source_context.length / 2, 1].max
|
|
200
|
+
|
|
201
|
+
source_context.each_with_index do |content, idx|
|
|
202
|
+
current_line = context_start_line + idx
|
|
203
|
+
line_num = current_line.to_s.rjust(5)
|
|
204
|
+
|
|
205
|
+
if current_line == line
|
|
206
|
+
lines << " > #{line_num} | #{content}"
|
|
207
|
+
if column && column > 0
|
|
208
|
+
pointer = " " * (10 + [column - 1, 0].max) + "^"
|
|
209
|
+
lines << pointer
|
|
210
|
+
end
|
|
211
|
+
else
|
|
212
|
+
lines << " #{line_num} | #{content}"
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
lines.join("\n")
|
|
217
|
+
end
|
|
218
|
+
# :nocov:
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
# Syntax error in DSL file
|
|
223
|
+
#
|
|
224
|
+
# Raised when the parser encounters invalid syntax that doesn't
|
|
225
|
+
# match the expected DSL grammar.
|
|
226
|
+
#
|
|
227
|
+
# @example
|
|
228
|
+
# # Missing colon after field name
|
|
229
|
+
# # User:
|
|
230
|
+
# # name text <- SyntaxError: expected ':'
|
|
231
|
+
#
|
|
232
|
+
|
|
233
|
+
class SyntaxError < ParseError
|
|
234
|
+
ERROR_CODE = "SYNTAX_ERROR"
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
# Unknown type referenced in DSL
|
|
239
|
+
#
|
|
240
|
+
# Raised when a field uses a type that hasn't been registered.
|
|
241
|
+
# This could be a typo or a custom type that wasn't defined.
|
|
242
|
+
# Includes "did you mean" suggestions for similar type names.
|
|
243
|
+
#
|
|
244
|
+
# @!attribute [r] type_name
|
|
245
|
+
# @return [String] the unknown type name that was referenced
|
|
246
|
+
#
|
|
247
|
+
# @example
|
|
248
|
+
# # User:
|
|
249
|
+
# # name: strng <- UnknownTypeError: Unknown type 'strng'. Did you mean: string, text?
|
|
250
|
+
#
|
|
251
|
+
|
|
252
|
+
class UnknownTypeError < ParseError
|
|
253
|
+
ERROR_CODE = "UNKNOWN_TYPE_ERROR"
|
|
254
|
+
attr_reader :type_name
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
# Create a new UnknownTypeError
|
|
258
|
+
#
|
|
259
|
+
# @param type_name [String] the type name that wasn't found
|
|
260
|
+
# @param suggestions [Array<String>] similar type names
|
|
261
|
+
# @param kwargs [Hash] location information (line, column, source_line)
|
|
262
|
+
#
|
|
263
|
+
|
|
264
|
+
def initialize(type_name, suggestions: nil, **kwargs)
|
|
265
|
+
@type_name = type_name
|
|
266
|
+
super("Unknown type '#{type_name}'", suggestions: suggestions, **kwargs)
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
# Invalid path in copy() reference
|
|
272
|
+
#
|
|
273
|
+
# Raised when a copy() type references a path that doesn't exist
|
|
274
|
+
# in the schema structure. Includes "did you mean" suggestions
|
|
275
|
+
# for similar paths.
|
|
276
|
+
#
|
|
277
|
+
# @!attribute [r] path
|
|
278
|
+
# @return [String] the invalid path that was referenced
|
|
279
|
+
#
|
|
280
|
+
# @!attribute [r] available_paths
|
|
281
|
+
# @return [Array<String>] list of valid paths available
|
|
282
|
+
#
|
|
283
|
+
# @example
|
|
284
|
+
# # copy("users.snder.id") <- PathError: Path 'users.snder.id' not found.
|
|
285
|
+
# # Did you mean: users.sender.id?
|
|
286
|
+
#
|
|
287
|
+
|
|
288
|
+
class PathError < ParseError
|
|
289
|
+
ERROR_CODE = "PATH_ERROR"
|
|
290
|
+
attr_reader :path, :available_paths
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
# Create a new PathError
|
|
294
|
+
#
|
|
295
|
+
# @param path [String] the path that wasn't found
|
|
296
|
+
# @param available_paths [Array<String>] list of valid paths
|
|
297
|
+
# @param suggestions [Array<String>] similar paths
|
|
298
|
+
# @param kwargs [Hash] location information (line, column, source_line)
|
|
299
|
+
#
|
|
300
|
+
|
|
301
|
+
def initialize(path, available_paths: [], suggestions: nil, **kwargs)
|
|
302
|
+
@path = path
|
|
303
|
+
@available_paths = available_paths
|
|
304
|
+
super("Path '#{path}' not found in schema", suggestions: suggestions, **kwargs)
|
|
305
|
+
end
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
# Circular schema reference detected
|
|
310
|
+
#
|
|
311
|
+
# Raised when schemas reference each other in a cycle that would cause
|
|
312
|
+
# infinite recursion during data generation.
|
|
313
|
+
#
|
|
314
|
+
# @!attribute [r] cycle
|
|
315
|
+
# @return [Array<String>] the schemas involved in the cycle
|
|
316
|
+
#
|
|
317
|
+
# @example Circular reference
|
|
318
|
+
# # Parent:
|
|
319
|
+
# # child: Child
|
|
320
|
+
# # Child:
|
|
321
|
+
# # parent: Parent <- Circular!
|
|
322
|
+
#
|
|
323
|
+
|
|
324
|
+
class CycleError < ParseError
|
|
325
|
+
ERROR_CODE = "CYCLE_ERROR"
|
|
326
|
+
attr_reader :cycle
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
# Create a new CycleError
|
|
330
|
+
#
|
|
331
|
+
# @param cycle [Array<String>] list of schema names in the cycle
|
|
332
|
+
# @param kwargs [Hash] additional options
|
|
333
|
+
#
|
|
334
|
+
|
|
335
|
+
def initialize(cycle, **kwargs)
|
|
336
|
+
@cycle = cycle
|
|
337
|
+
cycle_path = cycle.join(" -> ")
|
|
338
|
+
super("Circular schema reference detected: #{cycle_path}", **kwargs)
|
|
339
|
+
end
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
# Field order error for copy() references
|
|
344
|
+
#
|
|
345
|
+
# Raised when a copy() field references another field that is defined
|
|
346
|
+
# after it in the schema. Since fields are generated in definition order,
|
|
347
|
+
# this would result in nil values.
|
|
348
|
+
#
|
|
349
|
+
# @!attribute [r] field_name
|
|
350
|
+
# @return [String] the name of the copy field
|
|
351
|
+
#
|
|
352
|
+
# @!attribute [r] copy_path
|
|
353
|
+
# @return [String] the path being copied
|
|
354
|
+
#
|
|
355
|
+
# @!attribute [r] schema_name
|
|
356
|
+
# @return [String] the schema containing the error
|
|
357
|
+
#
|
|
358
|
+
# @example Field order problem
|
|
359
|
+
# # Order:
|
|
360
|
+
# # user_id: copy("user.id") <- ERROR: user not defined yet!
|
|
361
|
+
# # user: User
|
|
362
|
+
#
|
|
363
|
+
|
|
364
|
+
class FieldOrderError < ParseError
|
|
365
|
+
ERROR_CODE = "FIELD_ORDER_ERROR"
|
|
366
|
+
attr_reader :field_name, :copy_path, :schema_name
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
# Create a new FieldOrderError
|
|
370
|
+
#
|
|
371
|
+
# @param field_name [String] the copy field name
|
|
372
|
+
# @param copy_path [String] the path being copied
|
|
373
|
+
# @param schema_name [String] the schema name
|
|
374
|
+
# @param suggestion [String] how to fix the error
|
|
375
|
+
# @param kwargs [Hash] additional options
|
|
376
|
+
#
|
|
377
|
+
|
|
378
|
+
def initialize(field_name:, copy_path:, schema_name:, suggestion: nil, **kwargs)
|
|
379
|
+
@field_name = field_name
|
|
380
|
+
@copy_path = copy_path
|
|
381
|
+
@schema_name = schema_name
|
|
382
|
+
|
|
383
|
+
message = "Field order error in '#{schema_name}': " \
|
|
384
|
+
"'#{field_name}' uses copy(\"#{copy_path}\") but the source field is defined after it"
|
|
385
|
+
|
|
386
|
+
super(message, suggestions: suggestion ? [suggestion] : nil, **kwargs)
|
|
387
|
+
end
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
# Invalid probability specification
|
|
392
|
+
#
|
|
393
|
+
# Raised when enum probabilities exceed 100% total.
|
|
394
|
+
#
|
|
395
|
+
# @!attribute [r] total
|
|
396
|
+
# @return [Numeric] the total probability that exceeded 100%
|
|
397
|
+
#
|
|
398
|
+
# @example
|
|
399
|
+
# # status: enum(active:60%, inactive:60%) <- total 120% > 100%
|
|
400
|
+
#
|
|
401
|
+
|
|
402
|
+
class InvalidProbabilityError < ParseError
|
|
403
|
+
ERROR_CODE = "INVALID_PROBABILITY_ERROR"
|
|
404
|
+
attr_reader :total
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
# Create a new InvalidProbabilityError
|
|
408
|
+
#
|
|
409
|
+
# @param total [Numeric] the total probability percentage
|
|
410
|
+
# @param kwargs [Hash] location information (line, column, source_line)
|
|
411
|
+
#
|
|
412
|
+
|
|
413
|
+
def initialize(total, **kwargs)
|
|
414
|
+
@total = total
|
|
415
|
+
super("Probability total #{total}% exceeds 100%", **kwargs)
|
|
416
|
+
end
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
# Indentation error in DSL file
|
|
421
|
+
#
|
|
422
|
+
# Raised when indentation doesn't match the expected pattern.
|
|
423
|
+
# Synthra uses 2-space indentation consistently.
|
|
424
|
+
#
|
|
425
|
+
# @!attribute [r] expected
|
|
426
|
+
# @return [Integer] the expected number of spaces
|
|
427
|
+
#
|
|
428
|
+
# @!attribute [r] actual
|
|
429
|
+
# @return [Integer] the actual number of spaces found
|
|
430
|
+
#
|
|
431
|
+
# @example
|
|
432
|
+
# # User:
|
|
433
|
+
# # name: text <- 3 spaces instead of 2
|
|
434
|
+
#
|
|
435
|
+
|
|
436
|
+
class IndentationError < ParseError
|
|
437
|
+
ERROR_CODE = "INDENTATION_ERROR"
|
|
438
|
+
attr_reader :expected, :actual
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
# Create a new IndentationError
|
|
442
|
+
#
|
|
443
|
+
# @param expected [Integer] expected number of spaces
|
|
444
|
+
# @param actual [Integer] actual number of spaces found
|
|
445
|
+
# @param kwargs [Hash] location information (line, column, source_line)
|
|
446
|
+
#
|
|
447
|
+
|
|
448
|
+
def initialize(expected:, actual:, **kwargs)
|
|
449
|
+
@expected = expected
|
|
450
|
+
@actual = actual
|
|
451
|
+
super("Invalid indentation: expected #{expected} spaces, got #{actual}", **kwargs)
|
|
452
|
+
end
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
# ============================================================================
|
|
456
|
+
|
|
457
|
+
# Simulyra DSL Validation Errors
|
|
458
|
+
# ============================================================================
|
|
459
|
+
#
|
|
460
|
+
# These errors are raised when validating Simulyra DSL structure.
|
|
461
|
+
# They enforce the strict separation between Schema, API, and Scenario layers.
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
# Base class for Simulyra DSL validation errors
|
|
465
|
+
#
|
|
466
|
+
# ValidationError provides structured error messages with suggestions
|
|
467
|
+
# for how to fix the problem.
|
|
468
|
+
#
|
|
469
|
+
# @!attribute [r] suggestion
|
|
470
|
+
# @return [String, nil] suggestion for how to fix the error
|
|
471
|
+
#
|
|
472
|
+
|
|
473
|
+
class ValidationError < ParseError
|
|
474
|
+
ERROR_CODE = "VALIDATION_ERROR"
|
|
475
|
+
attr_reader :suggestion
|
|
476
|
+
|
|
477
|
+
# Create a new ValidationError
|
|
478
|
+
#
|
|
479
|
+
# @param message [String] error description
|
|
480
|
+
# @param line [Integer, nil] line number where error occurred
|
|
481
|
+
# @param suggestion [String, nil] suggestion for fixing the error
|
|
482
|
+
#
|
|
483
|
+
def initialize(message, line: nil, suggestion: nil, **kwargs)
|
|
484
|
+
@suggestion = suggestion
|
|
485
|
+
full_message = message
|
|
486
|
+
full_message += " -> #{suggestion}" if suggestion
|
|
487
|
+
super(full_message, line: line, **kwargs)
|
|
488
|
+
end
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
# Schema-level validation error
|
|
493
|
+
#
|
|
494
|
+
# Raised when there are problems with schema definitions.
|
|
495
|
+
#
|
|
496
|
+
# @example Duplicate schema names
|
|
497
|
+
# # SchemaError: Duplicate schema "User" -> Defined again at line 15
|
|
498
|
+
#
|
|
499
|
+
|
|
500
|
+
class SchemaError < ValidationError
|
|
501
|
+
ERROR_CODE = "SCHEMA_ERROR"
|
|
502
|
+
end
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
# API-level validation error
|
|
506
|
+
#
|
|
507
|
+
# Raised when there are problems with API definitions.
|
|
508
|
+
#
|
|
509
|
+
# @example API without scenarios
|
|
510
|
+
# # ApiError: API GET /users must define at least one scenario
|
|
511
|
+
#
|
|
512
|
+
|
|
513
|
+
class ApiError < ValidationError
|
|
514
|
+
ERROR_CODE = "API_ERROR"
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
# Scenario-level validation error
|
|
519
|
+
#
|
|
520
|
+
# Raised when there are problems with scenario definitions.
|
|
521
|
+
#
|
|
522
|
+
# @example Missing @status directive
|
|
523
|
+
# # ScenarioError: Scenario "Success" must define @status
|
|
524
|
+
#
|
|
525
|
+
|
|
526
|
+
class ScenarioError < ValidationError
|
|
527
|
+
ERROR_CODE = "SCENARIO_ERROR"
|
|
528
|
+
end
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
# Reference resolution error
|
|
532
|
+
#
|
|
533
|
+
# Raised when a schema(:Name) reference cannot be resolved.
|
|
534
|
+
#
|
|
535
|
+
# @example Unknown schema reference
|
|
536
|
+
# # ReferenceError: Schema "Users" is not defined -> Did you mean: User?
|
|
537
|
+
#
|
|
538
|
+
|
|
539
|
+
class ReferenceError < ValidationError
|
|
540
|
+
ERROR_CODE = "REFERENCE_ERROR"
|
|
541
|
+
end
|
|
542
|
+
|
|
543
|
+
|
|
544
|
+
# Context separation error
|
|
545
|
+
#
|
|
546
|
+
# Raised when DSL elements are used in the wrong context.
|
|
547
|
+
#
|
|
548
|
+
# @example HTTP directive in schema
|
|
549
|
+
# # ContextError: HTTP directives are not allowed inside schema definitions
|
|
550
|
+
#
|
|
551
|
+
|
|
552
|
+
class ContextError < ValidationError
|
|
553
|
+
ERROR_CODE = "CONTEXT_ERROR"
|
|
554
|
+
end
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
# Type-level validation error
|
|
558
|
+
#
|
|
559
|
+
# Raised when type definitions have invalid syntax or unknown types.
|
|
560
|
+
#
|
|
561
|
+
# @example Invalid array syntax
|
|
562
|
+
# # TypeError: Arrays can only be created from schema references
|
|
563
|
+
#
|
|
564
|
+
|
|
565
|
+
class TypeError < ValidationError
|
|
566
|
+
ERROR_CODE = "TYPE_ERROR"
|
|
567
|
+
end
|
|
568
|
+
|
|
569
|
+
# ============================================================================
|
|
570
|
+
|
|
571
|
+
# Generation Errors
|
|
572
|
+
# ============================================================================
|
|
573
|
+
#
|
|
574
|
+
# These errors are raised during data generation when something goes wrong.
|
|
575
|
+
# They indicate problems with schema definitions, references, or constraints.
|
|
576
|
+
|
|
577
|
+
|
|
578
|
+
|
|
579
|
+
# Base class for errors that occur during data generation
|
|
580
|
+
#
|
|
581
|
+
# GenerationError and its subclasses are raised when the schema is valid
|
|
582
|
+
# but something goes wrong during the actual data generation process.
|
|
583
|
+
#
|
|
584
|
+
# @example
|
|
585
|
+
# begin
|
|
586
|
+
# schema.generate(count: 1000)
|
|
587
|
+
# rescue Synthra::GenerationError => e
|
|
588
|
+
# puts "Could not generate data: #{e.message}"
|
|
589
|
+
# end
|
|
590
|
+
#
|
|
591
|
+
|
|
592
|
+
class GenerationError < Error
|
|
593
|
+
ERROR_CODE = "GENERATION_ERROR"
|
|
594
|
+
end
|
|
595
|
+
|
|
596
|
+
# Raised when a DSL feature needs a dangerous opt-in that is disabled by
|
|
597
|
+
# default — e.g. the `formula` type's eval. Default-safe: surfaces a clear
|
|
598
|
+
# error instead of silently executing tenant-supplied Ruby. Inherits from
|
|
599
|
+
# Error (not GenerationError) so a generic `rescue` in a type generator
|
|
600
|
+
# cannot swallow it back into a silent value.
|
|
601
|
+
class SecurityError < Error
|
|
602
|
+
ERROR_CODE = "SECURITY_ERROR"
|
|
603
|
+
end
|
|
604
|
+
|
|
605
|
+
|
|
606
|
+
# Uniqueness constraint could not be satisfied
|
|
607
|
+
#
|
|
608
|
+
# Raised when the generator cannot produce a unique value after
|
|
609
|
+
# multiple attempts. This typically happens when generating many
|
|
610
|
+
# records with unique fields that have limited possible values.
|
|
611
|
+
#
|
|
612
|
+
# @!attribute [r] field
|
|
613
|
+
# @return [String] the field name that requires uniqueness
|
|
614
|
+
#
|
|
615
|
+
# @!attribute [r] attempts
|
|
616
|
+
# @return [Integer] number of attempts made before giving up
|
|
617
|
+
#
|
|
618
|
+
# @!attribute [r] last_values
|
|
619
|
+
# @return [Array] the last few values that were rejected as duplicates
|
|
620
|
+
#
|
|
621
|
+
# @example
|
|
622
|
+
# # When generating 1000 users with unique emails from small domain
|
|
623
|
+
# # UniquenessError: Could not generate unique value for 'email' after 100 attempts
|
|
624
|
+
#
|
|
625
|
+
|
|
626
|
+
class UniquenessError < GenerationError
|
|
627
|
+
ERROR_CODE = "UNIQUENESS_ERROR"
|
|
628
|
+
attr_reader :field, :attempts, :last_values, :schema_name
|
|
629
|
+
|
|
630
|
+
|
|
631
|
+
# Create a new UniquenessError
|
|
632
|
+
#
|
|
633
|
+
# @param field [String] the field name that requires uniqueness
|
|
634
|
+
# @param attempts [Integer] number of generation attempts made
|
|
635
|
+
# @param last_values [Array] the last values attempted (for debugging)
|
|
636
|
+
# @param schema_name [String, nil] the schema name where the error occurred
|
|
637
|
+
#
|
|
638
|
+
|
|
639
|
+
def initialize(field:, attempts: nil, last_values: nil, schema_name: nil)
|
|
640
|
+
@field = field
|
|
641
|
+
@attempts = attempts || Synthra.configuration.max_unique_retries
|
|
642
|
+
@last_values = last_values || []
|
|
643
|
+
@schema_name = schema_name
|
|
644
|
+
message = "Could not generate unique value for '#{field}'"
|
|
645
|
+
message += " in schema '#{schema_name}'" if schema_name
|
|
646
|
+
message += " after #{@attempts} attempts"
|
|
647
|
+
message += ". Last values: #{@last_values.first(5).inspect}" unless @last_values.empty?
|
|
648
|
+
super(message)
|
|
649
|
+
end
|
|
650
|
+
end
|
|
651
|
+
|
|
652
|
+
|
|
653
|
+
# Cyclic reference detected between schemas
|
|
654
|
+
#
|
|
655
|
+
# Raised when schemas reference each other in a cycle, which would
|
|
656
|
+
# cause infinite recursion during generation.
|
|
657
|
+
#
|
|
658
|
+
# @!attribute [r] cycle
|
|
659
|
+
# @return [Array<String>] the schema names forming the cycle
|
|
660
|
+
#
|
|
661
|
+
# @example
|
|
662
|
+
# # User references Order, Order references User
|
|
663
|
+
# # CyclicReferenceError: Cyclic reference detected: User -> Order -> User
|
|
664
|
+
#
|
|
665
|
+
|
|
666
|
+
class CyclicReferenceError < GenerationError
|
|
667
|
+
ERROR_CODE = "CYCLIC_REFERENCE_ERROR"
|
|
668
|
+
attr_reader :cycle
|
|
669
|
+
|
|
670
|
+
|
|
671
|
+
# Create a new CyclicReferenceError
|
|
672
|
+
#
|
|
673
|
+
# @param cycle [Array<String>] the schema names in the reference cycle
|
|
674
|
+
#
|
|
675
|
+
|
|
676
|
+
def initialize(cycle)
|
|
677
|
+
@cycle = cycle
|
|
678
|
+
cycle_str = cycle.join(" -> ")
|
|
679
|
+
super("Cyclic reference detected: #{cycle_str}")
|
|
680
|
+
end
|
|
681
|
+
end
|
|
682
|
+
|
|
683
|
+
|
|
684
|
+
# Referenced schema or field not found
|
|
685
|
+
#
|
|
686
|
+
# Raised when a Ref() references a schema or field that doesn't exist.
|
|
687
|
+
#
|
|
688
|
+
# @!attribute [r] schema_name
|
|
689
|
+
# @return [String] the schema name that was referenced
|
|
690
|
+
#
|
|
691
|
+
# @!attribute [r] field_path
|
|
692
|
+
# @return [String, nil] the field path within the schema (if applicable)
|
|
693
|
+
#
|
|
694
|
+
# @example
|
|
695
|
+
# # user_id: Ref(NonExistent.id)
|
|
696
|
+
# # MissingReferenceError: Reference not found: NonExistent.id
|
|
697
|
+
#
|
|
698
|
+
|
|
699
|
+
class MissingReferenceError < GenerationError
|
|
700
|
+
ERROR_CODE = "MISSING_REFERENCE_ERROR"
|
|
701
|
+
attr_reader :schema_name, :field_path
|
|
702
|
+
|
|
703
|
+
|
|
704
|
+
# Create a new MissingReferenceError
|
|
705
|
+
#
|
|
706
|
+
# @param schema_name [String] the schema name that wasn't found
|
|
707
|
+
# @param field_path [String, nil] the field path if referencing a specific field
|
|
708
|
+
#
|
|
709
|
+
|
|
710
|
+
def initialize(schema_name:, field_path: nil)
|
|
711
|
+
@schema_name = schema_name
|
|
712
|
+
@field_path = field_path
|
|
713
|
+
|
|
714
|
+
message = if field_path
|
|
715
|
+
"Reference not found: #{schema_name}.#{field_path}"
|
|
716
|
+
else
|
|
717
|
+
"Schema not found: #{schema_name}"
|
|
718
|
+
end
|
|
719
|
+
super(message)
|
|
720
|
+
end
|
|
721
|
+
end
|
|
722
|
+
|
|
723
|
+
|
|
724
|
+
# Custom function not registered
|
|
725
|
+
#
|
|
726
|
+
# Raised when a custom() type references a function that hasn't
|
|
727
|
+
# been registered with Synthra.register_function.
|
|
728
|
+
#
|
|
729
|
+
# @!attribute [r] function_name
|
|
730
|
+
# @return [Symbol] the function name that wasn't found
|
|
731
|
+
#
|
|
732
|
+
# @example
|
|
733
|
+
# # full_name: custom(:compute_name)
|
|
734
|
+
# # MissingFunctionError: Custom function not registered: compute_name
|
|
735
|
+
#
|
|
736
|
+
|
|
737
|
+
class MissingFunctionError < GenerationError
|
|
738
|
+
ERROR_CODE = "MISSING_FUNCTION_ERROR"
|
|
739
|
+
attr_reader :function_name
|
|
740
|
+
|
|
741
|
+
|
|
742
|
+
# Create a new MissingFunctionError
|
|
743
|
+
#
|
|
744
|
+
# @param function_name [Symbol, String] the function name that wasn't registered
|
|
745
|
+
#
|
|
746
|
+
|
|
747
|
+
def initialize(function_name)
|
|
748
|
+
@function_name = function_name
|
|
749
|
+
super("Custom function not registered: #{function_name}")
|
|
750
|
+
end
|
|
751
|
+
end
|
|
752
|
+
|
|
753
|
+
|
|
754
|
+
# Error evaluating a conditional field
|
|
755
|
+
#
|
|
756
|
+
# Raised when the condition expression for a conditional field
|
|
757
|
+
# cannot be evaluated, typically due to referencing a non-existent field.
|
|
758
|
+
#
|
|
759
|
+
# @!attribute [r] condition
|
|
760
|
+
# @return [String] the condition expression that failed
|
|
761
|
+
#
|
|
762
|
+
# @!attribute [r] original_error
|
|
763
|
+
# @return [Exception, nil] the underlying error if one occurred
|
|
764
|
+
#
|
|
765
|
+
# @example
|
|
766
|
+
# # admin_note: text if is_admin
|
|
767
|
+
# # ConditionError: Error evaluating condition 'is_admin'
|
|
768
|
+
#
|
|
769
|
+
|
|
770
|
+
class ConditionError < GenerationError
|
|
771
|
+
ERROR_CODE = "CONDITION_ERROR"
|
|
772
|
+
attr_reader :condition, :original_error
|
|
773
|
+
|
|
774
|
+
|
|
775
|
+
# Create a new ConditionError
|
|
776
|
+
#
|
|
777
|
+
# @param condition [String] the condition expression that failed
|
|
778
|
+
# @param original_error [Exception, nil] the underlying error
|
|
779
|
+
#
|
|
780
|
+
|
|
781
|
+
def initialize(condition:, original_error: nil)
|
|
782
|
+
@condition = condition
|
|
783
|
+
@original_error = original_error
|
|
784
|
+
|
|
785
|
+
message = "Error evaluating condition '#{condition}'"
|
|
786
|
+
message += ": #{original_error.message}" if original_error
|
|
787
|
+
super(message)
|
|
788
|
+
end
|
|
789
|
+
end
|
|
790
|
+
|
|
791
|
+
# ============================================================================
|
|
792
|
+
|
|
793
|
+
# Resource Limit Errors
|
|
794
|
+
# ============================================================================
|
|
795
|
+
#
|
|
796
|
+
# These errors are raised when configured resource limits are exceeded.
|
|
797
|
+
# They protect against runaway generation (infinite loops, huge arrays, etc.)
|
|
798
|
+
|
|
799
|
+
|
|
800
|
+
|
|
801
|
+
# Base class for resource limit exceeded errors
|
|
802
|
+
#
|
|
803
|
+
# ResourceLimitError and its subclasses are raised when generation
|
|
804
|
+
# would exceed configured safety limits. These limits prevent accidental
|
|
805
|
+
# resource exhaustion during testing.
|
|
806
|
+
#
|
|
807
|
+
# @example Handling limit errors
|
|
808
|
+
# begin
|
|
809
|
+
# schema.generate
|
|
810
|
+
# rescue Synthra::ResourceLimitError => e
|
|
811
|
+
# puts "Limit exceeded: #{e.message}"
|
|
812
|
+
# puts "Configure limits via Synthra.configure"
|
|
813
|
+
# end
|
|
814
|
+
#
|
|
815
|
+
|
|
816
|
+
class ResourceLimitError < Error
|
|
817
|
+
ERROR_CODE = "RESOURCE_LIMIT_ERROR"
|
|
818
|
+
end
|
|
819
|
+
|
|
820
|
+
|
|
821
|
+
# Latency exceeds configured maximum
|
|
822
|
+
#
|
|
823
|
+
# Raised when the @latency behavior specifies a delay that exceeds
|
|
824
|
+
# the configured max_latency_ms limit.
|
|
825
|
+
#
|
|
826
|
+
# @!attribute [r] requested
|
|
827
|
+
# @return [Integer] the requested latency in milliseconds
|
|
828
|
+
#
|
|
829
|
+
# @!attribute [r] max_allowed
|
|
830
|
+
# @return [Integer] the maximum allowed latency in milliseconds
|
|
831
|
+
#
|
|
832
|
+
# @example
|
|
833
|
+
# # @latency 60000 <- 60 seconds exceeds default 10 second max
|
|
834
|
+
# # LatencyLimitError: Latency 60000ms exceeds maximum allowed 10000ms
|
|
835
|
+
#
|
|
836
|
+
|
|
837
|
+
class LatencyLimitError < ResourceLimitError
|
|
838
|
+
ERROR_CODE = "LATENCY_LIMIT_ERROR"
|
|
839
|
+
attr_reader :requested, :max_allowed
|
|
840
|
+
|
|
841
|
+
|
|
842
|
+
# Create a new LatencyLimitError
|
|
843
|
+
#
|
|
844
|
+
# @param requested [Integer] the requested latency in milliseconds
|
|
845
|
+
# @param max_allowed [Integer] the configured maximum latency
|
|
846
|
+
#
|
|
847
|
+
|
|
848
|
+
def initialize(requested:, max_allowed:)
|
|
849
|
+
@requested = requested
|
|
850
|
+
@max_allowed = max_allowed
|
|
851
|
+
super(
|
|
852
|
+
"Latency #{requested}ms exceeds maximum allowed #{max_allowed}ms. " \
|
|
853
|
+
"Configure via Synthra.configure { |c| c.limits.max_latency_ms = N }"
|
|
854
|
+
)
|
|
855
|
+
end
|
|
856
|
+
end
|
|
857
|
+
|
|
858
|
+
|
|
859
|
+
# Recursion depth exceeds configured maximum
|
|
860
|
+
#
|
|
861
|
+
# Raised when nested schema generation exceeds the maximum recursion
|
|
862
|
+
# depth, which could indicate a circular reference or overly deep nesting.
|
|
863
|
+
#
|
|
864
|
+
# @!attribute [r] depth
|
|
865
|
+
# @return [Integer] the current recursion depth
|
|
866
|
+
#
|
|
867
|
+
# @!attribute [r] max_allowed
|
|
868
|
+
# @return [Integer] the maximum allowed recursion depth
|
|
869
|
+
#
|
|
870
|
+
# @example
|
|
871
|
+
# # Deeply nested: User -> Profile -> Settings -> Preferences -> ...
|
|
872
|
+
# # RecursionLimitError: Recursion depth 11 exceeds maximum allowed 10
|
|
873
|
+
#
|
|
874
|
+
|
|
875
|
+
class RecursionLimitError < ResourceLimitError
|
|
876
|
+
ERROR_CODE = "RECURSION_LIMIT_ERROR"
|
|
877
|
+
attr_reader :depth, :max_allowed
|
|
878
|
+
|
|
879
|
+
|
|
880
|
+
# Create a new RecursionLimitError
|
|
881
|
+
#
|
|
882
|
+
# @param depth [Integer] the current recursion depth
|
|
883
|
+
# @param max_allowed [Integer] the configured maximum depth
|
|
884
|
+
#
|
|
885
|
+
|
|
886
|
+
def initialize(depth:, max_allowed:)
|
|
887
|
+
@depth = depth
|
|
888
|
+
@max_allowed = max_allowed
|
|
889
|
+
super(
|
|
890
|
+
"Recursion depth #{depth} exceeds maximum allowed #{max_allowed}. " \
|
|
891
|
+
"Configure via Synthra.configure { |c| c.limits.max_recursion = N }"
|
|
892
|
+
)
|
|
893
|
+
end
|
|
894
|
+
end
|
|
895
|
+
|
|
896
|
+
|
|
897
|
+
# Array size exceeds configured maximum
|
|
898
|
+
#
|
|
899
|
+
# Raised when generating an array with more elements than the
|
|
900
|
+
# configured max_array_size limit.
|
|
901
|
+
#
|
|
902
|
+
# @!attribute [r] size
|
|
903
|
+
# @return [Integer] the requested array size
|
|
904
|
+
#
|
|
905
|
+
# @!attribute [r] max_allowed
|
|
906
|
+
# @return [Integer] the maximum allowed array size
|
|
907
|
+
#
|
|
908
|
+
# @example
|
|
909
|
+
# # items: array(Item, 10000) <- exceeds default 1000 max
|
|
910
|
+
# # ArraySizeLimitError: Array size 10000 exceeds maximum allowed 1000
|
|
911
|
+
#
|
|
912
|
+
|
|
913
|
+
class ArraySizeLimitError < ResourceLimitError
|
|
914
|
+
ERROR_CODE = "ARRAY_SIZE_LIMIT_ERROR"
|
|
915
|
+
attr_reader :size, :max_allowed
|
|
916
|
+
|
|
917
|
+
|
|
918
|
+
# Create a new ArraySizeLimitError
|
|
919
|
+
#
|
|
920
|
+
# @param size [Integer] the requested array size
|
|
921
|
+
# @param max_allowed [Integer] the configured maximum size
|
|
922
|
+
#
|
|
923
|
+
|
|
924
|
+
def initialize(size:, max_allowed:)
|
|
925
|
+
@size = size
|
|
926
|
+
@max_allowed = max_allowed
|
|
927
|
+
super(
|
|
928
|
+
"Array size #{size} exceeds maximum allowed #{max_allowed}. " \
|
|
929
|
+
"Configure via Synthra.configure { |c| c.limits.max_array_size = N }"
|
|
930
|
+
)
|
|
931
|
+
end
|
|
932
|
+
end
|
|
933
|
+
|
|
934
|
+
|
|
935
|
+
# Text length exceeds configured maximum
|
|
936
|
+
#
|
|
937
|
+
# Raised when generating text with more characters than the
|
|
938
|
+
# configured max_text_length limit.
|
|
939
|
+
#
|
|
940
|
+
# @!attribute [r] length
|
|
941
|
+
# @return [Integer] the requested text length
|
|
942
|
+
#
|
|
943
|
+
# @!attribute [r] max_allowed
|
|
944
|
+
# @return [Integer] the maximum allowed text length
|
|
945
|
+
#
|
|
946
|
+
# @example
|
|
947
|
+
# # body: text(1..50000) <- exceeds default 10000 max
|
|
948
|
+
# # TextLengthLimitError: Text length 50000 exceeds maximum allowed 10000
|
|
949
|
+
#
|
|
950
|
+
|
|
951
|
+
class TextLengthLimitError < ResourceLimitError
|
|
952
|
+
ERROR_CODE = "TEXT_LENGTH_LIMIT_ERROR"
|
|
953
|
+
attr_reader :length, :max_allowed
|
|
954
|
+
|
|
955
|
+
|
|
956
|
+
# Create a new TextLengthLimitError
|
|
957
|
+
#
|
|
958
|
+
# @param length [Integer] the requested text length
|
|
959
|
+
# @param max_allowed [Integer] the maximum allowed text length
|
|
960
|
+
#
|
|
961
|
+
|
|
962
|
+
def initialize(length:, max_allowed:)
|
|
963
|
+
@length = length
|
|
964
|
+
@max_allowed = max_allowed
|
|
965
|
+
super(
|
|
966
|
+
"Text length #{length} exceeds maximum allowed #{max_allowed}. " \
|
|
967
|
+
"Configure via Synthra.configure { |c| c.limits.max_text_length = N }"
|
|
968
|
+
)
|
|
969
|
+
end
|
|
970
|
+
end
|
|
971
|
+
|
|
972
|
+
# ============================================================================
|
|
973
|
+
|
|
974
|
+
# Simulated Errors (Expected behavior for testing)
|
|
975
|
+
# ============================================================================
|
|
976
|
+
#
|
|
977
|
+
# These errors are intentionally raised by behaviors to simulate failure
|
|
978
|
+
# scenarios. They are expected errors, not bugs, and are useful for testing
|
|
979
|
+
# error handling in applications that consume generated data.
|
|
980
|
+
|
|
981
|
+
|
|
982
|
+
|
|
983
|
+
# Base class for simulated behavior errors
|
|
984
|
+
#
|
|
985
|
+
# Simulated errors are raised intentionally by behaviors like @failure,
|
|
986
|
+
# @close_connection, and @simulate_error. They help test how consuming
|
|
987
|
+
# applications handle various failure scenarios.
|
|
988
|
+
#
|
|
989
|
+
# @example Testing error handling
|
|
990
|
+
# begin
|
|
991
|
+
# api_mock.generate # Schema has @failure 10%
|
|
992
|
+
# rescue Synthra::SimulatedBehaviorError => e
|
|
993
|
+
# # This is expected - test that your app handles it correctly
|
|
994
|
+
# expect(app.last_error).to eq("Service unavailable")
|
|
995
|
+
# end
|
|
996
|
+
#
|
|
997
|
+
|
|
998
|
+
class SimulatedBehaviorError < Error
|
|
999
|
+
ERROR_CODE = "SIMULATED_BEHAVIOR_ERROR"
|
|
1000
|
+
end
|
|
1001
|
+
|
|
1002
|
+
|
|
1003
|
+
# Simulated failure (service unavailable)
|
|
1004
|
+
#
|
|
1005
|
+
# Raised by the @failure behavior to simulate a service being unavailable.
|
|
1006
|
+
# Useful for testing retry logic and error handling.
|
|
1007
|
+
#
|
|
1008
|
+
# @!attribute [r] probability
|
|
1009
|
+
# @return [Integer, nil] the configured failure probability percentage
|
|
1010
|
+
#
|
|
1011
|
+
# @example DSL usage
|
|
1012
|
+
# # API:
|
|
1013
|
+
# # @failure 10% <- 10% chance of SimulatedFailure
|
|
1014
|
+
# # id: uuid
|
|
1015
|
+
#
|
|
1016
|
+
|
|
1017
|
+
class SimulatedFailure < SimulatedBehaviorError
|
|
1018
|
+
ERROR_CODE = "SIMULATED_FAILURE"
|
|
1019
|
+
attr_reader :probability
|
|
1020
|
+
|
|
1021
|
+
|
|
1022
|
+
# Create a new SimulatedFailure
|
|
1023
|
+
#
|
|
1024
|
+
# @param probability [Integer, nil] the probability percentage if configured
|
|
1025
|
+
#
|
|
1026
|
+
|
|
1027
|
+
def initialize(probability: nil)
|
|
1028
|
+
@probability = probability
|
|
1029
|
+
message = "Simulated failure"
|
|
1030
|
+
message += " (#{probability}% probability)" if probability
|
|
1031
|
+
super(message)
|
|
1032
|
+
end
|
|
1033
|
+
end
|
|
1034
|
+
|
|
1035
|
+
|
|
1036
|
+
# Simulated connection drop
|
|
1037
|
+
#
|
|
1038
|
+
# Raised by the @close_connection behavior to simulate the connection
|
|
1039
|
+
# being closed unexpectedly. Useful for testing reconnection logic.
|
|
1040
|
+
#
|
|
1041
|
+
# @!attribute [r] probability
|
|
1042
|
+
# @return [Integer, nil] the configured probability percentage
|
|
1043
|
+
#
|
|
1044
|
+
# @example DSL usage
|
|
1045
|
+
# # Stream:
|
|
1046
|
+
# # @close_connection 5% <- 5% chance of SimulatedConnectionDrop
|
|
1047
|
+
# # data: text
|
|
1048
|
+
#
|
|
1049
|
+
|
|
1050
|
+
class SimulatedConnectionDrop < SimulatedBehaviorError
|
|
1051
|
+
ERROR_CODE = "SIMULATED_CONNECTION_DROP"
|
|
1052
|
+
attr_reader :probability
|
|
1053
|
+
|
|
1054
|
+
|
|
1055
|
+
# Create a new SimulatedConnectionDrop
|
|
1056
|
+
#
|
|
1057
|
+
# @param probability [Integer, nil] the probability percentage if configured
|
|
1058
|
+
#
|
|
1059
|
+
|
|
1060
|
+
def initialize(probability: nil)
|
|
1061
|
+
@probability = probability
|
|
1062
|
+
message = "Simulated connection drop"
|
|
1063
|
+
message += " (#{probability}% probability)" if probability
|
|
1064
|
+
super(message)
|
|
1065
|
+
end
|
|
1066
|
+
end
|
|
1067
|
+
|
|
1068
|
+
|
|
1069
|
+
# Simulated HTTP error
|
|
1070
|
+
#
|
|
1071
|
+
# Raised by the @simulate_error behavior to simulate specific HTTP
|
|
1072
|
+
# error responses. Useful for testing how applications handle various
|
|
1073
|
+
# HTTP status codes.
|
|
1074
|
+
#
|
|
1075
|
+
# @!attribute [r] code
|
|
1076
|
+
# @return [Integer] the HTTP status code being simulated
|
|
1077
|
+
#
|
|
1078
|
+
# @!attribute [r] probability
|
|
1079
|
+
# @return [Integer, nil] the configured probability percentage
|
|
1080
|
+
#
|
|
1081
|
+
# @example DSL usage
|
|
1082
|
+
# # API:
|
|
1083
|
+
# # @simulate_error 429:5% <- 5% chance of 429 Too Many Requests
|
|
1084
|
+
# # @simulate_error 500:1% <- 1% chance of 500 Internal Server Error
|
|
1085
|
+
# # id: uuid
|
|
1086
|
+
#
|
|
1087
|
+
|
|
1088
|
+
class SimulatedError < SimulatedBehaviorError
|
|
1089
|
+
ERROR_CODE = "SIMULATED_ERROR"
|
|
1090
|
+
attr_reader :code, :probability
|
|
1091
|
+
|
|
1092
|
+
|
|
1093
|
+
# Create a new SimulatedError
|
|
1094
|
+
#
|
|
1095
|
+
# @param code [Integer] the HTTP status code to simulate
|
|
1096
|
+
# @param probability [Integer, nil] the probability percentage if configured
|
|
1097
|
+
#
|
|
1098
|
+
|
|
1099
|
+
def initialize(code:, probability: nil)
|
|
1100
|
+
@code = code
|
|
1101
|
+
@probability = probability
|
|
1102
|
+
message = "Simulated HTTP error: #{code}"
|
|
1103
|
+
message += " (#{probability}% probability)" if probability
|
|
1104
|
+
super(message)
|
|
1105
|
+
end
|
|
1106
|
+
end
|
|
1107
|
+
end
|
|
1108
|
+
|
|
1109
|
+
# ============================================================================
|
|
1110
|
+
|
|
1111
|
+
# Module-Level Aliases
|
|
1112
|
+
# ============================================================================
|
|
1113
|
+
#
|
|
1114
|
+
# These aliases allow you to reference error classes directly from the
|
|
1115
|
+
# Synthra module without the Errors:: namespace prefix.
|
|
1116
|
+
#
|
|
1117
|
+
# @example Both of these work
|
|
1118
|
+
# rescue Synthra::Errors::ParseError => e
|
|
1119
|
+
# rescue Synthra::ParseError => e # Preferred
|
|
1120
|
+
|
|
1121
|
+
|
|
1122
|
+
|
|
1123
|
+
# @!parse
|
|
1124
|
+
# # Base error class (alias of Errors::Error)
|
|
1125
|
+
# class Error < StandardError; end
|
|
1126
|
+
|
|
1127
|
+
Error = Errors::Error
|
|
1128
|
+
|
|
1129
|
+
|
|
1130
|
+
# Parsing errors
|
|
1131
|
+
ParseError = Errors::ParseError
|
|
1132
|
+
SyntaxError = Errors::SyntaxError
|
|
1133
|
+
UnknownTypeError = Errors::UnknownTypeError
|
|
1134
|
+
PathError = Errors::PathError
|
|
1135
|
+
InvalidProbabilityError = Errors::InvalidProbabilityError
|
|
1136
|
+
IndentationError = Errors::IndentationError
|
|
1137
|
+
|
|
1138
|
+
# Simulyra DSL validation errors
|
|
1139
|
+
ValidationError = Errors::ValidationError
|
|
1140
|
+
SchemaError = Errors::SchemaError
|
|
1141
|
+
ApiError = Errors::ApiError
|
|
1142
|
+
ScenarioError = Errors::ScenarioError
|
|
1143
|
+
ReferenceError = Errors::ReferenceError
|
|
1144
|
+
ContextError = Errors::ContextError
|
|
1145
|
+
# Note: Don't alias TypeError as it conflicts with Ruby's built-in TypeError
|
|
1146
|
+
|
|
1147
|
+
# Generation errors
|
|
1148
|
+
GenerationError = Errors::GenerationError
|
|
1149
|
+
UniquenessError = Errors::UniquenessError
|
|
1150
|
+
CyclicReferenceError = Errors::CyclicReferenceError
|
|
1151
|
+
MissingReferenceError = Errors::MissingReferenceError
|
|
1152
|
+
MissingFunctionError = Errors::MissingFunctionError
|
|
1153
|
+
ConditionError = Errors::ConditionError
|
|
1154
|
+
|
|
1155
|
+
|
|
1156
|
+
# Resource limit errors
|
|
1157
|
+
ResourceLimitError = Errors::ResourceLimitError
|
|
1158
|
+
LatencyLimitError = Errors::LatencyLimitError
|
|
1159
|
+
RecursionLimitError = Errors::RecursionLimitError
|
|
1160
|
+
ArraySizeLimitError = Errors::ArraySizeLimitError
|
|
1161
|
+
TextLengthLimitError = Errors::TextLengthLimitError
|
|
1162
|
+
|
|
1163
|
+
|
|
1164
|
+
# Simulated behavior errors
|
|
1165
|
+
SimulatedBehaviorError = Errors::SimulatedBehaviorError
|
|
1166
|
+
SimulatedFailure = Errors::SimulatedFailure
|
|
1167
|
+
SimulatedConnectionDrop = Errors::SimulatedConnectionDrop
|
|
1168
|
+
SimulatedError = Errors::SimulatedError
|
|
1169
|
+
end
|