github.com/inspektor-gadget/inspektor-gadget@v0.28.1/pkg/testing/ig/ig.go (about)

     1  // Copyright 2019-2024 The Inspektor Gadget 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 ig provides executable wrapper for ig binary.
    16  //
    17  // Mainly used for testing of image-based gadgets.
    18  package ig
    19  
    20  import (
    21  	"fmt"
    22  	"os"
    23  	"os/exec"
    24  	"testing"
    25  
    26  	igtesting "github.com/inspektor-gadget/inspektor-gadget/pkg/testing"
    27  	"github.com/inspektor-gadget/inspektor-gadget/pkg/testing/command"
    28  )
    29  
    30  // runner is responsible for storing configuration of ig executable and provide methods to interact with.
    31  type runner struct {
    32  	path  string
    33  	image string
    34  
    35  	// command.Command contains *exec.Cmd and additional properties and methods for the same.
    36  	command.Command
    37  	flags []string
    38  }
    39  
    40  func (ig *runner) createCmd() {
    41  	ig.flags = append(ig.flags, "-o=json")
    42  	args := append([]string{"run", ig.image}, ig.flags...)
    43  
    44  	ig.Cmd = exec.Command(ig.path, args...)
    45  }
    46  
    47  type option func(*runner)
    48  
    49  // WithPath used for providing custom path to ig executable.
    50  func WithPath(path string) option {
    51  	return func(ig *runner) {
    52  		ig.path = path
    53  	}
    54  }
    55  
    56  // WithFlags args should be in form: "--flag_name=value" or "-shorthand=value".
    57  func WithFlags(flags ...string) option {
    58  	return func(ig *runner) {
    59  		ig.flags = flags
    60  	}
    61  }
    62  
    63  // WithStartAndStop used to set StartAndStop value to true.
    64  func WithStartAndStop() option {
    65  	return func(ig *runner) {
    66  		ig.StartAndStop = true
    67  	}
    68  }
    69  
    70  // WithValidateOutput used to compare the actual output with expected output.
    71  func WithValidateOutput(validateOutput func(t *testing.T, output string)) option {
    72  	return func(ig *runner) {
    73  		ig.ValidateOutput = validateOutput
    74  	}
    75  }
    76  
    77  // New creates a new IG configured with the options passed as parameters.
    78  func New(image string, opts ...option) igtesting.TestStep {
    79  	commandName := fmt.Sprintf("Run_%s", image)
    80  	repository := os.Getenv("GADGET_REPOSITORY")
    81  	tag := os.Getenv("GADGET_TAG")
    82  	if repository != "" {
    83  		image = fmt.Sprintf("%s/%s", repository, image)
    84  	}
    85  	if tag != "" {
    86  		image = fmt.Sprintf("%s:%s", image, tag)
    87  	}
    88  
    89  	ig := &runner{
    90  		path:  "ig",
    91  		image: image,
    92  		Command: command.Command{
    93  			Name: commandName,
    94  		},
    95  	}
    96  
    97  	if path, ok := os.LookupEnv("IG"); ok {
    98  		ig.path = path
    99  	}
   100  
   101  	for _, opt := range opts {
   102  		opt(ig)
   103  	}
   104  
   105  	ig.createCmd()
   106  
   107  	return ig
   108  }