blob: 94cb0cad064e809a0c57d06b68ebca8fb514a2d7 [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,
19 HttpCliBadRequestTest)
Adrian Villincee15aa2024-03-14 11:42:55 -040020 registerNoTopoSoloTests(HttpStaticPromTest)
21}
22
23func HttpTpsTest(s *NsSuite) {
adrianvillin28bd8f02024-02-13 06:00:02 -050024 iface := s.getInterfaceByName(clientInterface)
Maros Ondrejickae7625d02023-02-28 16:55:01 +010025 client_ip := iface.ip4AddressString()
Filip Tehlarb15a0002022-11-10 12:34:17 +010026 port := "8080"
Maros Ondrejicka2908f8c2023-02-02 08:58:04 +010027 finished := make(chan error, 1)
adrianvillin28bd8f02024-02-13 06:00:02 -050028 clientNetns := s.getNetNamespaceByName("cln")
Maros Ondrejickadb823ed2022-12-14 16:30:04 +010029
30 container := s.getContainerByName("vpp")
Filip Tehlarb15a0002022-11-10 12:34:17 +010031
Maros Ondrejicka2908f8c2023-02-02 08:58:04 +010032 // configure vpp in the container
33 container.vppInstance.vppctl("http tps uri tcp://0.0.0.0/8080")
Filip Tehlarb15a0002022-11-10 12:34:17 +010034
Adrian Villincee15aa2024-03-14 11:42:55 -040035 go func() {
36 defer GinkgoRecover()
37 s.startWget(finished, client_ip, port, "test_file_10M", clientNetns)
38 }()
Filip Tehlarb15a0002022-11-10 12:34:17 +010039 // wait for client
Maros Ondrejicka2908f8c2023-02-02 08:58:04 +010040 err := <-finished
Adrian Villincee15aa2024-03-14 11:42:55 -040041 s.assertNil(err, fmt.Sprint(err))
Filip Tehlarb15a0002022-11-10 12:34:17 +010042}
43
Adrian Villincee15aa2024-03-14 11:42:55 -040044func HttpCliTest(s *VethsSuite) {
Maros Ondrejickadb823ed2022-12-14 16:30:04 +010045 serverContainer := s.getContainerByName("server-vpp")
46 clientContainer := s.getContainerByName("client-vpp")
Filip Tehlarb15a0002022-11-10 12:34:17 +010047
adrianvillin28bd8f02024-02-13 06:00:02 -050048 serverVeth := s.getInterfaceByName(serverInterfaceName)
Maros Ondrejickaffa3f602023-01-26 10:07:29 +010049
Maros Ondrejicka2908f8c2023-02-02 08:58:04 +010050 serverContainer.vppInstance.vppctl("http cli server")
Filip Tehlarb15a0002022-11-10 12:34:17 +010051
Maros Ondrejickae7625d02023-02-28 16:55:01 +010052 uri := "http://" + serverVeth.ip4AddressString() + "/80"
Maros Ondrejickaffa3f602023-01-26 10:07:29 +010053
Maros Ondrejicka2908f8c2023-02-02 08:58:04 +010054 o := clientContainer.vppInstance.vppctl("http cli client" +
Filip Tehlard8944382023-11-27 13:28:36 +010055 " uri " + uri + " query /show/vlib/graph")
Filip Tehlarb15a0002022-11-10 12:34:17 +010056
Maros Ondrejickaffa3f602023-01-26 10:07:29 +010057 s.log(o)
Maros Ondrejicka98a91e82022-12-06 15:38:05 +010058 s.assertContains(o, "<html>", "<html> not found in the result!")
Filip Tehlarb15a0002022-11-10 12:34:17 +010059}
Filip Tehlarc204c872022-12-21 08:59:16 +010060
Matus Fabian3d008932024-05-13 10:29:11 +020061func HttpCliConnectErrorTest(s *VethsSuite) {
62 clientContainer := s.getContainerByName("client-vpp")
63
64 serverVeth := s.getInterfaceByName(serverInterfaceName)
65
66 uri := "http://" + serverVeth.ip4AddressString() + "/80"
67
68 o := clientContainer.vppInstance.vppctl("http cli client" +
69 " uri " + uri + " query /show/vlib/graph")
70
71 s.log(o)
72 s.assertContains(o, "failed to connect")
73}
74
Adrian Villincee15aa2024-03-14 11:42:55 -040075func NginxHttp3Test(s *NoTopoSuite) {
Filip Tehlar31eaea92023-06-15 10:06:57 +020076 s.SkipUnlessExtendedTestsBuilt()
77
78 query := "index.html"
79 nginxCont := s.getContainerByName("nginx-http3")
80 s.assertNil(nginxCont.run())
81
82 vpp := s.getContainerByName("vpp").vppInstance
83 vpp.waitForApp("nginx-", 5)
adrianvillin28bd8f02024-02-13 06:00:02 -050084 serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
Filip Tehlar31eaea92023-06-15 10:06:57 +020085
86 defer func() { os.Remove(query) }()
87 curlCont := s.getContainerByName("curl")
Filip Tehlar87241fe2024-01-17 21:45:28 +010088 args := fmt.Sprintf("curl --noproxy '*' --local-port 55444 --http3-only -k https://%s:8443/%s", serverAddress, query)
Filip Tehlar31eaea92023-06-15 10:06:57 +020089 curlCont.extraRunningArgs = args
90 o, err := curlCont.combinedOutput()
Adrian Villincee15aa2024-03-14 11:42:55 -040091 s.assertNil(err, fmt.Sprint(err))
Filip Tehlar31eaea92023-06-15 10:06:57 +020092 s.assertContains(o, "<http>", "<http> not found in the result!")
93}
94
Adrian Villincee15aa2024-03-14 11:42:55 -040095func HttpStaticPromTest(s *NoTopoSuite) {
Filip Tehlarcc1475c2023-11-29 12:59:05 +010096 finished := make(chan error, 1)
97 query := "stats.prom"
98 vpp := s.getContainerByName("vpp").vppInstance
adrianvillin28bd8f02024-02-13 06:00:02 -050099 serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
Filip Tehlarcc1475c2023-11-29 12:59:05 +0100100 s.log(vpp.vppctl("http static server uri tcp://" + serverAddress + "/80 url-handlers"))
101 s.log(vpp.vppctl("prom enable"))
Adrian Villincee15aa2024-03-14 11:42:55 -0400102 time.Sleep(time.Second * 5)
103 go func() {
104 defer GinkgoRecover()
105 s.startWget(finished, serverAddress, "80", query, "")
106 }()
Filip Tehlarcc1475c2023-11-29 12:59:05 +0100107 err := <-finished
Adrian Villincee15aa2024-03-14 11:42:55 -0400108 s.assertNil(err)
Filip Tehlarcc1475c2023-11-29 12:59:05 +0100109}
110
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200111func HttpStaticMovedTest(s *NoTopoSuite) {
112 vpp := s.getContainerByName("vpp").vppInstance
113 vpp.container.exec("mkdir -p /tmp/tmp.aaa")
114 vpp.container.createFile("/tmp/tmp.aaa/index.html", "<http><body><p>Hello</p></body></http>")
115 serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
116 s.log(vpp.vppctl("http static server www-root /tmp uri tcp://" + serverAddress + "/80 debug"))
117
Matus Fabian595d8cb2024-05-17 11:28:43 +0200118 transport := http.DefaultTransport
119 transport.(*http.Transport).Proxy = nil
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200120 client := &http.Client{
121 CheckRedirect: func(req *http.Request, via []*http.Request) error {
122 return http.ErrUseLastResponse
123 },
Matus Fabian595d8cb2024-05-17 11:28:43 +0200124 Transport: transport,
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200125 }
126 req, err := http.NewRequest("GET", "http://"+serverAddress+":80/tmp.aaa", nil)
127 s.assertNil(err, fmt.Sprint(err))
128 resp, err := client.Do(req)
129 s.assertNil(err, fmt.Sprint(err))
130 defer resp.Body.Close()
131 s.assertEqual(301, resp.StatusCode)
132 s.assertNotEqual("", resp.Header.Get("Location"))
133}
134
135func HttpStaticNotFoundTest(s *NoTopoSuite) {
136 vpp := s.getContainerByName("vpp").vppInstance
137 serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
138 s.log(vpp.vppctl("http static server www-root /tmp uri tcp://" + serverAddress + "/80 debug"))
139
Matus Fabian595d8cb2024-05-17 11:28:43 +0200140 transport := http.DefaultTransport
141 transport.(*http.Transport).Proxy = nil
142 client := &http.Client{Transport: transport}
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200143 req, err := http.NewRequest("GET", "http://"+serverAddress+":80/notfound.html", nil)
144 s.assertNil(err, fmt.Sprint(err))
Matus Fabian595d8cb2024-05-17 11:28:43 +0200145 resp, err := client.Do(req)
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200146 s.assertNil(err, fmt.Sprint(err))
147 defer resp.Body.Close()
148 s.assertEqual(404, resp.StatusCode)
149}
150
151func HttpCliMethodNotAllowedTest(s *NoTopoSuite) {
Matus Fabian616201a2024-05-02 11:17:15 +0200152 vpp := s.getContainerByName("vpp").vppInstance
153 serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
154 vpp.vppctl("http cli server")
155
Matus Fabian595d8cb2024-05-17 11:28:43 +0200156 transport := http.DefaultTransport
157 transport.(*http.Transport).Proxy = nil
158 client := &http.Client{Transport: transport}
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200159 req, err := http.NewRequest("POST", "http://"+serverAddress+":80/test", nil)
Matus Fabian616201a2024-05-02 11:17:15 +0200160 s.assertNil(err, fmt.Sprint(err))
Matus Fabian595d8cb2024-05-17 11:28:43 +0200161 resp, err := client.Do(req)
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200162 s.assertNil(err, fmt.Sprint(err))
163 defer resp.Body.Close()
164 s.assertEqual(405, resp.StatusCode)
165 // TODO: need to be fixed in http code
166 //s.assertNotEqual("", resp.Header.Get("Allow"))
167}
168
169func HttpCliBadRequestTest(s *NoTopoSuite) {
170 vpp := s.getContainerByName("vpp").vppInstance
171 serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
172 vpp.vppctl("http cli server")
173
Matus Fabian595d8cb2024-05-17 11:28:43 +0200174 transport := http.DefaultTransport
175 transport.(*http.Transport).Proxy = nil
176 client := &http.Client{Transport: transport}
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200177 req, err := http.NewRequest("GET", "http://"+serverAddress+":80", nil)
178 s.assertNil(err, fmt.Sprint(err))
Matus Fabian595d8cb2024-05-17 11:28:43 +0200179 resp, err := client.Do(req)
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200180 s.assertNil(err, fmt.Sprint(err))
181 defer resp.Body.Close()
182 s.assertEqual(400, resp.StatusCode)
183}
184
185func HeaderServerTest(s *NoTopoSuite) {
186 vpp := s.getContainerByName("vpp").vppInstance
187 serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
188 vpp.vppctl("http cli server")
189
Matus Fabian595d8cb2024-05-17 11:28:43 +0200190 transport := http.DefaultTransport
191 transport.(*http.Transport).Proxy = nil
192 client := &http.Client{Transport: transport}
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200193 req, err := http.NewRequest("GET", "http://"+serverAddress+":80/show/version", nil)
194 s.assertNil(err, fmt.Sprint(err))
Matus Fabian595d8cb2024-05-17 11:28:43 +0200195 resp, err := client.Do(req)
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200196 s.assertNil(err, fmt.Sprint(err))
197 defer resp.Body.Close()
198 s.assertEqual("http_cli_server", resp.Header.Get("Server"))
Matus Fabian616201a2024-05-02 11:17:15 +0200199}
200
Adrian Villincee15aa2024-03-14 11:42:55 -0400201func NginxAsServerTest(s *NoTopoSuite) {
Filip Tehlarc204c872022-12-21 08:59:16 +0100202 query := "return_ok"
203 finished := make(chan error, 1)
Filip Tehlarc204c872022-12-21 08:59:16 +0100204
205 nginxCont := s.getContainerByName("nginx")
206 s.assertNil(nginxCont.run())
207
Maros Ondrejicka7550dd22023-02-07 20:40:27 +0100208 vpp := s.getContainerByName("vpp").vppInstance
Florin Corase2415f72023-02-28 14:51:03 -0800209 vpp.waitForApp("nginx-", 5)
Filip Tehlarc204c872022-12-21 08:59:16 +0100210
adrianvillin28bd8f02024-02-13 06:00:02 -0500211 serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
Maros Ondrejicka7550dd22023-02-07 20:40:27 +0100212
Filip Tehlarc204c872022-12-21 08:59:16 +0100213 defer func() { os.Remove(query) }()
Adrian Villincee15aa2024-03-14 11:42:55 -0400214 go func() {
215 defer GinkgoRecover()
216 s.startWget(finished, serverAddress, "80", query, "")
217 }()
Filip Tehlarc204c872022-12-21 08:59:16 +0100218 s.assertNil(<-finished)
219}
Filip Tehlar8df3de42023-01-27 13:14:34 +0100220
Filip Tehlar58113562023-04-15 20:41:18 +0200221func parseString(s, pattern string) string {
222 temp := strings.Split(s, "\n")
223 for _, item := range temp {
224 if strings.Contains(item, pattern) {
225 return item
226 }
227 }
228 return ""
229}
230
Filip Tehlar8df3de42023-01-27 13:14:34 +0100231func runNginxPerf(s *NoTopoSuite, mode, ab_or_wrk string) error {
232 nRequests := 1000000
Filip Tehlardda1f682023-04-24 17:52:50 +0200233 nClients := 1000
Filip Tehlar8df3de42023-01-27 13:14:34 +0100234
adrianvillin28bd8f02024-02-13 06:00:02 -0500235 serverAddress := s.getInterfaceByName(tapInterfaceName).peer.ip4AddressString()
Maros Ondrejicka7550dd22023-02-07 20:40:27 +0100236
Maros Ondrejicka7550dd22023-02-07 20:40:27 +0100237 vpp := s.getContainerByName("vpp").vppInstance
Filip Tehlar8df3de42023-01-27 13:14:34 +0100238
adrianvillinfbf5f2b2024-02-13 03:26:25 -0500239 nginxCont := s.getContainerByName(singleTopoContainerNginx)
Filip Tehlar8df3de42023-01-27 13:14:34 +0100240 s.assertNil(nginxCont.run())
Florin Corase2415f72023-02-28 14:51:03 -0800241 vpp.waitForApp("nginx-", 5)
Filip Tehlar8df3de42023-01-27 13:14:34 +0100242
Filip Tehlarb41b0af2023-03-20 12:39:20 +0100243 if ab_or_wrk == "ab" {
244 abCont := s.getContainerByName("ab")
245 args := fmt.Sprintf("-n %d -c %d", nRequests, nClients)
246 if mode == "rps" {
247 args += " -k"
248 } else if mode != "cps" {
249 return fmt.Errorf("invalid mode %s; expected cps/rps", mode)
250 }
Filip Tehlardda1f682023-04-24 17:52:50 +0200251 // don't exit on socket receive errors
252 args += " -r"
Filip Tehlarb41b0af2023-03-20 12:39:20 +0100253 args += " http://" + serverAddress + ":80/64B.json"
254 abCont.extraRunningArgs = args
Adrian Villincee15aa2024-03-14 11:42:55 -0400255 time.Sleep(time.Second * 10)
Filip Tehlarb41b0af2023-03-20 12:39:20 +0100256 o, err := abCont.combinedOutput()
Filip Tehlar58113562023-04-15 20:41:18 +0200257 rps := parseString(o, "Requests per second:")
Adrian Villincee15aa2024-03-14 11:42:55 -0400258 s.log(rps)
259 s.log(err)
adrianvillin7c675472024-02-12 02:44:53 -0500260 s.assertNil(err, "err: '%s', output: '%s'", err, o)
Filip Tehlarb41b0af2023-03-20 12:39:20 +0100261 } else {
262 wrkCont := s.getContainerByName("wrk")
263 args := fmt.Sprintf("-c %d -t 2 -d 30 http://%s:80/64B.json", nClients,
264 serverAddress)
265 wrkCont.extraRunningArgs = args
266 o, err := wrkCont.combinedOutput()
Filip Tehlar58113562023-04-15 20:41:18 +0200267 rps := parseString(o, "requests")
Adrian Villincee15aa2024-03-14 11:42:55 -0400268 s.log(rps)
269 s.log(err)
adrianvillin7c675472024-02-12 02:44:53 -0500270 s.assertNil(err, "err: '%s', output: '%s'", err, o)
Filip Tehlarb41b0af2023-03-20 12:39:20 +0100271 }
Filip Tehlar8df3de42023-01-27 13:14:34 +0100272 return nil
273}
274
Adrian Villin0df582e2024-05-22 09:26:47 -0400275// unstable with multiple workers
Adrian Villincee15aa2024-03-14 11:42:55 -0400276func NginxPerfCpsTest(s *NoTopoSuite) {
Adrian Villin0df582e2024-05-22 09:26:47 -0400277 s.SkipIfMultiWorker()
Filip Tehlar8df3de42023-01-27 13:14:34 +0100278 s.assertNil(runNginxPerf(s, "cps", "ab"))
279}
280
Adrian Villincee15aa2024-03-14 11:42:55 -0400281func NginxPerfRpsTest(s *NoTopoSuite) {
Filip Tehlar8df3de42023-01-27 13:14:34 +0100282 s.assertNil(runNginxPerf(s, "rps", "ab"))
283}
284
Adrian Villincee15aa2024-03-14 11:42:55 -0400285func NginxPerfWrkTest(s *NoTopoSuite) {
Filip Tehlar8df3de42023-01-27 13:14:34 +0100286 s.assertNil(runNginxPerf(s, "", "wrk"))
287}