-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy pathIntegrationTests.kt
143 lines (114 loc) · 4.66 KB
/
IntegrationTests.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
@file:Suppress("BlockingMethodInNonBlockingContext")
import com.github.tomakehurst.wiremock.WireMockServer
import com.github.tomakehurst.wiremock.client.WireMock.*
import com.github.tomakehurst.wiremock.core.WireMockConfiguration.options
import io.kotest.core.spec.style.StringSpec
import io.kotest.core.test.TestCase
import io.kotest.core.test.TestResult
import io.kotest.matchers.shouldBe
import io.kotest.matchers.string.shouldNotBeEmpty
import java.io.BufferedReader
import java.lang.Thread.sleep
import java.nio.file.Path
import java.nio.file.Paths
import java.util.concurrent.TimeUnit
// We require TEST_JAR to always be set when running the tests, giving us the appropriate path
// to the specific agent jar that we're testing.
val AGENT_JAR_PATH = System.getenv("TEST_JAR")!!
val x = run {
println("Testing $AGENT_JAR_PATH")
}
// For the test-app JAR we just use a constant string
val TEST_APP_JAR = Paths.get("test-app", "build", "libs", "test-app-1.0-SNAPSHOT-all.jar").toString()
val resourcesPath: Path = Paths.get("src", "test", "resources")
const val proxyHost = "127.0.0.1"
val certPath = resourcesPath.resolve("cert.pem").toAbsolutePath().toString()
// We always launch subprocesses with the same Java that we're using ourselves
val javaPath = Paths.get(System.getProperty("java.home"), "bin", "java").toString()
val wireMockServer = WireMockServer(options()
.dynamicPort()
.enableBrowserProxying(true)
.caKeystorePath(resourcesPath.resolve("cert.jks").toAbsolutePath().toString())
.caKeystorePassword("password")
)
val runningProcs = arrayListOf<Process>()
class IntegrationTests : StringSpec({
"Launching a self test should return successfully" {
val proc = ProcessBuilder(
javaPath,
"-Djdk.attach.allowAttachSelf=true",
"-jar", AGENT_JAR_PATH,
"self-test"
).start()
runningProcs.add(proc)
proc.waitFor(10, TimeUnit.SECONDS)
proc.isAlive.shouldBe(false)
proc.exitValue().shouldBe(0)
}
"Launching with list-targets should return successfully" {
val proc = ProcessBuilder(
javaPath,
"-jar", AGENT_JAR_PATH,
"list-targets"
).start()
runningProcs.add(proc)
val outputReader = proc.inputStream.bufferedReader()
proc.waitFor(10, TimeUnit.SECONDS)
val output = outputReader.use(BufferedReader::readText)
output.shouldNotBeEmpty()
proc.isAlive.shouldBe(false)
proc.exitValue().shouldBe(0)
}
"Launching with -javaagent should intercept all clients" {
val agentArgs = "$proxyHost|${wireMockServer.port()}|$certPath"
val proc = ProcessBuilder(
javaPath,
"-javaagent:$AGENT_JAR_PATH=$agentArgs",
"-jar", TEST_APP_JAR
).inheritIO().start()
runningProcs.add(proc)
proc.waitFor(30, TimeUnit.SECONDS)
proc.isAlive.shouldBe(false)
proc.exitValue().shouldBe(0)
}
"Launching directly and attaching later should eventually intercept all clients" {
// Start up the target:
val targetProc = ProcessBuilder(
javaPath,
"-jar", TEST_APP_JAR
).inheritIO().start()
runningProcs.add(targetProc)
targetProc.inputStream.read() // Wait until some output appears
sleep(2000) // Sleep a little extra, to check everything's fully running
// It shouldn't quit yet - it should block until we intercept
targetProc.isAlive.shouldBe(true)
// Attach the agent:
val agentAttachProc = ProcessBuilder(
javaPath,
"-jar", AGENT_JAR_PATH,
targetProc.pid().toString(), proxyHost, wireMockServer.port().toString(), certPath
).inheritIO().start()
runningProcs.add(agentAttachProc)
// Agent attacher should quit happily
agentAttachProc.waitFor(30, TimeUnit.SECONDS)
agentAttachProc.isAlive.shouldBe(false)
agentAttachProc.exitValue().shouldBe(0)
// Target should pick up proxy details & quit happily, eventually
targetProc.waitFor(30, TimeUnit.SECONDS)
targetProc.isAlive.shouldBe(false)
targetProc.exitValue().shouldBe(0)
}
}) {
override fun beforeTest(testCase: TestCase) {
super.beforeTest(testCase)
runningProcs.clear()
wireMockServer.start()
// Send a 200 response for all requests
wireMockServer.stubFor(any(anyUrl()).willReturn(ok()))
}
override fun afterTest(testCase: TestCase, result: TestResult) {
super.afterTest(testCase, result)
wireMockServer.stop()
runningProcs.forEach { proc -> proc.destroyForcibly() }
}
}