test

package
v0.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 21, 2025 License: MIT Imports: 3 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var AdditionalEdgeCaseTests = []Case{

	{"quote_in_string", `name eq "John \"The Great\" Doe"`, rule.D{"name": `John "The Great" Doe`}, true},
	{"single_quote_in_string", `name eq "John's book"`, rule.D{"name": "John's book"}, true},
	{"string_with_spaces", `text eq "hello world"`, rule.D{"text": "hello world"}, true},
	{"string_with_numbers", `code eq "ABC123"`, rule.D{"code": "ABC123"}, true},
	{"escaped_backslash", `path eq "C:\\Users\\John"`, rule.D{"path": `C:\Users\John`}, true},
	{"escaped_newline", `text eq "Line 1\nLine 2"`, rule.D{"text": "Line 1\nLine 2"}, true},
	{"escaped_tab", `text eq "Column1\tColumn2"`, rule.D{"text": "Column1\tColumn2"}, true},

	{"bool_true_caps", `active eq "TRUE"`, rule.D{"active": "TRUE"}, true},
	{"bool_false_caps", `active eq "FALSE"`, rule.D{"active": "FALSE"}, true},
	{"bool_mixed_case", `active eq "True"`, rule.D{"active": "True"}, true},

	{"unicode_emoji", `message co "🚀"`, rule.D{"message": "Launch 🚀 successful"}, true},
	{"unicode_accents", `name eq "José"`, rule.D{"name": "José"}, true},
	{"unicode_chinese", `text co "你好"`, rule.D{"text": "Hello 你好 World"}, true},

	{"very_large_float", `x lt 999999999999999999.0`, rule.D{"x": 123456789.0}, true},
	{"very_small_float", `x gt 0.000000000000001`, rule.D{"x": 0.001}, true},
	{"negative_zero", `x eq -0.0`, rule.D{"x": 0.0}, true},

	{"nested_array_deep", `user.permissions.roles in ["admin", "user"]`, rule.D{
		"user": rule.D{
			"permissions": rule.D{
				"roles": "admin",
			},
		},
	}, true},

	{"very_long_string", `text co "needle"`, rule.D{
		"text": "This is a very long string that contains the word needle somewhere in the middle of all this text that goes on and on and on and on and on and on and on and on and on and on and on and on and on and on and on and on and on and on and on and on and on and on and on and on and on and on and on and on",
	}, true},

	{"empty_string_contains_empty", `x co ""`, rule.D{"x": "hello"}, true},
	{"empty_string_starts_with_empty", `x sw ""`, rule.D{"x": "hello"}, true},
	{"empty_string_ends_with_empty", `x ew ""`, rule.D{"x": "hello"}, true},

	{"zero_string_vs_number", `x eq "0"`, rule.D{"x": 0}, false},
	{"false_string_vs_bool", `x eq "false"`, rule.D{"x": false}, false},
	{"null_string_literal", `x eq "null"`, rule.D{"x": "null"}, true},
}

AdditionalEdgeCaseTests contains additional edge case tests for comprehensive coverage.

