Skip to content

Commit 6e4b2a4

Browse files
committed
Add test suite for the using() routine.
1 parent cf6d11a commit 6e4b2a4

File tree

2 files changed

+267
-0
lines changed

2 files changed

+267
-0
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright 2018 ABSA Group Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package za.co.absa.cobrix.cobol.utils
18+
19+
class AutoCloseableSpy(failCreate: Boolean = false, failAction: Boolean = false, failClose: Boolean = false) extends AutoCloseable {
20+
var actionCallCount: Int = 0
21+
var closeCallCount: Int = 0
22+
23+
if (failCreate) {
24+
throw new RuntimeException("Failed to create resource")
25+
}
26+
27+
def dummyAction(): Unit = {
28+
actionCallCount += 1
29+
if (failAction) {
30+
throw new RuntimeException("Failed during action")
31+
}
32+
}
33+
34+
override def close(): Unit = {
35+
closeCallCount += 1
36+
if (failClose) {
37+
throw new RuntimeException("Failed to close resource")
38+
}
39+
}
40+
}
Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
/*
2+
* Copyright 2018 ABSA Group Limited
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package za.co.absa.cobrix.cobol.utils
18+
19+
import org.scalatest.wordspec.AnyWordSpec
20+
21+
class UsingUtilsSuite extends AnyWordSpec {
22+
"using with a single resource" should {
23+
"properly close the resource" in {
24+
var resource: AutoCloseableSpy = null
25+
26+
UsingUtils.using(new AutoCloseableSpy()) { res =>
27+
resource = res
28+
res.dummyAction()
29+
}
30+
31+
assert(resource.actionCallCount == 1)
32+
assert(resource.closeCallCount == 1)
33+
}
34+
35+
"close resource even if exception occurs" in {
36+
var resource: AutoCloseableSpy = null
37+
var exceptionThrown = false
38+
39+
try {
40+
UsingUtils.using(new AutoCloseableSpy(failAction = true)) { res =>
41+
resource = res
42+
res.dummyAction()
43+
}
44+
} catch {
45+
case ex: Throwable =>
46+
assert(ex.getMessage.contains("Failed during action"))
47+
exceptionThrown = true
48+
}
49+
50+
assert(exceptionThrown)
51+
assert(resource.actionCallCount == 1)
52+
assert(resource.closeCallCount == 1)
53+
}
54+
55+
"handle exceptions when a resource is created" in {
56+
var exceptionThrown = false
57+
var resource: AutoCloseableSpy = null
58+
59+
try {
60+
UsingUtils.using(new AutoCloseableSpy(failCreate = true)) { res =>
61+
resource = res
62+
res.dummyAction()
63+
}
64+
} catch {
65+
case ex: Throwable =>
66+
exceptionThrown = true
67+
assert(ex.getMessage.contains("Failed to create resource"))
68+
}
69+
70+
assert(exceptionThrown)
71+
assert(resource == null)
72+
}
73+
74+
"handle exceptions when a resource is closed" in {
75+
var resource: AutoCloseableSpy = null
76+
var exceptionThrown = false
77+
78+
try {
79+
UsingUtils.using(new AutoCloseableSpy(failClose = true)) { res =>
80+
resource = res
81+
res.dummyAction()
82+
}
83+
} catch {
84+
case ex: Throwable =>
85+
exceptionThrown = true
86+
assert(ex.getMessage.contains("Failed to close resource"))
87+
}
88+
89+
assert(exceptionThrown)
90+
assert(resource.actionCallCount == 1)
91+
assert(resource.closeCallCount == 1)
92+
}
93+
94+
"handle exceptions on both action and close" in {
95+
var resource: AutoCloseableSpy = null
96+
var exceptionThrown = false
97+
98+
try {
99+
UsingUtils.using(new AutoCloseableSpy(failClose = true)) { res =>
100+
resource = res
101+
res.dummyAction()
102+
throw new RuntimeException("Failed during action")
103+
}
104+
} catch {
105+
case ex: Throwable =>
106+
exceptionThrown = true
107+
assert(ex.getMessage.contains("Failed during action"))
108+
val suppressed = ex.getSuppressed
109+
assert(suppressed.length == 1)
110+
assert(suppressed(0).getMessage.contains("Failed to close resource"))
111+
}
112+
113+
assert(exceptionThrown)
114+
assert(resource.actionCallCount == 1)
115+
assert(resource.closeCallCount == 1)
116+
}
117+
}
118+
119+
"using with two resources" should {
120+
"properly close both resources" in {
121+
var resource1: AutoCloseableSpy = null
122+
var resource2: AutoCloseableSpy = null
123+
124+
val result = UsingUtils.using(new AutoCloseableSpy()) { res1 =>
125+
resource1 = res1
126+
UsingUtils.using(new AutoCloseableSpy()) { res2 =>
127+
resource2 = res2
128+
res1.dummyAction()
129+
res2.dummyAction()
130+
100
131+
}
132+
}
133+
134+
assert(result == 100)
135+
assert(resource1.actionCallCount == 1)
136+
assert(resource1.closeCallCount == 1)
137+
assert(resource2.actionCallCount == 1)
138+
assert(resource2.closeCallCount == 1)
139+
}
140+
141+
"properly close both resources when an inner one throws an exception during action and close" in {
142+
var resource1: AutoCloseableSpy = null
143+
var resource2: AutoCloseableSpy = null
144+
var exceptionThrown = false
145+
146+
try {
147+
UsingUtils.using(new AutoCloseableSpy()) { res1 =>
148+
resource1 = res1
149+
UsingUtils.using(new AutoCloseableSpy(failAction = true, failClose = true)) { res2 =>
150+
resource2 = res2
151+
res1.dummyAction()
152+
res2.dummyAction()
153+
}
154+
}
155+
} catch {
156+
case ex: Throwable =>
157+
exceptionThrown = true
158+
assert(ex.getMessage.contains("Failed during action"))
159+
val suppressed = ex.getSuppressed
160+
assert(suppressed.length == 1)
161+
assert(suppressed(0).getMessage.contains("Failed to close resource"))
162+
}
163+
164+
assert(exceptionThrown)
165+
assert(resource1.actionCallCount == 1)
166+
assert(resource1.closeCallCount == 1)
167+
assert(resource2.actionCallCount == 1)
168+
assert(resource2.closeCallCount == 1)
169+
}
170+
171+
"properly close both resources when an outer one throws an exception during action and close" in {
172+
var resource1: AutoCloseableSpy = null
173+
var resource2: AutoCloseableSpy = null
174+
var exceptionThrown = false
175+
176+
try {
177+
UsingUtils.using(new AutoCloseableSpy(failAction = true, failClose = true)) { res1 =>
178+
resource1 = res1
179+
UsingUtils.using(new AutoCloseableSpy()) { res2 =>
180+
resource2 = res2
181+
res1.dummyAction()
182+
res2.dummyAction()
183+
}
184+
}
185+
} catch {
186+
case ex: Throwable =>
187+
exceptionThrown = true
188+
assert(ex.getMessage.contains("Failed during action"))
189+
val suppressed = ex.getSuppressed
190+
assert(suppressed.length == 1)
191+
assert(suppressed(0).getMessage.contains("Failed to close resource"))
192+
}
193+
194+
assert(exceptionThrown)
195+
assert(resource1.actionCallCount == 1)
196+
assert(resource1.closeCallCount == 1)
197+
assert(resource2.actionCallCount == 0)
198+
assert(resource2.closeCallCount == 1)
199+
}
200+
201+
"properly close the outer resource when the inner one fails on create" in {
202+
var resource1: AutoCloseableSpy = null
203+
var resource2: AutoCloseableSpy = null
204+
var exceptionThrown = false
205+
206+
try {
207+
UsingUtils.using(new AutoCloseableSpy()) { res1 =>
208+
resource1 = res1
209+
UsingUtils.using(new AutoCloseableSpy(failCreate = true)) { res2 =>
210+
resource2 = res2
211+
res1.dummyAction()
212+
res2.dummyAction()
213+
}
214+
}
215+
} catch {
216+
case ex: Throwable =>
217+
exceptionThrown = true
218+
assert(ex.getMessage.contains("Failed to create resource"))
219+
}
220+
221+
assert(exceptionThrown)
222+
assert(resource1.actionCallCount == 0)
223+
assert(resource1.closeCallCount == 1)
224+
assert(resource2 == null)
225+
}
226+
}
227+
}

0 commit comments

Comments
 (0)