gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/bpf/decoder_test.go (about)

     1  // Copyright 2018 The gVisor Authors.
     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  package bpf
    16  
    17  import (
    18  	"testing"
    19  )
    20  
    21  func TestDecode(t *testing.T) {
    22  	for _, test := range []struct {
    23  		filter   Instruction
    24  		expected string
    25  		fail     bool
    26  	}{
    27  		{filter: Stmt(Ld+Imm, 10), expected: "A <- 10"},
    28  		{filter: Stmt(Ld+Abs+W, 10), expected: "A <- P[10:4]"},
    29  		{filter: Stmt(Ld+Ind+H, 10), expected: "A <- P[X+10:2]"},
    30  		{filter: Stmt(Ld+Ind+B, 10), expected: "A <- P[X+10:1]"},
    31  		{filter: Stmt(Ld+Mem, 10), expected: "A <- M[10]"},
    32  		{filter: Stmt(Ld+Len, 0), expected: "A <- len"},
    33  		{filter: Stmt(Ldx+Imm, 10), expected: "X <- 10"},
    34  		{filter: Stmt(Ldx+Mem, 10), expected: "X <- M[10]"},
    35  		{filter: Stmt(Ldx+Len, 0), expected: "X <- len"},
    36  		{filter: Stmt(Ldx+Msh, 10), expected: "X <- 4*(P[10:1]&0xf)"},
    37  		{filter: Stmt(St, 10), expected: "M[10] <- A"},
    38  		{filter: Stmt(Stx, 10), expected: "M[10] <- X"},
    39  		{filter: Stmt(Alu+Add+K, 10), expected: "A <- A + 10"},
    40  		{filter: Stmt(Alu+Sub+K, 10), expected: "A <- A - 10"},
    41  		{filter: Stmt(Alu+Mul+K, 10), expected: "A <- A * 10"},
    42  		{filter: Stmt(Alu+Div+K, 10), expected: "A <- A / 10"},
    43  		{filter: Stmt(Alu+Or+K, 10), expected: "A <- A | 10"},
    44  		{filter: Stmt(Alu+And+K, 10), expected: "A <- A & 10"},
    45  		{filter: Stmt(Alu+Lsh+K, 10), expected: "A <- A << 10"},
    46  		{filter: Stmt(Alu+Rsh+K, 10), expected: "A <- A >> 10"},
    47  		{filter: Stmt(Alu+Mod+K, 10), expected: "A <- A % 10"},
    48  		{filter: Stmt(Alu+Xor+K, 10), expected: "A <- A ^ 10"},
    49  		{filter: Stmt(Alu+Add+X, 0), expected: "A <- A + X"},
    50  		{filter: Stmt(Alu+Sub+X, 0), expected: "A <- A - X"},
    51  		{filter: Stmt(Alu+Mul+X, 0), expected: "A <- A * X"},
    52  		{filter: Stmt(Alu+Div+X, 0), expected: "A <- A / X"},
    53  		{filter: Stmt(Alu+Or+X, 0), expected: "A <- A | X"},
    54  		{filter: Stmt(Alu+And+X, 0), expected: "A <- A & X"},
    55  		{filter: Stmt(Alu+Lsh+X, 0), expected: "A <- A << X"},
    56  		{filter: Stmt(Alu+Rsh+X, 0), expected: "A <- A >> X"},
    57  		{filter: Stmt(Alu+Mod+X, 0), expected: "A <- A % X"},
    58  		{filter: Stmt(Alu+Xor+X, 0), expected: "A <- A ^ X"},
    59  		{filter: Stmt(Alu+Neg, 0), expected: "A <- -A"},
    60  		{filter: Stmt(Jmp+Ja, 10), expected: "pc += 10"},
    61  		{filter: Jump(Jmp+Jeq+K, 10, 2, 5), expected: "pc += (A == 10) ? 2 : 5"},
    62  		{filter: Jump(Jmp+Jgt+K, 10, 2, 5), expected: "pc += (A > 10) ? 2 : 5"},
    63  		{filter: Jump(Jmp+Jge+K, 10, 2, 5), expected: "pc += (A >= 10) ? 2 : 5"},
    64  		{filter: Jump(Jmp+Jset+K, 10, 2, 5), expected: "pc += (A & 10) ? 2 : 5"},
    65  		{filter: Jump(Jmp+Jeq+X, 0, 2, 5), expected: "pc += (A == X) ? 2 : 5"},
    66  		{filter: Jump(Jmp+Jgt+X, 0, 2, 5), expected: "pc += (A > X) ? 2 : 5"},
    67  		{filter: Jump(Jmp+Jge+X, 0, 2, 5), expected: "pc += (A >= X) ? 2 : 5"},
    68  		{filter: Jump(Jmp+Jset+X, 0, 2, 5), expected: "pc += (A & X) ? 2 : 5"},
    69  		{filter: Stmt(Ret+K, 10), expected: "ret 10"},
    70  		{filter: Stmt(Ret+A, 0), expected: "ret A"},
    71  		{filter: Stmt(Misc+Tax, 0), expected: "X <- A"},
    72  		{filter: Stmt(Misc+Txa, 0), expected: "A <- X"},
    73  		{filter: Stmt(Ld+Ind+Msh, 0), fail: true},
    74  	} {
    75  		got, err := Decode(test.filter)
    76  		if test.fail {
    77  			if err == nil {
    78  				t.Errorf("Decode(%v) failed, expected: 'error', got: %q", test.filter, got)
    79  				continue
    80  			}
    81  		} else {
    82  			if err != nil {
    83  				t.Errorf("Decode(%v) failed for test %q, error: %q", test.filter, test.expected, err)
    84  				continue
    85  			}
    86  			if got != test.expected {
    87  				t.Errorf("Decode(%v) failed, expected: %q, got: %q", test.filter, test.expected, got)
    88  				continue
    89  			}
    90  		}
    91  	}
    92  }
    93  
    94  func TestDecodeInstructions(t *testing.T) {
    95  	for _, test := range []struct {
    96  		name     string
    97  		program  []Instruction
    98  		expected string
    99  		fail     bool
   100  	}{
   101  		{name: "basic with jump indexes",
   102  			program: []Instruction{
   103  				Stmt(Ld+Abs+W, 10),
   104  				Stmt(Ldx+Mem, 10),
   105  				Stmt(St, 10),
   106  				Stmt(Stx, 10),
   107  				Stmt(Alu+Add+K, 10),
   108  				Stmt(Jmp+Ja, 10),
   109  				Jump(Jmp+Jeq+K, 10, 2, 5),
   110  				Jump(Jmp+Jset+X, 0, 0, 5),
   111  				Stmt(Misc+Tax, 0),
   112  			},
   113  			expected: "0: A <- P[10:4]\n" +
   114  				"1: X <- M[10]\n" +
   115  				"2: M[10] <- A\n" +
   116  				"3: M[10] <- X\n" +
   117  				"4: A <- A + 10\n" +
   118  				"5: pc += 10 [16]\n" +
   119  				"6: pc += (A == 10) ? 2 [9] : 5 [12]\n" +
   120  				"7: pc += (A & X) ? 0 [8] : 5 [13]\n" +
   121  				"8: X <- A\n",
   122  		},
   123  		{name: "invalid instruction",
   124  			program: []Instruction{Stmt(Ld+Abs+W, 10), Stmt(Ld+Len+Mem, 0)},
   125  			fail:    true},
   126  	} {
   127  		got, err := DecodeInstructions(test.program)
   128  		if test.fail {
   129  			if err == nil {
   130  				t.Errorf("%s: Decode(...) failed, expected: 'error', got: %q", test.name, got)
   131  				continue
   132  			}
   133  		} else {
   134  			if err != nil {
   135  				t.Errorf("%s: Decode failed: %v", test.name, err)
   136  				continue
   137  			}
   138  			if got != test.expected {
   139  				t.Errorf("%s: Decode(...) failed, expected: %q, got: %q", test.name, test.expected, got)
   140  				continue
   141  			}
   142  		}
   143  	}
   144  }