View Source
var AdvancedPrecedenceTests = []Case{

	{"precedence_and_or", "a eq 1 and b eq 2 or c eq 3", rule.D{"a": 1, "b": 2, "c": 4}, true},
	{"precedence_and_or_2", "a eq 1 and b eq 2 or c eq 3", rule.D{"a": 2, "b": 2, "c": 3}, true},
	{"precedence_and_or_3", "a eq 1 and b eq 2 or c eq 3", rule.D{"a": 2, "b": 3, "c": 4}, false},

	{"not_with_and_or", "not a eq 1 and b eq 2", rule.D{"a": 2, "b": 2}, true},
	{"not_with_and_or_2", "not a eq 1 or b eq 2", rule.D{"a": 1, "b": 3}, false},
	{"not_with_and_or_3", "not a eq 1 or b eq 2", rule.D{"a": 2, "b": 3}, true},

	{
		"long_chain",
		"a eq 1 and b eq 2 and c eq 3 or d eq 4 and e eq 5",
		rule.D{"a": 1, "b": 2, "c": 3, "d": 0, "e": 0},
		true,
	},
	{
		"long_chain_2",
		"a eq 1 and b eq 2 and c eq 3 or d eq 4 and e eq 5",
		rule.D{"a": 0, "b": 0, "c": 0, "d": 4, "e": 5},
		true,
	},
	{
		"long_chain_3",
		"a eq 1 and b eq 2 and c eq 3 or d eq 4 and e eq 5",
		rule.D{"a": 0, "b": 0, "c": 0, "d": 0, "e": 0},
		false,
	},
}
View Source
var ArrayEdgeCaseTests = []Case{

	{"mixed_array_string", `x in ["1", "42", "3.14"]`, rule.D{
		"x": "42",
	}, true},
	{"mixed_array_number", "x in [1, 42, 3.14]", rule.D{
		"x": 42,
	}, true},
	{"mixed_array_no_match", `x in ["test", "42", "false"]`, rule.D{
		"x": 42,
	}, false},

	{"nested_in_comparison", `user.role in permissions.allowed`, rule.D{
		"user":        rule.D{"role": "admin"},
		"permissions": rule.D{"allowed": []any{"admin", "moderator"}},
	}, true},
	{"deep_nested_in", "a.b.c in d.e.f", rule.D{
		"a": rule.D{"b": rule.D{"c": "value"}},
		"d": rule.D{"e": rule.D{"f": []any{"value", "other"}}},
	}, true},

	{"array_with_floats", "x in [1.0, 2.5, 3.14, 4.8]", rule.D{
		"x": 3.14,
	}, true},
	{"array_with_versions", `x in ["1.0.0", "1.2.3", "2.0.0"]`, rule.D{
		"x": "1.2.3",
	}, true},
}
View Source
var BoundaryConditionTests = []Case{

	{"empty_context_missing", "x eq 10", rule.D{}, false},
	{"empty_context_presence", "x pr", rule.D{}, false},

	{"nil_value_comparison", "x eq null", rule.D{"x": nil}, false},
	{"nil_value_presence", "x pr", rule.D{"x": nil}, true},

	{"empty_vs_missing", `x eq ""`, rule.D{"x": ""}, true},
	{"empty_vs_missing_2", `x eq ""`, rule.D{}, false},

	{"zero_vs_missing", "x eq 0", rule.D{"x": 0}, true},
	{"zero_vs_missing_2", "x eq 0", rule.D{}, false},

	{"false_vs_missing", "x eq false", rule.D{"x": false}, true},
	{"false_vs_missing_2", "x eq false", rule.D{}, false},
}
View Source
var ComplexLogicalTests = []Case{

	{"complex_nested_logic", "((a.x eq b.y) and (c.z gt d.w)) or ((e.f co g.h) and (i.j in k.l))", rule.D{
		"a": rule.D{"x": 10},
		"b": rule.D{"y": 10},
		"c": rule.D{"z": 20},
		"d": rule.D{"w": 15},
		"e": rule.D{"f": "hello world"},
		"g": rule.D{"h": "world"},
		"i": rule.D{"j": "admin"},
		"k": rule.D{"l": []any{"admin", "user"}},
	}, true},

	{"chained_comparisons", "a eq b and b eq c and c eq d", rule.D{
		"a": 42,
		"b": 42,
		"c": 42,
		"d": 42,
	}, true},
	{"chained_comparisons_fail", "a eq b and b eq c and c eq d", rule.D{
		"a": 42,
		"b": 42,
		"c": 42,
		"d": 43,
	}, false},

	{"complex_not_nested", "not (a.b eq c.d and e.f gt g.h)", rule.D{
		"a": rule.D{"b": 10},
		"c": rule.D{"d": 10},
		"e": rule.D{"f": 5},
		"g": rule.D{"h": 15},
	}, true},
	{"double_not", "not (not (x eq y))", rule.D{"x": 42, "y": 42}, true},
}
View Source
var ComplexNestedLogicTests = []Case{

	{
		"deeply_nested_logic",
		"((a eq b) and (c eq d)) or ((e eq f) and (g eq h)) or ((i eq j) and (k eq l))",
		rule.D{
			"a": 1, "b": 2, "c": 3, "d": 3, "e": 5, "f": 6, "g": 7, "h": 8, "i": 9, "j": 9, "k": 11, "l": 11,
		},
		true,
	},

	{
		"mixed_operators_complex",
		`(user.age ge 18 and user.verified eq true) and (user.email co "@" and user.domain ne "banned.com") or user.role eq "admin"`,
		rule.D{
			"user": rule.D{
				"age":      25,
				"verified": true,
				"email":    "user@example.com",
				"domain":   "example.com",
				"role":     "user",
			},
		},
		true,
	},

	{"multiple_nots", "not (not (not (x eq 1)))", rule.D{"x": 1}, false},
	{"not_complex_expression", "not ((a eq b and c eq d) or (e eq f and g eq h))", rule.D{
		"a": 1, "b": 1, "c": 2, "d": 2, "e": 3, "f": 4, "g": 5, "h": 6,
	}, false},
}
View Source
var ComplexStringPatternTests = []Case{

	{
		"email_validation",
		`email co "@" and email co "." and email sw "user"`,
		rule.D{"email": "user@example.com"},
		true,
	},
	{
		"email_validation_2",
		`email co "@" and email co "." and email sw "admin"`,
		rule.D{"email": "user@example.com"},
		false,
	},

	{
		"url_validation",
		`url sw "https://" and url co "example.com" and url ew "/path"`,
		rule.D{"url": "https://example.com/path"},
		true,
	},
	{
		"url_validation_2",
		`url sw "http://" and url co "example.com" and url ew ".html"`,
		rule.D{"url": "http://example.com/page.html"},
		true,
	},

	{"json_pattern", `data sw "{" and data ew "}" and data co "key"`, rule.D{"data": `{"key": "value"}`}, true},

	{
		"sql_pattern",
		`query sw "SELECT" and query co "FROM" and query co "WHERE"`,
		rule.D{"query": "SELECT * FROM users WHERE active = true"},
		true,
	},

	{
		"file_path_unix",
		`path sw "/" and path co "home" and path ew ".txt"`,
		rule.D{"path": "/home/user/document.txt"},
		true,
	},
	{
		"file_path_windows",
		`path sw "C:" and path co "Users" and path ew ".doc"`,
		rule.D{"path": "C:\\Users\\John\\file.doc"},
		true,
	},
}
View Source
var DateTimeComprehensiveTests = []Case{

	{"datetime_prop_unix_vs_unix_after", `start_time af end_time`, rule.D{
		"start_time": int64(1720558321),
		"end_time":   int64(1720558320),
	}, true},
	{"datetime_prop_unix_vs_unix_before", `start_time be end_time`, rule.D{
		"start_time": int64(1720558319),
		"end_time":   int64(1720558320),
	}, true},
	{"datetime_prop_unix_vs_unix_equal", `start_time dq end_time`, rule.D{
		"start_time": int64(1720558320),
		"end_time":   int64(1720558320),
	}, true},
	{"datetime_prop_unix_vs_unix_not_equal", `start_time dn end_time`, rule.D{
		"start_time": int64(1720558321),
		"end_time":   int64(1720558320),
	}, true},
	{"datetime_prop_unix_vs_unix_before_or_equal", `start_time bq end_time`, rule.D{
		"start_time": int64(1720558320),
		"end_time":   int64(1720558320),
	}, true},
	{"datetime_prop_unix_vs_unix_after_or_equal", `start_time aq end_time`, rule.D{
		"start_time": int64(1720558320),
		"end_time":   int64(1720558320),
	}, true},

	{"datetime_prop_rfc_vs_rfc_after", `created_at af updated_at`, rule.D{
		"created_at": "2024-07-09T22:12:01Z",
		"updated_at": "2024-07-09T22:12:00Z",
	}, true},
	{"datetime_prop_rfc_vs_rfc_before", `created_at be updated_at`, rule.D{
		"created_at": "2024-07-09T22:11:59Z",
		"updated_at": "2024-07-09T22:12:00Z",
	}, true},
	{"datetime_prop_rfc_vs_rfc_equal", `created_at dq updated_at`, rule.D{
		"created_at": "2024-07-09T22:12:00Z",
		"updated_at": "2024-07-09T22:12:00Z",
	}, true},
	{"datetime_prop_rfc_vs_rfc_timezone_equal", `created_at dq updated_at`, rule.D{
		"created_at": "2024-07-09T19:12:00-03:00",
		"updated_at": "2024-07-09T22:12:00Z",
	}, true},

	{"datetime_prop_mixed_rfc_vs_unix", `created_at af timestamp`, rule.D{
		"created_at": "2024-07-09T22:12:01Z",
		"timestamp":  int64(1720558320),
	}, true},
	{"datetime_prop_mixed_unix_vs_rfc", `timestamp be created_at`, rule.D{
		"timestamp":  int64(1720558319),
		"created_at": "2024-07-09T22:12:00Z",
	}, true},

	{"datetime_nested_prop_vs_literal_rfc", `event.created_at af "2024-07-09T22:12:00Z"`, rule.D{
		"event": rule.D{
			"created_at": "2024-07-09T22:12:01Z",
		},
	}, true},
	{"datetime_nested_prop_vs_literal_unix", `session.timestamp be 1720558320`, rule.D{
		"session": rule.D{
			"timestamp": int64(1720558319),
		},
	}, true},
	{"datetime_deep_nested_prop", `user.profile.last_login dq "2024-07-09T22:12:00Z"`, rule.D{
		"user": rule.D{
			"profile": rule.D{
				"last_login": "2024-07-09T22:12:00Z",
			},
		},
	}, true},

	{"datetime_nested_vs_nested_same_depth", `event.start_time be event.end_time`, rule.D{
		"event": rule.D{
			"start_time": "2024-07-09T22:11:59Z",
			"end_time":   "2024-07-09T22:12:00Z",
		},
	}, true},
	{"datetime_nested_vs_nested_different_depth", `session.created_at af user.last_login`, rule.D{
		"session": rule.D{
			"created_at": "2024-07-09T22:12:01Z",
		},
		"user": rule.D{
			"last_login": "2024-07-09T22:12:00Z",
		},
	}, true},
	{"datetime_deep_nested_vs_deep_nested", `user.profile.created_at bq admin.profile.last_update`, rule.D{
		"user": rule.D{
			"profile": rule.D{
				"created_at": "2024-07-09T22:12:00Z",
			},
		},
		"admin": rule.D{
			"profile": rule.D{
				"last_update": "2024-07-09T22:12:00Z",
			},
		},
	}, true},

	{"datetime_int32_timestamp", `timestamp af 1720558320`, rule.D{
		"timestamp": int32(1720558321),
	}, true},
	{"datetime_float32_timestamp", `timestamp be 1000000`, rule.D{
		"timestamp": float32(999999.0),
	}, true},
	{"datetime_float64_timestamp", `timestamp dq 1720558320`, rule.D{
		"timestamp": float64(1720558320.0),
	}, true},
	{"datetime_uint64_timestamp", `timestamp aq 1720558320`, rule.D{
		"timestamp": uint64(1720558320),
	}, true},

	{"datetime_string_unix_timestamp", `timestamp af "1720558320"`, rule.D{
		"timestamp": "1720558321",
	}, true},
	{"datetime_mixed_string_int_unix", `timestamp_str be timestamp_int`, rule.D{
		"timestamp_str": "1720558319",
		"timestamp_int": int64(1720558320),
	}, true},

	{"datetime_epoch_zero", `timestamp af 0`, rule.D{
		"timestamp": int64(1),
	}, true},
	{"datetime_negative_timestamp", `timestamp af -86400`, rule.D{
		"timestamp": int64(-86399),
	}, true},
	{"datetime_year_2038_problem", `timestamp be 2147483648`, rule.D{
		"timestamp": int64(2147483647),
	}, true},

	{"datetime_large_int_precision", `timestamp dq 9223372036854775807`, rule.D{
		"timestamp": int64(9223372036854775807),
	}, true},

	{"datetime_invalid_rfc3339_format", `created_at af "2024-07-09T25:12:00Z"`, rule.D{
		"created_at": "2024-07-09T22:12:00Z",
	}, false},
	{"datetime_invalid_property_format", `created_at af "2024-07-09T22:12:00Z"`, rule.D{
		"created_at": "invalid-date-format",
	}, false},
	{"datetime_non_numeric_unix_string", `timestamp af 1720558320`, rule.D{
		"timestamp": "not-a-number",
	}, false},

	{"datetime_missing_left_property", `nonexistent af "2024-07-09T22:12:00Z"`, rule.D{
		"other_field": "value",
	}, false},
	{"datetime_missing_right_property", `created_at af nonexistent`, rule.D{
		"created_at": "2024-07-09T22:12:00Z",
	}, false},
	{"datetime_missing_nested_property", `event.nonexistent af "2024-07-09T22:12:00Z"`, rule.D{
		"event": rule.D{
			"other_field": "value",
		},
	}, false},

	{
		"datetime_complex_and_operation",
		`start_time af "2024-07-09T22:12:00Z" and end_time be "2024-07-09T22:15:00Z"`,
		rule.D{
			"start_time": "2024-07-09T22:12:01Z",
			"end_time":   "2024-07-09T22:14:59Z",
		},
		true,
	},
	{
		"datetime_complex_or_operation",
		`created_at be "2024-07-09T22:12:00Z" or updated_at af "2024-07-09T22:15:00Z"`,
		rule.D{
			"created_at": "2024-07-09T22:13:00Z",
			"updated_at": "2024-07-09T22:15:01Z",
		},
		true,
	},
	{
		"datetime_complex_nested_and_mixed",
		`session.start_time af user.created_at and session.end_time be 1720558400`,
		rule.D{
			"session": rule.D{
				"start_time": "2024-07-09T22:12:01Z",
				"end_time":   int64(1720558399),
			},
			"user": rule.D{
				"created_at": "2024-07-09T22:12:00Z",
			},
		},
		true,
	},

	{"dl_rfc3339_within_threshold", `created_at dl 3650`, rule.D{
		"created_at": "2020-01-01T00:00:00Z",
	}, true},
	{"dl_rfc3339_exactly_threshold", `created_at dl 1`, rule.D{
		"created_at": "2020-01-01T00:00:00Z",
	}, false},
	{"dl_rfc3339_beyond_threshold", `created_at dl 365`, rule.D{
		"created_at": "2020-01-01T00:00:00Z",
	}, false},

	{"dl_unix_within_threshold", `timestamp dl 3650`, rule.D{
		"timestamp": int64(1577836800),
	}, true},
	{"dl_unix_beyond_threshold", `timestamp dl 365`, rule.D{
		"timestamp": int64(1577836800),
	}, false},

	{"dl_fractional_days_within", `created_at dl 3650.5`, rule.D{
		"created_at": "2020-01-01T00:00:00Z",
	}, true},
	{"dl_fractional_days_beyond", `created_at dl 0.5`, rule.D{
		"created_at": "2020-01-01T00:00:00Z",
	}, false},

	{"dl_string_days_within", `created_at dl "3650"`, rule.D{
		"created_at": "2020-01-01T00:00:00Z",
	}, true},
	{"dl_string_days_beyond", `created_at dl "365"`, rule.D{
		"created_at": "2020-01-01T00:00:00Z",
	}, false},

	{"dl_nested_property", `event.created_at dl 3650`, rule.D{
		"event": rule.D{
			"created_at": "2020-01-01T00:00:00Z",
		},
	}, true},
	{"dl_deep_nested_property", `user.profile.last_login dl 3650`, rule.D{
		"user": rule.D{
			"profile": rule.D{
				"last_login": "2020-01-01T00:00:00Z",
			},
		},
	}, true},

	{"dl_invalid_timestamp", `created_at dl 30`, rule.D{
		"created_at": "invalid-timestamp",
	}, false},
	{"dl_invalid_days_string", `created_at dl "not-a-number"`, rule.D{
		"created_at": "2020-01-01T00:00:00Z",
	}, false},
	{"dl_boolean_days", `created_at dl true`, rule.D{
		"created_at": "2020-01-01T00:00:00Z",
	}, false},
	{"dl_missing_property", `nonexistent dl 30`, rule.D{
		"other_field": "value",
	}, false},

	{"dl_zero_days", `created_at dl 0`, rule.D{
		"created_at": "2020-01-01T00:00:00Z",
	}, false},
	{"dl_negative_days", `created_at dl -1`, rule.D{
		"created_at": "2020-01-01T00:00:00Z",
	}, false},

	{"dl_with_and_operator", `created_at dl 3650 and status eq "active"`, rule.D{
		"created_at": "2020-01-01T00:00:00Z",
		"status":     "active",
	}, true},
	{"dl_with_or_operator", `created_at dl 365 or updated_at dl 3650`, rule.D{
		"created_at": "2020-01-01T00:00:00Z",
		"updated_at": "2020-01-01T00:00:00Z",
	}, true},

	{"dg_rfc3339_beyond_threshold", `created_at dg 365`, rule.D{
		"created_at": "2020-01-01T00:00:00Z",
	}, true},
	{"dg_rfc3339_within_threshold", `created_at dg 3650`, rule.D{
		"created_at": "2020-01-01T00:00:00Z",
	}, false},
	{"dg_rfc3339_exactly_threshold", `created_at dg 0.5`, rule.D{
		"created_at": "2020-01-01T00:00:00Z",
	}, true},

	{"dg_unix_beyond_threshold", `timestamp dg 365`, rule.D{
		"timestamp": int64(1577836800),
	}, true},
	{"dg_unix_within_threshold", `timestamp dg 3650`, rule.D{
		"timestamp": int64(1577836800),
	}, false},

	{"dg_fractional_days_beyond", `created_at dg 365.5`, rule.D{
		"created_at": "2020-01-01T00:00:00Z",
	}, true},
	{"dg_fractional_days_within", `created_at dg 3650.5`, rule.D{
		"created_at": "2020-01-01T00:00:00Z",
	}, false},

	{"dg_string_days_beyond", `created_at dg "365"`, rule.D{
		"created_at": "2020-01-01T00:00:00Z",
	}, true},
	{"dg_string_days_within", `created_at dg "3650"`, rule.D{
		"created_at": "2020-01-01T00:00:00Z",
	}, false},

	{"dg_nested_property", `event.created_at dg 365`, rule.D{
		"event": rule.D{
			"created_at": "2020-01-01T00:00:00Z",
		},
	}, true},
	{"dg_deep_nested_property", `user.profile.last_login dg 365`, rule.D{
		"user": rule.D{
			"profile": rule.D{
				"last_login": "2020-01-01T00:00:00Z",
			},
		},
	}, true},

	{"dg_invalid_timestamp", `created_at dg 30`, rule.D{
		"created_at": "invalid-timestamp",
	}, false},
	{"dg_invalid_days_string", `created_at dg "not-a-number"`, rule.D{
		"created_at": "2020-01-01T00:00:00Z",
	}, false},
	{"dg_boolean_days", `created_at dg true`, rule.D{
		"created_at": "2020-01-01T00:00:00Z",
	}, false},
	{"dg_missing_property", `nonexistent dg 30`, rule.D{
		"other_field": "value",
	}, false},

	{"dg_zero_days", `created_at dg 0`, rule.D{
		"created_at": "2020-01-01T00:00:00Z",
	}, true},
	{"dg_negative_days", `created_at dg -1`, rule.D{
		"created_at": "2020-01-01T00:00:00Z",
	}, true},

	{"dg_with_and_operator", `created_at dg 365 and status eq "inactive"`, rule.D{
		"created_at": "2020-01-01T00:00:00Z",
		"status":     "inactive",
	}, true},
	{"dg_with_or_operator", `created_at dg 3650 or updated_at dg 365`, rule.D{
		"created_at": "2020-01-01T00:00:00Z",
		"updated_at": "2020-01-01T00:00:00Z",
	}, true},

	{"dl_vs_dg_same_input_opposite_results_1", `created_at dl 365`, rule.D{
		"created_at": "2020-01-01T00:00:00Z",
	}, false},
	{"dl_vs_dg_same_input_opposite_results_2", `created_at dg 365`, rule.D{
		"created_at": "2020-01-01T00:00:00Z",
	}, true},
}

