blob: f51995c2aa2d2edf47b9540385b38767562739fd [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 server
import (
"net/http"
"strconv"
"testing"
"time"
)
import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
import (
"dubbo.apache.org/dubbo-go/v3/common/constant"
"dubbo.apache.org/dubbo-go/v3/common/extension"
"dubbo.apache.org/dubbo-go/v3/protocol"
_ "dubbo.apache.org/dubbo-go/v3/protocol/triple"
)
type httpMountTestHandler struct{}
func (h *httpMountTestHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {}
func TestServerAttachHTTPHandler(t *testing.T) {
srv, err := NewServer()
require.NoError(t, err)
handler := &httpMountTestHandler{}
err = srv.AttachHTTPHandler(handler)
require.NoError(t, err)
assert.Same(t, handler, srv.attachedHTTPHandler)
}
func TestServerAttachHTTPHandlerRejectsNil(t *testing.T) {
srv, err := NewServer()
require.NoError(t, err)
err = srv.AttachHTTPHandler(nil)
require.ErrorContains(t, err, "must not be nil")
}
func TestServerAttachHTTPHandlerRejectsDuplicate(t *testing.T) {
srv, err := NewServer()
require.NoError(t, err)
first := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
second := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
require.NoError(t, srv.AttachHTTPHandler(first))
err = srv.AttachHTTPHandler(second)
require.ErrorContains(t, err, "already been attached")
}
func TestServerAttachHTTPHandlerRejectsAfterServe(t *testing.T) {
srv, err := NewServer()
require.NoError(t, err)
srv.serve = true
err = srv.AttachHTTPHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
require.ErrorContains(t, err, "before Serve")
}
func TestHostAttachedHTTPHandlerRequiresTripleProtocol(t *testing.T) {
srv, err := NewServer(
WithServerProtocol(
protocol.WithDubbo(),
),
)
require.NoError(t, err)
require.NoError(t, srv.AttachHTTPHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})))
err = srv.hostAttachedHTTPHandler()
require.ErrorContains(t, err, "requires at least one triple protocol")
}
func TestHostAttachedHTTPHandlerRequiresExplicitPort(t *testing.T) {
srv, err := NewServer(
WithServerProtocol(
protocol.WithTriple(),
),
)
require.NoError(t, err)
srv.cfg.Protocols[constant.TriProtocol].Port = ""
require.NoError(t, srv.AttachHTTPHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})))
err = srv.hostAttachedHTTPHandler()
require.ErrorContains(t, err, "requires an explicit triple port")
}
func TestServeDoesNotHostAttachedHTTPHandlerBeforeLaterStartupFailures(t *testing.T) {
port := testFreePort(t)
srv, err := NewServer(
WithServerProtocol(
protocol.WithTriple(),
protocol.WithIp("127.0.0.1"),
protocol.WithPort(port),
),
)
require.NoError(t, err)
require.NoError(t, srv.AttachHTTPHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/healthz":
_, _ = w.Write([]byte("healthy"))
default:
http.NotFound(w, r)
}
})))
internalProLock.Lock()
originalInternalServices := internalProServices
internalProServices = []*InternalService{
{Name: "broken-internal-service"},
}
internalProLock.Unlock()
t.Cleanup(func() {
internalProLock.Lock()
internalProServices = originalInternalServices
internalProLock.Unlock()
})
t.Cleanup(func() {
extension.GetProtocol(constant.TriProtocol).Destroy()
})
err = srv.Serve()
require.ErrorContains(t, err, "internal service init func is empty")
client := &http.Client{Timeout: 100 * time.Millisecond}
baseURL := "http://127.0.0.1:" + strconv.Itoa(port)
deadline := time.Now().Add(time.Second)
for time.Now().Before(deadline) {
status, body, reqErr := simpleHTTPRequest(client, http.MethodGet, baseURL+"/healthz")
if reqErr == nil {
t.Fatalf("attached HTTP handler started after Serve failure: status=%d body=%q", status, body)
}
time.Sleep(50 * time.Millisecond)
}
}