...

Source file src/github.com/chaos-mesh/chaos-mesh/pkg/ptrace/ptrace_linux_test.go

Documentation: github.com/chaos-mesh/chaos-mesh/pkg/ptrace

     1  // Copyright 2021 Chaos Mesh 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  //go:build cgo
    16  
    17  package ptrace
    18  
    19  import (
    20  	"encoding/binary"
    21  	"math/rand"
    22  	"os"
    23  	"os/exec"
    24  	"testing"
    25  	"time"
    26  	"unsafe"
    27  
    28  	. "github.com/onsi/ginkgo/v2"
    29  	. "github.com/onsi/gomega"
    30  
    31  	"github.com/chaos-mesh/chaos-mesh/pkg/log"
    32  	"github.com/chaos-mesh/chaos-mesh/test/pkg/timer"
    33  )
    34  
    35  func TestPTrace(t *testing.T) {
    36  	RegisterFailHandler(Fail)
    37  
    38  	RunSpecs(t, "PTrace Suit")
    39  }
    40  
    41  var _ = BeforeSuite(func(done Done) {
    42  	rand.Seed(GinkgoRandomSeed())
    43  
    44  	By("change working directory")
    45  
    46  	err := os.Chdir("../../")
    47  	Expect(err).NotTo(HaveOccurred())
    48  
    49  	By("register logger")
    50  
    51  	close(done)
    52  })
    53  
    54  // These tests are written in BDD-style using Ginkgo framework. Refer to
    55  // http://onsi.github.io/ginkgo to learn more.
    56  
    57  var _ = Describe("PTrace", func() {
    58  
    59  	logger, err := log.NewDefaultZapLogger()
    60  	Expect(err).NotTo(HaveOccurred())
    61  
    62  	var t *timer.Timer
    63  	var program *TracedProgram
    64  
    65  	BeforeEach(func() {
    66  		var err error
    67  
    68  		t, err = timer.StartTimer()
    69  		Expect(err).ShouldNot(HaveOccurred(), "error: %+v", err)
    70  
    71  		time.Sleep(time.Millisecond)
    72  
    73  		program, err = Trace(t.Pid(), logger)
    74  		Expect(err).ShouldNot(HaveOccurred(), "error: %+v", err)
    75  	})
    76  
    77  	AfterEach(func() {
    78  		err := program.Detach()
    79  		Expect(err).ShouldNot(HaveOccurred(), "error: %+v", err)
    80  
    81  		err = t.Stop()
    82  		Expect(err).ShouldNot(HaveOccurred(), "error: %+v", err)
    83  	})
    84  
    85  	It("should mmap slice successfully", func() {
    86  		Expect(program.Pid()).Should(Equal(t.Pid()))
    87  
    88  		helloWorld := []byte("Hello World")
    89  		entry, err := program.MmapSlice(helloWorld)
    90  		Expect(err).ShouldNot(HaveOccurred(), "error: %+v", err)
    91  
    92  		readBuf, err := program.ReadSlice(entry.StartAddress, uint64(len(helloWorld)))
    93  		Expect(err).ShouldNot(HaveOccurred(), "error: %+v", err)
    94  
    95  		Expect(*readBuf).Should(Equal(helloWorld))
    96  	})
    97  
    98  	It("double trace should get error", func() {
    99  		_, err := Trace(t.Pid(), logger)
   100  		Expect(err).Should(HaveOccurred())
   101  	})
   102  
   103  	It("should ptrace write slice successfully", func() {
   104  		helloWorld := []byte("Hello World")
   105  		addr, err := program.Mmap(uint64(len(helloWorld)), 0)
   106  		Expect(err).ShouldNot(HaveOccurred(), "error: %+v", err)
   107  
   108  		err = program.PtraceWriteSlice(addr, helloWorld)
   109  		Expect(err).ShouldNot(HaveOccurred(), "error: %+v, addr: %d", err, addr)
   110  
   111  		readBuf, err := program.ReadSlice(addr, uint64(len(helloWorld)))
   112  		Expect(err).ShouldNot(HaveOccurred(), "error: %+v, addr: %d", err, addr)
   113  
   114  		Expect(*readBuf).Should(Equal(helloWorld))
   115  	})
   116  
   117  	It("should write uint64 successfully", func() {
   118  		number := rand.Uint64()
   119  		size := uint64(unsafe.Sizeof(number))
   120  		expectBuf := make([]byte, size)
   121  		binary.LittleEndian.PutUint64(expectBuf, number)
   122  
   123  		addr, err := program.Mmap(size, 0)
   124  		Expect(err).ShouldNot(HaveOccurred(), "error: %+v", err)
   125  
   126  		err = program.WriteUint64ToAddr(addr, number)
   127  		Expect(err).ShouldNot(HaveOccurred(), "error: %+v, addr: %d", err, addr)
   128  
   129  		readBuf, err := program.ReadSlice(addr, size)
   130  		Expect(err).ShouldNot(HaveOccurred(), "error: %+v, addr: %d", err, addr)
   131  
   132  		Expect(*readBuf).Should(Equal(expectBuf))
   133  	})
   134  
   135  	It("should be able to detach and reattach", func() {
   136  		err := program.Detach()
   137  		Expect(err).ShouldNot(HaveOccurred(), "error: %+v", err)
   138  
   139  		program, err = Trace(t.Pid(), logger)
   140  		Expect(err).ShouldNot(HaveOccurred(), "error: %+v", err)
   141  	})
   142  
   143  	It("should be able to attach and detach multithread program", func() {
   144  		p := exec.Command("./bin/test/multithread_tracee")
   145  		err := p.Start()
   146  		Expect(err).ShouldNot(HaveOccurred(), "error: %+v", err)
   147  
   148  		time.Sleep(time.Millisecond)
   149  
   150  		pid := p.Process.Pid
   151  		program, err := Trace(pid, logger)
   152  		Expect(err).ShouldNot(HaveOccurred(), "error: %+v", err)
   153  
   154  		err = program.Detach()
   155  		Expect(err).ShouldNot(HaveOccurred(), "error: %+v", err)
   156  
   157  		err = p.Process.Kill()
   158  		Expect(err).ShouldNot(HaveOccurred(), "error: %+v", err)
   159  	})
   160  })
   161