github.com/fafucoder/cilium@v1.6.11/proxylib/helpers_test.go (about)

     1  // Copyright 2018 Authors of Cilium
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // +build !privileged_tests
    16  
    17  package main
    18  
    19  // These helpers must be defined in the main package so that the exported shared library functions
    20  // can be called, as the C types used in the prototypes are only available from within the main
    21  // package.
    22  //
    23  // These can not be defined in '_test.go' files, as Go test is not compatible with Cgo.
    24  
    25  import (
    26  	"testing"
    27  
    28  	. "github.com/cilium/cilium/proxylib/proxylib"
    29  )
    30  
    31  func numConnections() int {
    32  	mutex.Lock()
    33  	defer mutex.Unlock()
    34  	return len(connections)
    35  }
    36  
    37  func checkConnectionCount(t *testing.T, expConns int) {
    38  	t.Helper()
    39  	nConns := numConnections()
    40  	if nConns != expConns {
    41  		t.Errorf("Number of connections does not match (have %d, but should be %d)", nConns, expConns)
    42  	}
    43  }
    44  
    45  func checkConnections(t *testing.T, res, expected FilterResult, expConns int) {
    46  	t.Helper()
    47  	if res != expected {
    48  		t.Errorf("OnNewConnection(): Invalid result, have %s, expected %s", res.Error(), expected.Error())
    49  	}
    50  	checkConnectionCount(t, expConns)
    51  }
    52  
    53  func CheckOnNewConnection(t *testing.T, instanceId uint64, proto string, connectionId uint64, ingress bool, srcId, dstId uint32, srcAddr, dstAddr, policyName string, bufSize int, expResult FilterResult, expNumConnections int) *byte {
    54  	t.Helper()
    55  	origBuf := make([]byte, 0, bufSize)
    56  	replyBuf := make([]byte, 1, bufSize)
    57  	replyBufAddr := &replyBuf[0]
    58  	replyBuf = replyBuf[:0] // make the buffer empty again
    59  
    60  	res := FilterResult(OnNewConnection(instanceId, proto, connectionId, ingress, srcId, dstId, srcAddr, dstAddr, policyName, &origBuf, &replyBuf))
    61  	checkConnections(t, res, expResult, expNumConnections)
    62  
    63  	return replyBufAddr
    64  }
    65  
    66  func CheckClose(t *testing.T, connectionId uint64, replyBufAddr *byte, n int) {
    67  	t.Helper()
    68  	checkConnectionCount(t, n)
    69  
    70  	// Find the connection
    71  	mutex.Lock()
    72  	connection, ok := connections[connectionId]
    73  	mutex.Unlock()
    74  	if !ok {
    75  		t.Errorf("OnData(): Connection %d not found!", connectionId)
    76  	} else if replyBufAddr != nil && len(*connection.ReplyBuf) > 0 && replyBufAddr != &(*connection.ReplyBuf)[0] {
    77  		t.Error("OnData(): Reply injection buffer reallocated while it must not be!")
    78  	}
    79  
    80  	Close(connectionId)
    81  
    82  	checkConnectionCount(t, n-1)
    83  }
    84  
    85  type ExpFilterOp struct {
    86  	op      OpType
    87  	n_bytes int
    88  }
    89  
    90  func checkOps(ops [][2]int64, exp []ExpFilterOp) bool {
    91  	if len(ops) != len(exp) {
    92  		return false
    93  	} else {
    94  		for i, op := range ops {
    95  			if op[0] != int64(exp[i].op) || op[1] != int64(exp[i].n_bytes) {
    96  				return false
    97  			}
    98  		}
    99  	}
   100  	return true
   101  }
   102  
   103  func checkBuf(t *testing.T, buf InjectBuf, expected string) {
   104  	t.Helper()
   105  	if len(*buf) < len(expected) {
   106  		t.Log("Inject buffer too small, data truncated")
   107  		expected = expected[:len(*buf)] // truncate to buffer length
   108  	}
   109  	if string(*buf) != expected {
   110  		t.Errorf("OnData(): Expected inject buffer to be %s, buf have: %s", expected, *buf)
   111  	}
   112  }
   113  
   114  func checkOnData(t *testing.T, res, expected FilterResult, ops [][2]int64, expOps []ExpFilterOp) {
   115  	t.Helper()
   116  	if res != expected {
   117  		t.Errorf("OnData(): Invalid result, have %s, expected %s", res.Error(), expected.Error())
   118  	}
   119  	if !checkOps(ops, expOps) {
   120  		t.Errorf("OnData(): Unexpected filter operations: %v, expected %v", ops, expOps)
   121  	}
   122  }
   123  
   124  func CheckOnData(t *testing.T, connectionId uint64, reply, endStream bool, data *[][]byte, expOps []ExpFilterOp, expResult FilterResult, expReplyBuf string) {
   125  	t.Helper()
   126  
   127  	// Find the connection
   128  	mutex.Lock()
   129  	connection, ok := connections[connectionId]
   130  	mutex.Unlock()
   131  	if !ok && expResult != UNKNOWN_CONNECTION {
   132  		t.Errorf("OnData(): Connection %d not found!", connectionId)
   133  	}
   134  
   135  	ops := make([][2]int64, 0, 1+len(expOps)*2)
   136  
   137  	res := FilterResult(OnData(connectionId, reply, endStream, data, &ops))
   138  
   139  	checkOnData(t, res, expResult, ops, expOps)
   140  
   141  	if ok {
   142  		replyBuf := connection.ReplyBuf
   143  		checkBuf(t, replyBuf, expReplyBuf)
   144  		*replyBuf = (*replyBuf)[:0] // make empty again
   145  	}
   146  }