Repository: cloudwego/hertz
Pull request #708 (2023-04-05 13:45:58)

feat: add CreateUtRequestContext function
#### What type of PR is this?
feat
<!--
Add one of the following kinds:

build: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
ci: Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)
docs: Documentation only changes
feat: A new feature
optimize: A new optimization
fix: A bug fix
perf: A code change that improves performance
refactor: A code change that neither fixes a bug nor adds a feature
style: Changes that do not affect the meaning of the code (white space, formatting, missing semi-colons, etc)
test: Adding missing tests or correcting existing tests
chore: Changes to the build process or auxiliary tools and libraries such as documentation generation
-->

#### Check the PR title.
<!--
The description of the title will be attached in Release Notes, 
so please describe it from user-oriented, what this PR does / why we need it.
Please check your PR title with the below requirements:
-->
- [x] This PR title match the format: \<type\>(optional scope): \<description\>
- [x] The description of this PR title is user-oriented and clear enough for others to understand.


#### (Optional) Translate the PR title into Chinese.
- 添加 CreateUtRequestContext 函数，用于辅助用户编写单测

#### Which issue(s) this PR fixes:
<!--
Automatically closes linked issue when PR is merged.
Eg: `Fixes #<issue number>`, or `Fixes (paste link of issue)`.
-->



Patch:
diff --git a/pkg/common/ut/context.go b/pkg/common/ut/context.go
new file mode 100644
index 0000000..30023dd
--- /dev/null
+++ b/pkg/common/ut/context.go
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2023 CloudWeGo Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ut
+
+import (
+	"io"
+	"io/ioutil"
+
+	"github.com/cloudwego/hertz/pkg/app"
+	"github.com/cloudwego/hertz/pkg/common/config"
+	"github.com/cloudwego/hertz/pkg/protocol"
+	"github.com/cloudwego/hertz/pkg/route"
+)
+
+// CreateUtRequestContext returns an app.RequestContext for testing purposes
+func CreateUtRequestContext(method, url string, body *Body, headers ...Header) *app.RequestContext {
+	engine := route.NewEngine(config.NewOptions([]config.Option{}))
+	return createUtRequestContext(engine, method, url, body, headers...)
+}
+
+func createUtRequestContext(engine *route.Engine, method, url string, body *Body, headers ...Header) *app.RequestContext {
+	ctx := engine.NewContext()
+
+	var r *protocol.Request
+	if body != nil && body.Body != nil {
+		r = protocol.NewRequest(method, url, body.Body)
+		r.CopyTo(&ctx.Request)
+		if engine.IsStreamRequestBody() || body.Len == -1 {
+			ctx.Request.SetBodyStream(body.Body, body.Len)
+		} else {
+			buf, err := ioutil.ReadAll(&io.LimitedReader{R: body.Body, N: int64(body.Len)})
+			ctx.Request.SetBody(buf)
+			if err != nil && err != io.EOF {
+				panic(err)
+			}
+		}
+	} else {
+		r = protocol.NewRequest(method, url, nil)
+		r.CopyTo(&ctx.Request)
+	}
+
+	for _, v := range headers {
+		if ctx.Request.Header.Get(v.Key) != "" {
+			ctx.Request.Header.Add(v.Key, v.Value)
+		} else {
+			ctx.Request.Header.Set(v.Key, v.Value)
+		}
+	}
+
+	return ctx
+}
diff --git a/pkg/common/ut/request.go b/pkg/common/ut/request.go
index f6dcfc4..93f8f91 100644
--- a/pkg/common/ut/request.go
+++ b/pkg/common/ut/request.go
@@ -20,9 +20,7 @@ package ut
 import (
 	"context"
 	"io"
-	"io/ioutil"
 
-	"github.com/cloudwego/hertz/pkg/protocol"
 	"github.com/cloudwego/hertz/pkg/route"
 )
 
@@ -49,34 +47,7 @@ type Body struct {
 //
 // See ./request_test.go for more examples
 func PerformRequest(engine *route.Engine, method, url string, body *Body, headers ...Header) *ResponseRecorder {
-	ctx := engine.NewContext()
-
-	var r *protocol.Request
-	if body != nil && body.Body != nil {
-		r = protocol.NewRequest(method, url, body.Body)
-		r.CopyTo(&ctx.Request)
-		if engine.IsStreamRequestBody() || body.Len == -1 {
-			ctx.Request.SetBodyStream(body.Body, body.Len)
-		} else {
-			buf, err := ioutil.ReadAll(&io.LimitedReader{R: body.Body, N: int64(body.Len)})
-			ctx.Request.SetBody(buf)
-			if err != nil && err != io.EOF {
-				panic(err)
-			}
-		}
-	} else {
-		r = protocol.NewRequest(method, url, nil)
-		r.CopyTo(&ctx.Request)
-	}
-
-	for _, v := range headers {
-		if ctx.Request.Header.Get(v.Key) != "" {
-			ctx.Request.Header.Add(v.Key, v.Value)
-		} else {
-			ctx.Request.Header.Set(v.Key, v.Value)
-		}
-	}
-
+	ctx := createUtRequestContext(engine, method, url, body, headers...)
 	engine.ServeHTTP(context.Background(), ctx)
 
 	w := NewRecorder()


Test patch:
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index b3e284c..fbe4130 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -1,13 +1,30 @@
 name: Tests
 
-on: [ push, pull_request ]
+on: [push, pull_request]
 
 jobs:
+  compat-test:
+    strategy:
+      matrix:
+        version: ["1.16", "1.17"]
+    runs-on: [self-hosted, X64]
+    steps:
+      - uses: actions/checkout@v3
+
+      - name: Set up Go
+        uses: actions/setup-go@v3
+        with:
+          go-version: ${{ matrix.version }}
+
+      # Just build tests without running them
+      - name: Build Test
+        run: go test -run=nope ./...
+
   lint-and-ut:
     strategy:
       matrix:
-        version: [ '1.18', '1.19', '1.20' ]
-    runs-on: [ self-hosted, X64 ]
+        version: ["1.18", "1.19", "1.20"]
+    runs-on: [self-hosted, X64]
     steps:
       - uses: actions/checkout@v3
 
@@ -31,7 +48,7 @@ jobs:
   ut-windows:
     strategy:
       matrix:
-        version: [ '1.18', '1.19', '1.20' ]
+        version: ["1.18", "1.19", "1.20"]
     runs-on: windows-latest
     steps:
       - uses: actions/checkout@v3
diff --git a/pkg/common/ut/context_test.go b/pkg/common/ut/context_test.go
new file mode 100644
index 0000000..023945c
--- /dev/null
+++ b/pkg/common/ut/context_test.go
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2023 CloudWeGo Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ut
+
+import (
+	"bytes"
+	"testing"
+
+	"github.com/cloudwego/hertz/pkg/common/test/assert"
+)
+
+func TestCreateUtRequestContext(t *testing.T) {
+	body := "1"
+	method := "PUT"
+	path := "/hey/dy"
+	headerKey := "Connection"
+	headerValue := "close"
+	ctx := CreateUtRequestContext(method, path, &Body{bytes.NewBufferString(body), len(body)},
+		Header{headerKey, headerValue})
+
+	assert.DeepEqual(t, method, string(ctx.Method()))
+	assert.DeepEqual(t, path, string(ctx.Path()))
+	body1, err := ctx.Body()
+	assert.DeepEqual(t, nil, err)
+	assert.DeepEqual(t, body, string(body1))
+	assert.DeepEqual(t, headerValue, string(ctx.GetHeader(headerKey)))
+}