github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/service/api/api_test.go (about)

     1  // Licensed under the Apache License, Version 2.0 (the "License");
     2  // you may not use this file except in compliance with the License.
     3  // You may obtain a copy of the License at
     4  //
     5  //     https://www.apache.org/licenses/LICENSE-2.0
     6  //
     7  // Unless required by applicable law or agreed to in writing, software
     8  // distributed under the License is distributed on an "AS IS" BASIS,
     9  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    10  // See the License for the specific language governing permissions and
    11  // limitations under the License.
    12  //
    13  // Original source: github.com/micro/go-micro/v3/api/api_test.go
    14  
    15  package api_test
    16  
    17  import (
    18  	"bytes"
    19  	"encoding/json"
    20  	"net/http"
    21  	"strings"
    22  	"testing"
    23  
    24  	"github.com/golang/protobuf/proto"
    25  	go_api "github.com/tickoalcantara12/micro/v3/proto/api"
    26  	"github.com/tickoalcantara12/micro/v3/service/api"
    27  )
    28  
    29  func TestEncoding(t *testing.T) {
    30  	testData := []*api.Endpoint{
    31  		nil,
    32  		{
    33  			Name:        "Foo.Bar",
    34  			Description: "A test endpoint",
    35  			Handler:     "meta",
    36  			Host:        []string{"foo.com"},
    37  			Method:      []string{"GET"},
    38  			Path:        []string{"/test"},
    39  		},
    40  	}
    41  
    42  	compare := func(expect, got []string) bool {
    43  		// no data to compare, return true
    44  		if len(expect) == 0 && len(got) == 0 {
    45  			return true
    46  		}
    47  		// no data expected but got some return false
    48  		if len(expect) == 0 && len(got) > 0 {
    49  			return false
    50  		}
    51  
    52  		// compare expected with what we got
    53  		for _, e := range expect {
    54  			var seen bool
    55  			for _, g := range got {
    56  				if e == g {
    57  					seen = true
    58  					break
    59  				}
    60  			}
    61  			if !seen {
    62  				return false
    63  			}
    64  		}
    65  
    66  		// we're done, return true
    67  		return true
    68  	}
    69  
    70  	for _, d := range testData {
    71  		// encode
    72  		e := api.Encode(d)
    73  		// decode
    74  		de := api.Decode(e)
    75  
    76  		// nil endpoint returns nil
    77  		if d == nil {
    78  			if e != nil {
    79  				t.Fatalf("expected nil got %v", e)
    80  			}
    81  			if de != nil {
    82  				t.Fatalf("expected nil got %v", de)
    83  			}
    84  
    85  			continue
    86  		}
    87  
    88  		// check encoded map
    89  		name := e["endpoint"]
    90  		desc := e["description"]
    91  		method := strings.Split(e["method"], ",")
    92  		path := strings.Split(e["path"], ",")
    93  		host := strings.Split(e["host"], ",")
    94  		handler := e["handler"]
    95  
    96  		if name != d.Name {
    97  			t.Fatalf("expected %v got %v", d.Name, name)
    98  		}
    99  		if desc != d.Description {
   100  			t.Fatalf("expected %v got %v", d.Description, desc)
   101  		}
   102  		if handler != d.Handler {
   103  			t.Fatalf("expected %v got %v", d.Handler, handler)
   104  		}
   105  		if ok := compare(d.Method, method); !ok {
   106  			t.Fatalf("expected %v got %v", d.Method, method)
   107  		}
   108  		if ok := compare(d.Path, path); !ok {
   109  			t.Fatalf("expected %v got %v", d.Path, path)
   110  		}
   111  		if ok := compare(d.Host, host); !ok {
   112  			t.Fatalf("expected %v got %v", d.Host, host)
   113  		}
   114  
   115  		if de.Name != d.Name {
   116  			t.Fatalf("expected %v got %v", d.Name, de.Name)
   117  		}
   118  		if de.Description != d.Description {
   119  			t.Fatalf("expected %v got %v", d.Description, de.Description)
   120  		}
   121  		if de.Handler != d.Handler {
   122  			t.Fatalf("expected %v got %v", d.Handler, de.Handler)
   123  		}
   124  		if ok := compare(d.Method, de.Method); !ok {
   125  			t.Fatalf("expected %v got %v", d.Method, de.Method)
   126  		}
   127  		if ok := compare(d.Path, de.Path); !ok {
   128  			t.Fatalf("expected %v got %v", d.Path, de.Path)
   129  		}
   130  		if ok := compare(d.Host, de.Host); !ok {
   131  			t.Fatalf("expected %v got %v", d.Host, de.Host)
   132  		}
   133  	}
   134  }
   135  
   136  func TestValidate(t *testing.T) {
   137  	epPcre := &api.Endpoint{
   138  		Name:        "Foo.Bar",
   139  		Description: "A test endpoint",
   140  		Handler:     "meta",
   141  		Host:        []string{"foo.com"},
   142  		Method:      []string{"GET"},
   143  		Path:        []string{"^/test/?$"},
   144  	}
   145  	if err := api.Validate(epPcre); err != nil {
   146  		t.Fatal(err)
   147  	}
   148  
   149  	epGpath := &api.Endpoint{
   150  		Name:        "Foo.Bar",
   151  		Description: "A test endpoint",
   152  		Handler:     "meta",
   153  		Host:        []string{"foo.com"},
   154  		Method:      []string{"GET"},
   155  		Path:        []string{"/test/{id}"},
   156  	}
   157  	if err := api.Validate(epGpath); err != nil {
   158  		t.Fatal(err)
   159  	}
   160  
   161  	epPcreInvalid := &api.Endpoint{
   162  		Name:        "Foo.Bar",
   163  		Description: "A test endpoint",
   164  		Handler:     "meta",
   165  		Host:        []string{"foo.com"},
   166  		Method:      []string{"GET"},
   167  		Path:        []string{"/test/?$"},
   168  	}
   169  	if err := api.Validate(epPcreInvalid); err == nil {
   170  		t.Fatalf("invalid pcre %v", epPcreInvalid.Path[0])
   171  	}
   172  
   173  }
   174  
   175  func TestRequestPayloadFromRequest(t *testing.T) {
   176  
   177  	// our test event so that we can validate serialising / deserializing of true protos works
   178  	protoEvent := go_api.Event{
   179  		Name: "Test",
   180  	}
   181  
   182  	protoBytes, err := proto.Marshal(&protoEvent)
   183  	if err != nil {
   184  		t.Fatal("Failed to marshal proto", err)
   185  	}
   186  
   187  	jsonBytes, err := json.Marshal(protoEvent)
   188  	if err != nil {
   189  		t.Fatal("Failed to marshal proto to JSON ", err)
   190  	}
   191  
   192  	jsonUrlBytes := []byte(`{"key1":"val1","key2":"val2","name":"Test"}`)
   193  
   194  	t.Run("extracting a json from a POST request with url params", func(t *testing.T) {
   195  		r, err := http.NewRequest("POST", "http://localhost/my/path?key1=val1&key2=val2", bytes.NewReader(jsonBytes))
   196  		if err != nil {
   197  			t.Fatalf("Failed to created http.Request: %v", err)
   198  		}
   199  
   200  		extByte, err := api.RequestPayload(r)
   201  		if err != nil {
   202  			t.Fatalf("Failed to extract payload from request: %v", err)
   203  		}
   204  		if string(extByte) != string(jsonUrlBytes) {
   205  			t.Fatalf("Expected %v and %v to match", string(extByte), jsonUrlBytes)
   206  		}
   207  	})
   208  
   209  	t.Run("extracting a proto from a POST request", func(t *testing.T) {
   210  		r, err := http.NewRequest("POST", "http://localhost/my/path", bytes.NewReader(protoBytes))
   211  		if err != nil {
   212  			t.Fatalf("Failed to created http.Request: %v", err)
   213  		}
   214  
   215  		extByte, err := api.RequestPayload(r)
   216  		if err != nil {
   217  			t.Fatalf("Failed to extract payload from request: %v", err)
   218  		}
   219  		if string(extByte) != string(protoBytes) {
   220  			t.Fatalf("Expected %v and %v to match", string(extByte), string(protoBytes))
   221  		}
   222  	})
   223  
   224  	t.Run("extracting JSON from a POST request", func(t *testing.T) {
   225  		r, err := http.NewRequest("POST", "http://localhost/my/path", bytes.NewReader(jsonBytes))
   226  		if err != nil {
   227  			t.Fatalf("Failed to created http.Request: %v", err)
   228  		}
   229  
   230  		extByte, err := api.RequestPayload(r)
   231  		if err != nil {
   232  			t.Fatalf("Failed to extract payload from request: %v", err)
   233  		}
   234  		if string(extByte) != string(jsonBytes) {
   235  			t.Fatalf("Expected %v and %v to match", string(extByte), string(jsonBytes))
   236  		}
   237  	})
   238  
   239  	t.Run("extracting params from a GET request", func(t *testing.T) {
   240  
   241  		r, err := http.NewRequest("GET", "http://localhost/my/path", nil)
   242  		if err != nil {
   243  			t.Fatalf("Failed to created http.Request: %v", err)
   244  		}
   245  
   246  		q := r.URL.Query()
   247  		q.Add("name", "Test")
   248  		r.URL.RawQuery = q.Encode()
   249  
   250  		extByte, err := api.RequestPayload(r)
   251  		if err != nil {
   252  			t.Fatalf("Failed to extract payload from request: %v", err)
   253  		}
   254  		if string(extByte) != string(jsonBytes) {
   255  			t.Fatalf("Expected %v and %v to match", string(extByte), string(jsonBytes))
   256  		}
   257  	})
   258  
   259  	t.Run("GET request with no params", func(t *testing.T) {
   260  
   261  		r, err := http.NewRequest("GET", "http://localhost/my/path", nil)
   262  		if err != nil {
   263  			t.Fatalf("Failed to created http.Request: %v", err)
   264  		}
   265  
   266  		extByte, err := api.RequestPayload(r)
   267  		if err != nil {
   268  			t.Fatalf("Failed to extract payload from request: %v", err)
   269  		}
   270  		if string(extByte) != "" {
   271  			t.Fatalf("Expected %v and %v to match", string(extByte), "")
   272  		}
   273  	})
   274  }