Skip to content

Commit c23b17d

Browse files
committed
feature: [174] Rewrite Java tests to Groovy Spock
1 parent f23b48b commit c23b17d

5 files changed

Lines changed: 522 additions & 494 deletions

File tree

acl-antlr-dsl/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
plugins {
2+
id("groovy")
23
id("java-library")
34
id("configure-java")
45
id("antlr")
Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
package javasabr.mqtt.acl.java.dsl
2+
3+
import javasabr.mqtt.acl.engine.exception.AclConfigurationException
4+
import javasabr.mqtt.acl.engine.model.condition.AllOfCondition
5+
import javasabr.mqtt.acl.engine.model.condition.AnyOfCondition
6+
import javasabr.mqtt.acl.engine.model.condition.ClientIdCondition
7+
import javasabr.mqtt.acl.engine.model.condition.MqttUserCondition
8+
import javasabr.mqtt.acl.engine.model.condition.UserNameCondition
9+
import javasabr.mqtt.acl.engine.model.matcher.AnyTopicMatcher
10+
import javasabr.mqtt.acl.engine.model.matcher.EqualsMatcher
11+
import javasabr.mqtt.acl.engine.model.matcher.RegexMatcher
12+
import javasabr.mqtt.acl.engine.model.matcher.StartsWithMatcher
13+
import javasabr.mqtt.acl.engine.model.matcher.dynamic.DynamicTopicMatcher
14+
import javasabr.mqtt.acl.engine.model.rule.AbstractAclRule
15+
import spock.lang.Specification
16+
17+
import static javasabr.mqtt.acl.engine.model.Action.ALLOW
18+
import static javasabr.mqtt.acl.engine.model.Action.DENY
19+
import static javasabr.mqtt.model.acl.Operation.PUBLISH
20+
import static javasabr.mqtt.model.acl.Operation.SUBSCRIBE
21+
22+
class AclRulesLoaderTest extends Specification {
23+
24+
def "should build ACL rules via ANTLR DSL"() {
25+
given: "a complex ACL rule configuration"
26+
def programmaticallyDefinedRules = { root ->
27+
root
28+
.allowPublish { rule ->
29+
rule
30+
.users { users ->
31+
users
32+
.userNames { un ->
33+
un
34+
.eq("sensor1")
35+
.regex("sensor10\$")
36+
}
37+
.clientIds { ci ->
38+
ci
39+
.eq("clientId1")
40+
.regex("^cliend")
41+
}
42+
.ipAddresses { ip ->
43+
ip
44+
.eq("10.56.0.3")
45+
.eq("127.0.0.1")
46+
}
47+
.anyOf { any -> any.userName(any.anyValue()) }
48+
.allOf { all ->
49+
all
50+
.userName(all.eq("sensor2"))
51+
.clientId(all.eq("clientId2"))
52+
.ipAddress(all.eq("10.56.0.3"))
53+
}
54+
}
55+
.topics { topics ->
56+
topics
57+
.eq("/topic1")
58+
.eq("/topic2/temp")
59+
}
60+
}
61+
.denyPublish { rule ->
62+
rule
63+
.users { users -> users.anyUser() }
64+
.topics { topics -> topics.anyTopic() }
65+
}
66+
.allowPublish { rule ->
67+
rule
68+
.users { users ->
69+
users
70+
.userName(users.startsWith("start_with_5"))
71+
.clientId(users.contains("contains"))
72+
}
73+
.topics { topics -> topics.anyTopic() }
74+
}
75+
.denySubscribe { rule ->
76+
rule
77+
.users { users ->
78+
users.allOf { all ->
79+
all
80+
.userName(all.eq("sensor2"))
81+
.clientId(all.eq("clientId2"))
82+
.ipAddress(all.eq("10.56.0.3"))
83+
}
84+
}
85+
.topics { topics ->
86+
topics
87+
.match("/topic1/#")
88+
.match("/topic2/+/temp")
89+
}
90+
}
91+
.allowSubscribe { rule ->
92+
rule
93+
.users { users ->
94+
users.allOf { all ->
95+
all
96+
.userName(all.eq("sensor2"))
97+
.clientId(all.eq("clientId2"))
98+
.ipAddress(all.eq("10.56.0.3"))
99+
}
100+
}
101+
.topics { topics ->
102+
topics
103+
.match("/topic1/#")
104+
.match("/topic2/+/temp")
105+
}
106+
}
107+
.denySubscribe { rule ->
108+
rule
109+
.users { users -> users.anyUser() }
110+
.topics { topics -> topics.anyTopic() }
111+
}
112+
.allowSubscribe { rule ->
113+
rule
114+
.users { users -> users.clientId(users.startsWith("device_")) }
115+
.topics { topics ->
116+
topics
117+
.dynamic("/devices/{clientId}/notify")
118+
.match("/devices/broadcast")
119+
}
120+
}
121+
}
122+
123+
when: "the rules are built"
124+
def rules = AclRulesLoader.build(programmaticallyDefinedRules)
125+
126+
then: "the rules are correct for PUBLISH"
127+
def publishRules = rules.get(PUBLISH)
128+
publishRules.size() == 3
129+
130+
def rule0 = (AbstractAclRule) publishRules.get(0)
131+
rule0.operation() == PUBLISH
132+
rule0.action() == ALLOW
133+
rule0.userCondition() instanceof AnyOfCondition
134+
def userCond0 = (AnyOfCondition) rule0.userCondition()
135+
userCond0.conditions().size() == 8
136+
((EqualsMatcher<String>) ((UserNameCondition) userCond0.conditions().get(0)).matcher()).expected() == "sensor1"
137+
((RegexMatcher) ((UserNameCondition) userCond0.conditions().get(1)).matcher()).pattern().pattern() == "sensor10\$"
138+
139+
def rule1 = (AbstractAclRule) publishRules.get(1)
140+
rule1.operation() == PUBLISH
141+
rule1.action() == DENY
142+
rule1.userCondition() == MqttUserCondition.MATCH_ANY
143+
rule1.topicCondition().matchers().get(0) == AnyTopicMatcher.instance()
144+
145+
def rule2 = (AbstractAclRule) publishRules.get(2)
146+
rule2.operation() == PUBLISH
147+
rule2.action() == ALLOW
148+
149+
and: "the rules are correct for SUBSCRIBE"
150+
def subscribeRules = rules.get(SUBSCRIBE)
151+
subscribeRules.size() == 4
152+
153+
def sRule0 = (AbstractAclRule) subscribeRules.get(0)
154+
sRule0.operation() == SUBSCRIBE
155+
sRule0.action() == DENY
156+
sRule0.userCondition() instanceof AllOfCondition
157+
158+
def sRule3 = (AbstractAclRule) subscribeRules.get(3)
159+
sRule3.operation() == SUBSCRIBE
160+
sRule3.action() == ALLOW
161+
sRule3.userCondition() instanceof ClientIdCondition
162+
((StartsWithMatcher) ((ClientIdCondition) sRule3.userCondition()).matcher()).prefix() == "device_"
163+
sRule3.topicCondition().matchers().get(0) instanceof DynamicTopicMatcher
164+
}
165+
166+
def "should throw exception if topics section is missing"() {
167+
when:
168+
AclRulesLoader.build { root -> root.allowPublish { rule -> rule.users { users -> users.anyUser() } } }
169+
170+
then:
171+
thrown(AclConfigurationException)
172+
}
173+
174+
def "should throw exception if users section is missing"() {
175+
when:
176+
AclRulesLoader.build { root -> root.allowPublish { rule -> rule.topics { topics -> topics.anyTopic() } } }
177+
178+
then:
179+
thrown(AclConfigurationException)
180+
}
181+
182+
def "should throw exception if multiple users sections"() {
183+
when:
184+
AclRulesLoader.build { root ->
185+
root.allowPublish { rule ->
186+
rule
187+
.users { users -> users.anyUser() }
188+
.users { users -> users.anyUser() }
189+
}
190+
}
191+
192+
then:
193+
thrown(AclConfigurationException)
194+
}
195+
196+
def "should throw exception if multiple topics sections"() {
197+
when:
198+
AclRulesLoader.build { root ->
199+
root.allowPublish { rule ->
200+
rule
201+
.users { users -> users.anyUser() }
202+
.topics { topics -> topics.anyTopic() }
203+
.topics { topics -> topics.anyTopic() }
204+
}
205+
}
206+
207+
then:
208+
thrown(AclConfigurationException)
209+
}
210+
}

0 commit comments

Comments
 (0)