...

Source file src/github.com/LINBIT/golinstor/cache/cache_test.go

Documentation: github.com/LINBIT/golinstor/cache

     1  package cache_test
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"net/http"
     7  	"net/http/httptest"
     8  	"net/url"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/stretchr/testify/assert"
    13  
    14  	linstor "github.com/LINBIT/golinstor"
    15  	"github.com/LINBIT/golinstor/cache"
    16  	"github.com/LINBIT/golinstor/client"
    17  )
    18  
    19  type TestResponse struct {
    20  	Code int
    21  	Body any
    22  }
    23  
    24  type TestServer struct {
    25  	counter   map[string]int
    26  	responses map[string]TestResponse
    27  }
    28  
    29  func (t *TestServer) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
    30  	req := request.Method + " " + request.URL.String()
    31  	t.counter[req]++
    32  
    33  	resp, ok := t.responses[req]
    34  	if !ok {
    35  		writer.WriteHeader(http.StatusInternalServerError)
    36  	} else {
    37  		writer.WriteHeader(resp.Code)
    38  		_ = json.NewEncoder(writer).Encode(resp.Body)
    39  	}
    40  }
    41  
    42  const (
    43  	NodesRequest     = "GET /v1/nodes?cached=true&limit=0&offset=0"
    44  	ReconnectRequest = "PUT /v1/nodes/node1/reconnect"
    45  )
    46  
    47  var (
    48  	Node1 = client.Node{
    49  		Name: "node1",
    50  		Props: map[string]string{
    51  			"Aux/key1": "val1",
    52  			"Aux/key2": "val2",
    53  		},
    54  		Type: linstor.ValNodeTypeStlt,
    55  	}
    56  	Node2 = client.Node{
    57  		Name: "node2",
    58  		Props: map[string]string{
    59  			"Aux/key3": "val3",
    60  		},
    61  		Type: linstor.ValNodeTypeCmbd,
    62  	}
    63  	AllNodes = []client.Node{Node1, Node2}
    64  )
    65  
    66  func TestNodeCache(t *testing.T) {
    67  	testSrv := TestServer{
    68  		counter: make(map[string]int),
    69  		responses: map[string]TestResponse{
    70  			NodesRequest:     {Code: http.StatusOK, Body: AllNodes},
    71  			ReconnectRequest: {Code: http.StatusOK},
    72  		},
    73  	}
    74  	srv := httptest.NewServer(&testSrv)
    75  	defer srv.Close()
    76  
    77  	u, err := url.Parse(srv.URL)
    78  	assert.NoError(t, err)
    79  
    80  	cl, err := client.NewClient(
    81  		client.HTTPClient(srv.Client()),
    82  		client.BaseURL(u),
    83  		cache.WithCaches(&cache.NodeCache{Timeout: 1 * time.Second}),
    84  	)
    85  	assert.NoError(t, err)
    86  
    87  	nodes, err := cl.Nodes.GetAll(context.Background())
    88  	assert.NoError(t, err)
    89  	assert.Equal(t, AllNodes, nodes)
    90  
    91  	node1, err := cl.Nodes.Get(context.Background(), "node1")
    92  	assert.NoError(t, err)
    93  	assert.Equal(t, Node1, node1)
    94  
    95  	_, err = cl.Nodes.Get(context.Background(), "node3")
    96  	assert.Equal(t, client.NotFoundError, err)
    97  
    98  	// Assert that the request was only sent once
    99  	assert.Equal(t, 1, testSrv.counter[NodesRequest])
   100  
   101  	// Invalidate cache
   102  	err = cl.Nodes.Reconnect(context.Background(), "node1")
   103  	assert.NoError(t, err)
   104  
   105  	node1, err = cl.Nodes.Get(context.Background(), "node1")
   106  	assert.NoError(t, err)
   107  	assert.Equal(t, Node1, node1)
   108  	assert.Equal(t, 2, testSrv.counter[NodesRequest])
   109  
   110  	// Wait for cache time out to be reached
   111  	time.Sleep(1*time.Second + 100*time.Millisecond)
   112  	node1, err = cl.Nodes.Get(context.Background(), "node1")
   113  	assert.NoError(t, err)
   114  	assert.Equal(t, Node1, node1)
   115  	assert.Equal(t, 3, testSrv.counter[NodesRequest])
   116  }
   117  

View as plain text