DateTimeComprehensiveTests contains exhaustive datetime operator test cases.

View Source
var EdgeCaseTests = []Case{

	{"deep_nested_eq", "a.b.c eq d.e.f", rule.D{
		"a": rule.D{"b": rule.D{"c": 42}},
		"d": rule.D{"e": rule.D{"f": 42}},
	}, true},
	{"deep_nested_ne", "a.b.c.d ne e.f.g.h", rule.D{
		"a": rule.D{"b": rule.D{"c": rule.D{"d": "test"}}},
		"e": rule.D{"f": rule.D{"g": rule.D{"h": "different"}}},
	}, true},

	{"mixed_string_number", `version eq "2024"`, rule.D{
		"version": "2024",
	}, true},
	{"mixed_float_int", "price eq discount", rule.D{
		"price":    99.0,
		"discount": 99,
	}, true},

	{"zero_int_eq", "x eq y", rule.D{"x": 0, "y": 0}, true},
	{"zero_float_eq", "x eq y", rule.D{"x": 0.0, "y": 0}, true},
	{"empty_string_eq", "x eq y", rule.D{"x": "", "y": ""}, true},
	{"zero_vs_empty", `x eq ""`, rule.D{"x": 0}, false},

	{"empty_array_membership", "x in y", rule.D{
		"x": 1,
		"y": []any{},
	}, false},
	{"nested_array_membership", "user.id in allowed.users", rule.D{
		"user":    rule.D{"id": 123},
		"allowed": rule.D{"users": []any{123, 456, 789}},
	}, true},

	{"complex_and_or", "(a.x eq b.y) and (c.z gt d.w) or (e eq f)", rule.D{
		"a": rule.D{"x": 10},
		"b": rule.D{"y": 10},
		"c": rule.D{"z": 20},
		"d": rule.D{"w": 15},
		"e": 999,
		"f": 999,
	}, true},
	{"nested_not_operations", "not (x.y eq z.w and a.b ne c.d)", rule.D{
		"x": rule.D{"y": 10},
		"z": rule.D{"w": 10},
		"a": rule.D{"b": "same"},
		"c": rule.D{"d": "same"},
	}, true},
}
View Source
var EqualTests = []Case{

	{"eq_int_true", "x eq 1", rule.D{"x": 1}, true},
	{"eq_int_false", "x eq 1", rule.D{"x": 2}, false},

	{"eq_float_true", "x eq 1.23", rule.D{"x": 1.23}, true},
	{"eq_float_false", "x eq 1.23", rule.D{"x": 1.24}, false},

	{"eq_string_true", `x eq "abc"`, rule.D{"x": "abc"}, true},
	{"eq_string_false", `x eq "abc"`, rule.D{"x": "def"}, false},

	{"eq_version_true", `version eq "1.2.3"`, rule.D{"version": "1.2.3"}, true},
	{"eq_version_false", `version eq "1.2.3"`, rule.D{"version": "1.2.4"}, false},

	{
		"eq_nested_true",
		"x.y eq 2",
		rule.D{"x": rule.D{"y": 2}},
		true,
	},
	{
		"eq_nested_false",
		"x.y eq 2",
		rule.D{"x": rule.D{"y": 3}},
		false,
	},

	{"eq_alias_true", "x == 99", rule.D{"x": 99}, true},
	{"ne_int_true", "x ne 1", rule.D{"x": 2}, true},
	{"ne_alias_true", "x != 42", rule.D{"x": 1}, true},
}
View Source
var ErrorBoundaryTests = []Case{

	{"missing_nested_left", "missing.attr eq 10", rule.D{}, false},
	{"missing_nested_right", "10 eq missing.attr", rule.D{}, false},
	{"missing_nested_both", "missing1.attr eq missing2.attr", rule.D{}, false},

	{"deep_missing_chain", "a.b.c.d.e.f eq 10", rule.D{
		"a": rule.D{"b": rule.D{"c": rule.D{}}},
	}, false},

	{"nested_type_mismatch", "user.profile.age eq 25", rule.D{
		"user": rule.D{"profile": "not_an_object"},
	}, false},

	{"bool_vs_string", `active eq "true"`, rule.D{"active": true}, false},
	{"bool_vs_number", "active eq 1", rule.D{"active": true}, false},
	{"bool_false_vs_zero", "active eq 0", rule.D{"active": false}, false},

	{"array_membership_wrong_type", "value in array", rule.D{
		"value": "not_an_array",
		"array": "also_not_an_array",
	}, false},

	{"presence_missing_chain", "user.profile.settings.theme pr", rule.D{
		"user": rule.D{"profile": rule.D{}},
	}, false},

	{"operator_precedence", "a eq b and c eq d or e eq f", rule.D{
		"a": 1, "b": 2, "c": 3, "d": 3, "e": 5, "f": 5,
	}, true},
}
View Source
var ExtremeValueTests = []Case{

	{"long_string_eq", `x eq "` + strings.Repeat("a", 1000) + `"`, rule.D{
		"x": strings.Repeat("a", 1000),
	}, true},
	{"long_string_contains", `x co "needle"`, rule.D{
		"x": strings.Repeat("a", 500) + "needle" + strings.Repeat("b", 500),
	}, true},

	{
		"extreme_deep_nesting",
		"level1.level2.level3.level4.level5.level6.level7.level8.level9.level10 eq 42",
		rule.D{
			"level1": rule.D{
				"level2": rule.D{
					"level3": rule.D{
						"level4": rule.D{
							"level5": rule.D{
								"level6": rule.D{
									"level7": rule.D{
										"level8": rule.D{
											"level9": rule.D{
												"level10": 42,
											},
										},
									},
								},
							},
						},
					},
				},
			},
		},
		true,
	},

	{"large_array_membership", "x in large_array", rule.D{
		"x": 999,
		"large_array": func() []any {
			arr := make([]any, 1000)
			for i := range 1000 {
				arr[i] = i
			}
			return arr
		}(),
	}, true},

	{"unicode_strings", `emoji eq "🚀"`, rule.D{"emoji": "🚀"}, true},
	{"unicode_contains", `text co "🎉"`, rule.D{"text": "Hello 🎉 World"}, true},
	{"special_chars", `path eq "/path/to/file@domain.com"`, rule.D{
		"path": "/path/to/file@domain.com",
	}, true},

	{"datetime_equal_rfc3339", `created_at dq "2024-07-09T19:12:00-03:00"`, rule.D{
		"created_at": "2024-07-09T22:12:00Z",
	}, true},
	{"datetime_not_equal_rfc3339", `created_at dn "2024-07-09T19:12:00-03:00"`, rule.D{
		"created_at": "2024-07-09T22:13:00Z",
	}, true},
	{"datetime_before_rfc3339", `created_at be "2024-07-09T19:12:00-03:00"`, rule.D{
		"created_at": "2024-07-09T22:11:00Z",
	}, true},
	{"datetime_before_or_equal_rfc3339", `created_at bq "2024-07-09T19:12:00-03:00"`, rule.D{
		"created_at": "2024-07-09T22:12:00Z",
	}, true},
	{"datetime_after_rfc3339", `created_at af "2024-07-09T19:12:00-03:00"`, rule.D{
		"created_at": "2024-07-09T22:13:00Z",
	}, true},
	{"datetime_after_or_equal_rfc3339", `created_at aq "2024-07-09T19:12:00-03:00"`, rule.D{
		"created_at": "2024-07-09T22:12:00Z",
	}, true},

	{"datetime_equal_unix", `timestamp dq 1720558320`, rule.D{
		"timestamp": int64(1720558320),
	}, true},
	{"datetime_not_equal_unix", `timestamp dn 1720558320`, rule.D{
		"timestamp": int64(1720558321),
	}, true},
	{"datetime_before_unix", `timestamp be 1720558320`, rule.D{
		"timestamp": int64(1720558319),
	}, true},
	{"datetime_before_or_equal_unix", `timestamp bq 1720558320`, rule.D{
		"timestamp": int64(1720558320),
	}, true},
	{"datetime_after_unix", `timestamp af 1720558320`, rule.D{
		"timestamp": int64(1720558321),
	}, true},
	{"datetime_after_or_equal_unix", `timestamp aq 1720558320`, rule.D{
		"timestamp": int64(1720558320),
	}, true},

	{"datetime_mixed_rfc3339_vs_unix", `created_at af 1720558320`, rule.D{
		"created_at": "2024-07-09T22:12:01Z",
	}, true},
	{"datetime_mixed_unix_vs_rfc3339", `timestamp be "2024-07-09T22:12:01Z"`, rule.D{
		"timestamp": int64(1720558320),
	}, true},

	{"datetime_false_before", `created_at be "2024-07-09T19:12:00-03:00"`, rule.D{
		"created_at": "2024-07-09T22:13:00Z",
	}, false},
	{"datetime_false_after", `created_at af "2024-07-09T19:12:00-03:00"`, rule.D{
		"created_at": "2024-07-09T22:11:00Z",
	}, false},
	{"datetime_false_equal", `created_at dq "2024-07-09T19:12:00-03:00"`, rule.D{
		"created_at": "2024-07-09T22:13:00Z",
	}, false},
}
View Source
var InTests = []Case{
	{"in_int_true", "x in [1,2,3]", rule.D{"x": 2}, true},
	{"in_int_false", "x in [1,2,3]", rule.D{"x": 4}, false},
	{
		"in_str_true",
		`color in ["red","green","blue"]`,
		rule.D{"color": "green"},
		true,
	},
	{
		"in_str_false",
		`color in ["red","green","blue"]`,
		rule.D{"color": "yellow"},
		false,
	},
}
View Source
var LogicalTests = []Case{
	{"not_true", "not (x eq 1)", rule.D{"x": 2}, true},
	{"not_false", "not (x eq 1)", rule.D{"x": 1}, false},
	{"and_true", "(x gt 1) and (y lt 5)", rule.D{"x": 2, "y": 3}, true},
	{"and_false_left", "(x gt 1) and (y lt 5)", rule.D{"x": 1, "y": 3}, false},
	{"or_true_left", "(x lt 0) or (y eq 7)", rule.D{"x": -1, "y": 9}, true},
	{"or_true_right", "(x lt 0) or (y eq 7)", rule.D{"x": 1, "y": 7}, true},
	{"or_false", "(x lt 0) or (y eq 7)", rule.D{"x": 1, "y": 8}, false},
}
View Source
var NestedPropTests = []Case{

	{"nested_eq_true", "x.y eq z.w", rule.D{
		"x": rule.D{"y": 10},
		"z": rule.D{"w": 10},
	}, true},
	{"nested_eq_false", "x.y eq z.w", rule.D{
		"x": rule.D{"y": 10},
		"z": rule.D{"w": 11},
	}, false},

	{"mixed_depth_eq_true", "x.y eq z", rule.D{
		"x": rule.D{"y": "abc"},
		"z": "abc",
	}, true},

	{"nested_gt_true", "m.n gt p.q", rule.D{
		"m": rule.D{"n": 20},
		"p": rule.D{"q": 15},
	}, true},
	{"nested_le_false", "m.n le p.q", rule.D{
		"m": rule.D{"n": 21},
		"p": rule.D{"q": 20},
	}, false},
}
View Source
var NumericEdgeCaseTests = []Case{

	{"large_int_eq", "x eq y", rule.D{
		"x": 9223372036854775807,
		"y": 9223372036854775807,
	}, true},
	{"large_float_eq", "x eq y", rule.D{
		"x": 1.7976931348623157e+308,
		"y": 1.7976931348623157e+308,
	}, true},

	{"negative_comparison", "x lt y", rule.D{"x": -10, "y": -5}, true},
	{"negative_zero", "x eq y", rule.D{"x": math.Copysign(0, -1), "y": 0.0}, true},

	{"int_float_eq", "x eq y", rule.D{"x": 42, "y": 42.0}, true},
	{"int_float_gt", "x gt y", rule.D{"x": 43, "y": 42.5}, true},
	{"int_float_lt", "x lt y", rule.D{"x": 42, "y": 42.1}, true},
}
View Source
var PerformanceStressTests = []Case{

	{
		"long_and_chain",
		"a eq 1 and b eq 2 and c eq 3 and d eq 4 and e eq 5 and f eq 6 and g eq 7 and h eq 8 and i eq 9 and j eq 10",
		rule.D{
			"a": 1, "b": 2, "c": 3, "d": 4, "e": 5, "f": 6, "g": 7, "h": 8, "i": 9, "j": 10,
		},
		true,
	},

	{
		"long_or_chain",
		"a eq 0 or b eq 0 or c eq 0 or d eq 0 or e eq 0 or f eq 0 or g eq 0 or h eq 0 or i eq 0 or j eq 1",
		rule.D{
			"a": 1, "b": 2, "c": 3, "d": 4, "e": 5, "f": 6, "g": 7, "h": 8, "i": 9, "j": 1,
		},
		true,
	},

	{"deep_property_chain", "a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t eq 42", rule.D{
		"a": rule.D{
			"b": rule.D{
				"c": rule.D{
					"d": rule.D{
						"e": rule.D{
							"f": rule.D{
								"g": rule.D{
									"h": rule.D{
										"i": rule.D{
											"j": rule.D{
												"k": rule.D{
													"l": rule.D{
														"m": rule.D{
															"n": rule.D{
																"o": rule.D{
																	"p": rule.D{
																		"q": rule.D{
																			"r": rule.D{
																				"s": rule.D{
																					"t": 42,
																				},
																			},
																		},
																	},
																},
															},
														},
													},
												},
											},
										},
									},
								},
							},
						},
					},
				},
			},
		},
	}, true},
}
View Source
var PresenceEdgeCaseTests = []Case{

	{"nested_presence_true", "user.profile pr", rule.D{
		"user": rule.D{"profile": rule.D{"name": "John"}},
	}, true},
	{"nested_presence_false", "user.profile pr", rule.D{
		"user": rule.D{"other": "value"},
	}, false},
	{"deep_nested_presence", "a.b.c.d pr", rule.D{
		"a": rule.D{
			"b": rule.D{
				"c": rule.D{"d": "exists"},
			},
		},
	}, true},

	{"presence_zero_int", "x pr", rule.D{"x": 0}, true},
	{"presence_empty_string", "x pr", rule.D{"x": ""}, true},
	{"presence_false_bool", "x pr", rule.D{"x": false}, true},
	{"presence_empty_array", "x pr", rule.D{"x": []any{}}, true},
}
View Source
var PresenceTests = []Case{
	{"pr_present", "betaUser pr", rule.D{"betaUser": true}, true},
	{"pr_missing", "betaUser pr", rule.D{}, false},
}
View Source
var PropCompareTests = []Case{

	{"prop_eq_int_true", "x eq y", rule.D{"x": 5, "y": 5}, true},
	{"prop_eq_int_false", "x eq y", rule.D{"x": 5, "y": 6}, false},
	{"prop_ne_int_true", "x ne y", rule.D{"x": 1, "y": 2}, true},

	{"prop_gt_true", "a gt b", rule.D{"a": 10, "b": 3}, true},
	{"prop_lt_false", "a lt b", rule.D{"a": 10, "b": 3}, false},
	{"prop_le_true", "a le b", rule.D{"a": 7, "b": 7}, true},
	{"prop_ge_false", "a ge b", rule.D{"a": 6, "b": 7}, false},

	{"prop_eq_str_true", `first eq last`, rule.D{"first": "go", "last": "go"}, true},
	{"prop_ne_str_true", `first ne last`, rule.D{"first": "go", "last": "rust"}, true},

	{"prop_co_true", `email co domain`, rule.D{
		"email":  "foo@example.com",
		"domain": "@example.com",
	}, true},
	{"prop_sw_false", `login sw prefix`, rule.D{
		"login":  "guest123",
		"prefix": "user_",
	}, false},
	{"prop_ew_true", `file ew ext`, rule.D{
		"file": "report.pdf",
		"ext":  ".pdf",
	}, true},

	{"prop_in_list_true", `color in allowed`, rule.D{
		"color":   "red",
		"allowed": []any{"red", "green"},
	}, true},
	{"prop_in_list_false", `color in allowed`, rule.D{
		"color":   "blue",
		"allowed": []any{"red", "green"},
	}, false},
}
View Source
var RealWorldEdgeTests = []Case{

	{"json_like_structure", `response.data.status eq "success" and response.data.count gt 0`, rule.D{
		"response": rule.D{
			"data": rule.D{
				"status": "success",
				"count":  2,
			},
		},
	}, true},

	{"http_headers", `headers.content_type co "application/json" and headers.authorization sw "Bearer"`, rule.D{
		"headers": rule.D{
			"content_type":  "application/json; charset=utf-8",
			"authorization": "Bearer token123",
		},
	}, true},

	{
		"database_query",
		`user.created_at ge "2023-01-01" and user.status eq "active" and user.subscription.plan in ["premium", "enterprise"]`,
		rule.D{
			"user": rule.D{
				"created_at": "2023-06-15",
				"status":     "active",
				"subscription": rule.D{
					"plan": "premium",
				},
			},
		},
		true,
	},

	{
		"config_validation",
		`config.database.host sw "localhost" and config.database.port ge 1024 and config.database.ssl eq true`,
		rule.D{
			"config": rule.D{
				"database": rule.D{
					"host": "localhost:5432",
					"port": 5432,
					"ssl":  true,
				},
			},
		},
		true,
	},
}
View Source
var RealWorldTests = []Case{

	{
		"user_permissions",
		`user.role in permissions.roles and user.active eq true and user.profile.verified eq true`,
		rule.D{
			"user": rule.D{
				"role":   "admin",
				"active": true,
				"profile": rule.D{
					"verified": true,
				},
			},
			"permissions": rule.D{
				"roles": []any{"admin", "moderator"},
			},
		},
		true,
	},

	{"rate_limiting", `request.count lt limits.max and request.user.tier eq "premium"`, rule.D{
		"request": rule.D{
			"count": 50,
			"user":  rule.D{"tier": "premium"},
		},
		"limits": rule.D{"max": 100},
	}, true},

	{
		"feature_flags",
		`user.id in features.beta_users or (user.plan eq "enterprise" and features.enterprise_enabled eq true)`,
		rule.D{
			"user": rule.D{
				"id":   12345,
				"plan": "enterprise",
			},
			"features": rule.D{
				"beta_users":         []any{11111, 22222, 33333},
				"enterprise_enabled": true,
			},
		},
		true,
	},

	{
		"config_matching",
		`env.stage eq "production" and config.debug eq false and config.monitoring.enabled eq true`,
		rule.D{
			"env": rule.D{"stage": "production"},
			"config": rule.D{
				"debug": false,
				"monitoring": rule.D{
					"enabled": true,
				},
			},
		},
		true,
	},

	{
		"content_filtering",
		`post.author.reputation gt 100 and not (post.content co "spam") and post.tags.category ne "adult"`,
		rule.D{
			"post": rule.D{
				"author":  rule.D{"reputation": 150},
				"content": "This is a legitimate post",
				"tags":    rule.D{"category": "general"},
			},
		},
		true,
	},
}
View Source
var RelationalTests = []Case{
	{"lt_true", "score lt 10", rule.D{"score": 5}, true},
	{"lt_false", "score lt 10", rule.D{"score": 10}, false},
	{"gt_true", "score gt 10", rule.D{"score": 11}, true},
	{"gt_false", "score gt 10", rule.D{"score": 9}, false},
	{"le_true_equal", "score le 7", rule.D{"score": 7}, true},
	{"le_true_less", "score le 7", rule.D{"score": 6}, true},
	{"ge_true_equal", "score ge 7", rule.D{"score": 7}, true},
	{"ge_true_greater", "score ge 7", rule.D{"score": 8}, true},
}
View Source
var SpecialNumericTests = []Case{

	{"very_small_positive", "x gt 0", rule.D{"x": 1e-100}, true},
	{"very_small_negative", "x lt 0", rule.D{"x": -1e-100}, true},

	{"max_int64", "x eq 9223372036854775807", rule.D{"x": int64(9223372036854775807)}, true},
	{"min_int64", "x eq -9223372036854775808", rule.D{"x": int64(-9223372036854775808)}, true},
}
View Source
var StringEdgeCaseTests = []Case{

	{"prop_contains_nested", "user.email co domain.suffix", rule.D{
		"user":   rule.D{"email": "john@example.com"},
		"domain": rule.D{"suffix": "@example.com"},
	}, true},
	{"prop_startswith_nested", "file.name sw prefix.value", rule.D{
		"file":   rule.D{"name": "user_profile.jpg"},
		"prefix": rule.D{"value": "user_"},
	}, true},
	{"prop_endswith_nested", "document.path ew extension.type", rule.D{
		"document":  rule.D{"path": "report.pdf"},
		"extension": rule.D{"type": ".pdf"},
	}, true},

	{"empty_string_contains", `x co ""`, rule.D{"x": "hello"}, true},
	{"empty_string_startswith", `x sw ""`, rule.D{"x": "hello"}, true},
	{"empty_string_endswith", `x ew ""`, rule.D{"x": "hello"}, true},
	{"contains_empty_string", `"" co "test"`, rule.D{}, false},

	{"case_insensitive_eq", `x eq "test"`, rule.D{"x": "Test"}, true},
	{"case_insensitive_contains", `x co "hello"`, rule.D{"x": "Hello World"}, true},
}
View Source
var StringOpTests = []Case{
	{"co_true", `city co "York"`, rule.D{"city": "New York"}, true},
	{"co_false", `city co "York"`, rule.D{"city": "Boston"}, false},
	{"sw_true", `id sw "user_"`, rule.D{"id": "user_123"}, true},
	{"sw_false", `id sw "user_"`, rule.D{"id": "admin_1"}, false},
	{"ew_true", `file ew ".txt"`, rule.D{"file": "report.txt"}, true},
	{"ew_false", `file ew ".txt"`, rule.D{"file": "image.png"}, false},
}
View Source
var TypeCoercionStressTests = []Case{

	{"float_precision", "x eq 0.1000000000000001", rule.D{"x": 0.1000000000000001}, true},
	{"float_precision_2", "x eq 0.1000000000000001", rule.D{"x": 0.1}, false},

	{"large_int_comparison", "x gt 9223372036854775806", rule.D{"x": int64(9223372036854775807)}, true},
	{"large_float_comparison", "x lt 1000000000000000000", rule.D{"x": 999999999999999999}, true},

	{
		"string_numeric_mixed",
		`version ge "1.10.0"`,
		rule.D{"version": "1.9.0"},
		true,
	},
	{
		"string_numeric_mixed_2",
		`version ge "1.10.0"`,
		rule.D{"version": "1.2.0"},
		true,
	},

	{"bool_string_strict", `flag eq "true"`, rule.D{"flag": "true"}, true},
	{"bool_string_strict_2", `flag eq "true"`, rule.D{"flag": true}, false},
	{"bool_int_strict", "flag eq 1", rule.D{"flag": 1}, true},
	{"bool_int_strict_2", "flag eq 1", rule.D{"flag": true}, false},
}
View Source
var WhitespaceTests = []Case{

	{"extra_spaces", "  x    eq    10   ", rule.D{"x": 10}, true},
	{"tabs_and_spaces", "x\teq\t10", rule.D{"x": 10}, true},
	{"mixed_whitespace", "  x  \t eq \t 10  ", rule.D{"x": 10}, true},

	{"spaces_in_parens", "( x eq 10 )", rule.D{"x": 10}, true},
	{"complex_spacing", "(  x  eq  10  )  and  (  y  gt  5  )", rule.D{"x": 10, "y": 6}, true},

	{"array_spaces", "x in [ 1 , 2 , 3 ]", rule.D{"x": 2}, true},
	{"array_mixed_spacing", "x in [1, 2,3 ,4]", rule.D{"x": 3}, true},

	{"strings_with_spaces", `name eq "John Doe"`, rule.D{"name": "John Doe"}, true},
	{"property_with_spaces", `user.full_name eq "Jane Smith"`, rule.D{
		"user": rule.D{"full_name": "Jane Smith"},
	}, true},
}

Functions

This section is empty.

Types

type Case

type Case struct {
	Name   string
	Query  string
	Ctx    rule.D
	Result bool
}

Case bundles one rule, its context, and the expected boolean result.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL