blob: 875d489b3432d5a69d5093673c75c3626ec7e5c5 [file] [log] [blame]
Filip Tehlarb15a0002022-11-10 12:34:17 +01001package main
2
Filip Tehlarc204c872022-12-21 08:59:16 +01003import (
Filip Tehlar8df3de42023-01-27 13:14:34 +01004 "fmt"
Matus Fabianb7a9ed72024-05-10 16:20:40 +02005 "net/http"
Filip Tehlarc204c872022-12-21 08:59:16 +01006 "os"
Filip Tehlar58113562023-04-15 20:41:18 +02007 "strings"
Adrian Villincee15aa2024-03-14 11:42:55 -04008 "time"
9
10 . "github.com/onsi/ginkgo/v2"
Filip Tehlarc204c872022-12-21 08:59:16 +010011)
12
Adrian Villincee15aa2024-03-14 11:42:55 -040013func init() {
14 registerNsTests(HttpTpsTest)
Matus Fabian3d008932024-05-13 10:29:11 +020015 registerVethTests(HttpCliTest, HttpCliConnectErrorTest)
Adrian Villincee15aa2024-03-14 11:42:55 -040016 registerNoTopoTests(NginxHttp3Test, NginxAsServerTest,
Matus Fabianb7a9ed72024-05-10 16:20:40 +020017 NginxPerfCpsTest, NginxPerfRpsTest, NginxPerfWrkTest, HeaderServerTest,
18 HttpStaticMovedTest, HttpStaticNotFoundTest, HttpCliMethodNotAllowedTest,
Matus Fabian5409d332024-05-28 13:39:13 +020019 HttpCliBadRequestTest, HttpStaticPathTraversalTest)
Adrian Villincee15aa2024-03-14 11:42:55 -040020 registerNoTopoSoloTests(HttpStaticPromTest)
21}
22
Matus Fabian5409d332024-05-28 13:39:13 +020023const wwwRootPath = "/tmp/www_root"
24
Adrian Villincee15aa2024-03-14 11:42:55 -040025func HttpTpsTest(s *NsSuite) {
adrianvillin28bd8f02024-02-13 06:00:02 -050026 iface := s.getInterfaceByName(clientInterface)
Maros Ondrejickae7625d02023-02-28 16:55:01 +010027 client_ip := iface.ip4AddressString()
Filip Tehlarb15a0002022-11-10 12:34:17 +010028 port := "8080"
Maros Ondrejicka2908f8c2023-02-02 08:58:04 +010029 finished := make(chan error, 1)
adrianvillin28bd8f02024-02-13 06:00:02 -050030 clientNetns := s.getNetNamespaceByName("cln")
Maros Ondrejickadb823ed2022-12-14 16:30:04 +010031
32 container := s.getContainerByName("vpp")
Filip Tehlarb15a0002022-11-10 12:34:17 +010033
Maros Ondrejicka2908f8c2023-02-02 08:58:04 +010034 // configure vpp in the container
35 container.vppInstance.vppctl("http tps uri tcp://0.0.0.0/8080")
Filip Tehlarb15a0002022-11-10 12:34:17 +010036
Adrian Villincee15aa2024-03-14 11:42:55 -040037 go func() {
38 defer GinkgoRecover()
39 s.startWget(finished, client_ip, port, "test_file_10M", clientNetns)
40 }()
Filip Tehlarb15a0002022-11-10 12:34:17 +010041 // wait for client
Maros Ondrejicka2908f8c2023-02-02 08:58:04 +010042 err := <-finished
Adrian Villincee15aa2024-03-14 11:42:55 -040043 s.assertNil(err, fmt.Sprint(err))
Filip Tehlarb15a0002022-11-10 12:34:17 +010044}
45
Adrian Villincee15aa2024-03-14 11:42:55 -040046func HttpCliTest(s *VethsSuite) {
Maros Ondrejickadb823ed2022-12-14 16:30:04 +010047 serverContainer := s.getContainerByName("server-vpp")
48 clientContainer := s.getContainerByName("client-vpp")
Filip Tehlarb15a0002022-11-10 12:34:17 +010049
adrianvillin28bd8f02024-02-13 06:00:02 -050050 serverVeth := s.getInterfaceByName(serverInterfaceName)
Maros Ondrejickaffa3f602023-01-26 10:07:29 +010051
Maros Ondrejicka2908f8c2023-02-02 08:58:04 +010052 serverContainer.vppInstance.vppctl("http cli server")
Filip Tehlarb15a0002022-11-10 12:34:17 +010053
Maros Ondrejickae7625d02023-02-28 16:55:01 +010054 uri := "http://" + serverVeth.ip4AddressString() + "/80"
Maros Ondrejickaffa3f602023-01-26 10:07:29 +010055
Maros Ondrejicka2908f8c2023-02-02 08:58:04 +010056 o := clientContainer.vppInstance.vppctl("http cli client" +
Filip Tehlard8944382023-11-27 13:28:36 +010057 " uri " + uri + " query /show/vlib/graph")
Filip Tehlarb15a0002022-11-10 12:34:17 +010058
Maros Ondrejickaffa3f602023-01-26 10:07:29 +010059 s.log(o)
Maros Ondrejicka98a91e82022-12-06 15:38:05 +010060 s.assertContains(o, "<html>", "<html> not found in the result!")
Filip Tehlarb15a0002022-11-10 12:34:17 +010061}
Filip Tehlarc204c872022-12-21 08:59:16 +010062
Matus Fabian3d008932024-05-13 10:29:11 +020063func HttpCliConnectErrorTest(s *VethsSuite) {
64 clientContainer := s.getContainerByName("client-vpp")
65
66 serverVeth := s.getInterfaceByName(serverInterfaceName)
67
68 uri := "http://" + serverVeth.ip4AddressString() + "/80"
69
70 o := clientContainer.vppInstance.vppctl("http cli client" +
71 " uri " + uri + " query /show/vlib/graph")
72
73 s.log(o)
74 s.assertContains(o, "failed to connect")
75}
76
Adrian Villincee15aa2024-03-14 11:42:55 -040077func NginxHttp3Test(s *NoTopoSuite) {
Filip Tehlar31eaea92023-06-15 10:06:57 +020078 s.SkipUnlessExtendedTestsBuilt()
79
80 query := "index.html"
81 nginxCont := s.getContainerByName("nginx-http3")
82 s.assertNil(nginxCont.run())
83
84 vpp := s.getContainerByName("vpp").vppInstance
85 vpp.waitForApp("nginx-", 5)
adrianvillin28bd8f02024-02-13 06:00:02 -050086 serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
Filip Tehlar31eaea92023-06-15 10:06:57 +020087
88 defer func() { os.Remove(query) }()
89 curlCont := s.getContainerByName("curl")
Filip Tehlar87241fe2024-01-17 21:45:28 +010090 args := fmt.Sprintf("curl --noproxy '*' --local-port 55444 --http3-only -k https://%s:8443/%s", serverAddress, query)
Filip Tehlar31eaea92023-06-15 10:06:57 +020091 curlCont.extraRunningArgs = args
92 o, err := curlCont.combinedOutput()
Adrian Villincee15aa2024-03-14 11:42:55 -040093 s.assertNil(err, fmt.Sprint(err))
Filip Tehlar31eaea92023-06-15 10:06:57 +020094 s.assertContains(o, "<http>", "<http> not found in the result!")
95}
96
Adrian Villincee15aa2024-03-14 11:42:55 -040097func HttpStaticPromTest(s *NoTopoSuite) {
Filip Tehlarcc1475c2023-11-29 12:59:05 +010098 finished := make(chan error, 1)
99 query := "stats.prom"
100 vpp := s.getContainerByName("vpp").vppInstance
adrianvillin28bd8f02024-02-13 06:00:02 -0500101 serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
Filip Tehlarcc1475c2023-11-29 12:59:05 +0100102 s.log(vpp.vppctl("http static server uri tcp://" + serverAddress + "/80 url-handlers"))
103 s.log(vpp.vppctl("prom enable"))
Adrian Villincee15aa2024-03-14 11:42:55 -0400104 time.Sleep(time.Second * 5)
105 go func() {
106 defer GinkgoRecover()
107 s.startWget(finished, serverAddress, "80", query, "")
108 }()
Filip Tehlarcc1475c2023-11-29 12:59:05 +0100109 err := <-finished
Adrian Villincee15aa2024-03-14 11:42:55 -0400110 s.assertNil(err)
Filip Tehlarcc1475c2023-11-29 12:59:05 +0100111}
112
Matus Fabian5409d332024-05-28 13:39:13 +0200113func HttpStaticPathTraversalTest(s *NoTopoSuite) {
114 vpp := s.getContainerByName("vpp").vppInstance
115 vpp.container.exec("mkdir -p " + wwwRootPath)
116 vpp.container.exec("mkdir -p " + "/tmp/secret_folder")
117 vpp.container.createFile("/tmp/secret_folder/secret_file.txt", "secret")
118 serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
119 s.log(vpp.vppctl("http static server www-root " + wwwRootPath + " uri tcp://" + serverAddress + "/80 debug"))
120
121 client := newHttpClient()
122 req, err := http.NewRequest("GET", "http://"+serverAddress+":80/../secret_folder/secret_file.txt", nil)
123 s.assertNil(err, fmt.Sprint(err))
124 resp, err := client.Do(req)
125 s.assertNil(err, fmt.Sprint(err))
126 defer resp.Body.Close()
127 s.assertEqual(404, resp.StatusCode)
128}
129
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200130func HttpStaticMovedTest(s *NoTopoSuite) {
131 vpp := s.getContainerByName("vpp").vppInstance
Matus Fabian5409d332024-05-28 13:39:13 +0200132 vpp.container.exec("mkdir -p " + wwwRootPath + "/tmp.aaa")
133 vpp.container.createFile(wwwRootPath+"/tmp.aaa/index.html", "<http><body><p>Hello</p></body></http>")
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200134 serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
Matus Fabian5409d332024-05-28 13:39:13 +0200135 s.log(vpp.vppctl("http static server www-root " + wwwRootPath + " uri tcp://" + serverAddress + "/80 debug"))
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200136
Matus Fabian5409d332024-05-28 13:39:13 +0200137 client := newHttpClient()
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200138 req, err := http.NewRequest("GET", "http://"+serverAddress+":80/tmp.aaa", nil)
139 s.assertNil(err, fmt.Sprint(err))
140 resp, err := client.Do(req)
141 s.assertNil(err, fmt.Sprint(err))
142 defer resp.Body.Close()
143 s.assertEqual(301, resp.StatusCode)
144 s.assertNotEqual("", resp.Header.Get("Location"))
145}
146
147func HttpStaticNotFoundTest(s *NoTopoSuite) {
148 vpp := s.getContainerByName("vpp").vppInstance
Matus Fabian5409d332024-05-28 13:39:13 +0200149 vpp.container.exec("mkdir -p " + wwwRootPath)
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200150 serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
Matus Fabian5409d332024-05-28 13:39:13 +0200151 s.log(vpp.vppctl("http static server www-root " + wwwRootPath + " uri tcp://" + serverAddress + "/80 debug"))
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200152
Matus Fabian5409d332024-05-28 13:39:13 +0200153 client := newHttpClient()
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200154 req, err := http.NewRequest("GET", "http://"+serverAddress+":80/notfound.html", nil)
155 s.assertNil(err, fmt.Sprint(err))
Matus Fabian595d8cb2024-05-17 11:28:43 +0200156 resp, err := client.Do(req)
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200157 s.assertNil(err, fmt.Sprint(err))
158 defer resp.Body.Close()
159 s.assertEqual(404, resp.StatusCode)
160}
161
162func HttpCliMethodNotAllowedTest(s *NoTopoSuite) {
Matus Fabian616201a2024-05-02 11:17:15 +0200163 vpp := s.getContainerByName("vpp").vppInstance
164 serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
165 vpp.vppctl("http cli server")
166
Matus Fabian5409d332024-05-28 13:39:13 +0200167 client := newHttpClient()
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200168 req, err := http.NewRequest("POST", "http://"+serverAddress+":80/test", nil)
Matus Fabian616201a2024-05-02 11:17:15 +0200169 s.assertNil(err, fmt.Sprint(err))
Matus Fabian595d8cb2024-05-17 11:28:43 +0200170 resp, err := client.Do(req)
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200171 s.assertNil(err, fmt.Sprint(err))
172 defer resp.Body.Close()
173 s.assertEqual(405, resp.StatusCode)
174 // TODO: need to be fixed in http code
175 //s.assertNotEqual("", resp.Header.Get("Allow"))
176}
177
178func HttpCliBadRequestTest(s *NoTopoSuite) {
179 vpp := s.getContainerByName("vpp").vppInstance
180 serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
181 vpp.vppctl("http cli server")
182
Matus Fabian5409d332024-05-28 13:39:13 +0200183 client := newHttpClient()
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200184 req, err := http.NewRequest("GET", "http://"+serverAddress+":80", nil)
185 s.assertNil(err, fmt.Sprint(err))
Matus Fabian595d8cb2024-05-17 11:28:43 +0200186 resp, err := client.Do(req)
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200187 s.assertNil(err, fmt.Sprint(err))
188 defer resp.Body.Close()
189 s.assertEqual(400, resp.StatusCode)
190}
191
192func HeaderServerTest(s *NoTopoSuite) {
193 vpp := s.getContainerByName("vpp").vppInstance
194 serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
195 vpp.vppctl("http cli server")
196
Matus Fabian5409d332024-05-28 13:39:13 +0200197 client := newHttpClient()
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200198 req, err := http.NewRequest("GET", "http://"+serverAddress+":80/show/version", nil)
199 s.assertNil(err, fmt.Sprint(err))
Matus Fabian595d8cb2024-05-17 11:28:43 +0200200 resp, err := client.Do(req)
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200201 s.assertNil(err, fmt.Sprint(err))
202 defer resp.Body.Close()
203 s.assertEqual("http_cli_server", resp.Header.Get("Server"))
Matus Fabian616201a2024-05-02 11:17:15 +0200204}
205
Adrian Villincee15aa2024-03-14 11:42:55 -0400206func NginxAsServerTest(s *NoTopoSuite) {
Filip Tehlarc204c872022-12-21 08:59:16 +0100207 query := "return_ok"
208 finished := make(chan error, 1)
Filip Tehlarc204c872022-12-21 08:59:16 +0100209
210 nginxCont := s.getContainerByName("nginx")
211 s.assertNil(nginxCont.run())
212
Maros Ondrejicka7550dd22023-02-07 20:40:27 +0100213 vpp := s.getContainerByName("vpp").vppInstance
Florin Corase2415f72023-02-28 14:51:03 -0800214 vpp.waitForApp("nginx-", 5)
Filip Tehlarc204c872022-12-21 08:59:16 +0100215
adrianvillin28bd8f02024-02-13 06:00:02 -0500216 serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
Maros Ondrejicka7550dd22023-02-07 20:40:27 +0100217
Filip Tehlarc204c872022-12-21 08:59:16 +0100218 defer func() { os.Remove(query) }()
Adrian Villincee15aa2024-03-14 11:42:55 -0400219 go func() {
220 defer GinkgoRecover()
221 s.startWget(finished, serverAddress, "80", query, "")
222 }()
Filip Tehlarc204c872022-12-21 08:59:16 +0100223 s.assertNil(<-finished)
224}
Filip Tehlar8df3de42023-01-27 13:14:34 +0100225
Filip Tehlar58113562023-04-15 20:41:18 +0200226func parseString(s, pattern string) string {
227 temp := strings.Split(s, "\n")
228 for _, item := range temp {
229 if strings.Contains(item, pattern) {
230 return item
231 }
232 }
233 return ""
234}
235
Filip Tehlar8df3de42023-01-27 13:14:34 +0100236func runNginxPerf(s *NoTopoSuite, mode, ab_or_wrk string) error {
237 nRequests := 1000000
Filip Tehlardda1f682023-04-24 17:52:50 +0200238 nClients := 1000
Filip Tehlar8df3de42023-01-27 13:14:34 +0100239
adrianvillin28bd8f02024-02-13 06:00:02 -0500240 serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
Maros Ondrejicka7550dd22023-02-07 20:40:27 +0100241
Maros Ondrejicka7550dd22023-02-07 20:40:27 +0100242 vpp := s.getContainerByName("vpp").vppInstance
Filip Tehlar8df3de42023-01-27 13:14:34 +0100243
adrianvillinfbf5f2b2024-02-13 03:26:25 -0500244 nginxCont := s.getContainerByName(singleTopoContainerNginx)
Filip Tehlar8df3de42023-01-27 13:14:34 +0100245 s.assertNil(nginxCont.run())
Florin Corase2415f72023-02-28 14:51:03 -0800246 vpp.waitForApp("nginx-", 5)
Filip Tehlar8df3de42023-01-27 13:14:34 +0100247
Filip Tehlarb41b0af2023-03-20 12:39:20 +0100248 if ab_or_wrk == "ab" {
249 abCont := s.getContainerByName("ab")
Adrian Villin7ad37b52024-06-05 05:53:50 -0400250 abCont.runDetached = true
Filip Tehlarb41b0af2023-03-20 12:39:20 +0100251 args := fmt.Sprintf("-n %d -c %d", nRequests, nClients)
252 if mode == "rps" {
253 args += " -k"
254 } else if mode != "cps" {
255 return fmt.Errorf("invalid mode %s; expected cps/rps", mode)
256 }
Filip Tehlardda1f682023-04-24 17:52:50 +0200257 // don't exit on socket receive errors
258 args += " -r"
Filip Tehlarb41b0af2023-03-20 12:39:20 +0100259 args += " http://" + serverAddress + ":80/64B.json"
260 abCont.extraRunningArgs = args
261 o, err := abCont.combinedOutput()
Filip Tehlar58113562023-04-15 20:41:18 +0200262 rps := parseString(o, "Requests per second:")
Adrian Villincee15aa2024-03-14 11:42:55 -0400263 s.log(rps)
264 s.log(err)
adrianvillin7c675472024-02-12 02:44:53 -0500265 s.assertNil(err, "err: '%s', output: '%s'", err, o)
Filip Tehlarb41b0af2023-03-20 12:39:20 +0100266 } else {
267 wrkCont := s.getContainerByName("wrk")
Adrian Villin7ad37b52024-06-05 05:53:50 -0400268 wrkCont.runDetached = true
Filip Tehlarb41b0af2023-03-20 12:39:20 +0100269 args := fmt.Sprintf("-c %d -t 2 -d 30 http://%s:80/64B.json", nClients,
270 serverAddress)
271 wrkCont.extraRunningArgs = args
272 o, err := wrkCont.combinedOutput()
Filip Tehlar58113562023-04-15 20:41:18 +0200273 rps := parseString(o, "requests")
Adrian Villincee15aa2024-03-14 11:42:55 -0400274 s.log(rps)
275 s.log(err)
adrianvillin7c675472024-02-12 02:44:53 -0500276 s.assertNil(err, "err: '%s', output: '%s'", err, o)
Filip Tehlarb41b0af2023-03-20 12:39:20 +0100277 }
Filip Tehlar8df3de42023-01-27 13:14:34 +0100278 return nil
279}
280
Adrian Villin0df582e2024-05-22 09:26:47 -0400281// unstable with multiple workers
Adrian Villincee15aa2024-03-14 11:42:55 -0400282func NginxPerfCpsTest(s *NoTopoSuite) {
Adrian Villin0df582e2024-05-22 09:26:47 -0400283 s.SkipIfMultiWorker()
Filip Tehlar8df3de42023-01-27 13:14:34 +0100284 s.assertNil(runNginxPerf(s, "cps", "ab"))
285}
286
Adrian Villincee15aa2024-03-14 11:42:55 -0400287func NginxPerfRpsTest(s *NoTopoSuite) {
Filip Tehlar8df3de42023-01-27 13:14:34 +0100288 s.assertNil(runNginxPerf(s, "rps", "ab"))
289}
290
Adrian Villincee15aa2024-03-14 11:42:55 -0400291func NginxPerfWrkTest(s *NoTopoSuite) {
Filip Tehlar8df3de42023-01-27 13:14:34 +0100292 s.assertNil(runNginxPerf(s, "", "wrk"))
293}