github.com/ks888/tgo@v0.0.0-20190130135156-80bf89407292/tracee/value_test.go (about)

     1  package tracee
     2  
     3  import (
     4  	"fmt"
     5  	"runtime"
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/ks888/tgo/testutils"
    10  )
    11  
    12  var typePrintAttr = Attributes{
    13  	FirstModuleDataAddr: testutils.TypePrintAddrFirstModuleData,
    14  	CompiledGoVersion:   runtime.Version(),
    15  }
    16  
    17  func TestParseValue(t *testing.T) {
    18  	proc, err := LaunchProcess(testutils.ProgramTypePrint, nil, typePrintAttr)
    19  	if err != nil {
    20  		t.Fatalf("failed to launch process: %v", err)
    21  	}
    22  	defer proc.Detach()
    23  
    24  	for i, testdata := range []struct {
    25  		funcAddr uint64
    26  		expected string
    27  	}{
    28  		// Note: the test order must be same as the order of functions called in typeprint.
    29  		{funcAddr: testutils.TypePrintAddrPrintBool, expected: "true"},
    30  		{funcAddr: testutils.TypePrintAddrPrintInt8, expected: "-1"},
    31  		{funcAddr: testutils.TypePrintAddrPrintInt16, expected: "-2"},
    32  		{funcAddr: testutils.TypePrintAddrPrintInt32, expected: "-3"},
    33  		{funcAddr: testutils.TypePrintAddrPrintInt64, expected: "-4"},
    34  		{funcAddr: testutils.TypePrintAddrPrintUint8, expected: fmt.Sprintf("%d", ^uint8(0))},
    35  		{funcAddr: testutils.TypePrintAddrPrintUint16, expected: fmt.Sprintf("%d", ^uint16(0))},
    36  		{funcAddr: testutils.TypePrintAddrPrintUint32, expected: fmt.Sprintf("%d", ^uint32(0))},
    37  		{funcAddr: testutils.TypePrintAddrPrintUint64, expected: fmt.Sprintf("%d", ^uint64(0))},
    38  		{funcAddr: testutils.TypePrintAddrPrintFloat32, expected: "0.12345679"},
    39  		{funcAddr: testutils.TypePrintAddrPrintFloat64, expected: "0.12345678901234568"},
    40  		{funcAddr: testutils.TypePrintAddrPrintComplex64, expected: "(1+2i)"},
    41  		{funcAddr: testutils.TypePrintAddrPrintComplex128, expected: "(3+4i)"},
    42  		{funcAddr: testutils.TypePrintAddrPrintString, expected: "\"hello\\n\""},
    43  		{funcAddr: testutils.TypePrintAddrPrintArray, expected: "[2]{1, 2}"},
    44  		{funcAddr: testutils.TypePrintAddrPrintSlice, expected: "[]{3, 4}"},
    45  		{funcAddr: testutils.TypePrintAddrPrintNilSlice, expected: "nil"},
    46  		{funcAddr: testutils.TypePrintAddrPrintPtr, expected: "&1"},
    47  	} {
    48  		if err := proc.SetBreakpoint(testdata.funcAddr); err != nil {
    49  			t.Fatalf("failed to set breakpoint: %v", err)
    50  		}
    51  		event, err := proc.ContinueAndWait()
    52  		if err != nil {
    53  			t.Fatalf("failed to continue and wait: %v", err)
    54  		}
    55  
    56  		tids := event.Data.([]int)
    57  		threadInfo, err := proc.CurrentThreadInfo(tids[0])
    58  		if err != nil {
    59  			t.Fatalf("failed to get CurrentThreadInfo: %v", err)
    60  		}
    61  
    62  		f, err := proc.Binary.FindFunction(testdata.funcAddr)
    63  		if err != nil {
    64  			t.Fatalf("failed to FindFunction: %v", err)
    65  		}
    66  
    67  		typ := f.Parameters[0].Typ
    68  		buff := make([]byte, typ.Size())
    69  		if err := proc.debugapiClient.ReadMemory(threadInfo.CurrentStackAddr+8, buff); err != nil {
    70  			t.Fatalf("failed to ReadMemory: %v", err)
    71  		}
    72  		val := (valueParser{reader: proc.debugapiClient}).parseValue(typ, buff, 0)
    73  		if val.String() != testdata.expected {
    74  			t.Errorf("[%d] wrong value: %s", i, val)
    75  		}
    76  
    77  		proc.SingleStep(tids[0], testdata.funcAddr)
    78  	}
    79  }
    80  
    81  func TestParseValue_NotFixedStringCase(t *testing.T) {
    82  	proc, err := LaunchProcess(testutils.ProgramTypePrint, nil, typePrintAttr)
    83  	if err != nil {
    84  		t.Fatalf("failed to launch process: %v", err)
    85  	}
    86  	defer proc.Detach()
    87  	go1_11 := GoVersion{MajorVersion: 1, MinorVersion: 11, PatchVersion: 0}
    88  
    89  	for _, testdata := range []struct {
    90  		funcAddr        uint64
    91  		testFunc        func(t *testing.T, val value)
    92  		testIfLaterThan GoVersion
    93  	}{
    94  		// Note: the test order must be same as the order of functions called in typeprint.
    95  		{funcAddr: testutils.TypePrintAddrPrintStruct, testFunc: func(t *testing.T, val value) {
    96  			fields := val.(structValue).fields
    97  			if fields["a"].(int64Value).val != 1 || fields["b"].(int64Value).val != 2 {
    98  				t.Errorf("wrong value: %s", fields)
    99  			}
   100  			innerFields := fields["T"].(structValue).fields
   101  			if len(innerFields) != 0 {
   102  				t.Errorf("The fields of 'T' should be empty because the depth is 1. actual: %d", len(innerFields))
   103  			}
   104  		}},
   105  		{funcAddr: testutils.TypePrintAddrPrintFunc, testFunc: func(t *testing.T, val value) {
   106  			if !strings.HasPrefix(val.String(), "0x") {
   107  				t.Errorf("wrong prefix: %s", val)
   108  			}
   109  		}},
   110  		{funcAddr: testutils.TypePrintAddrPrintInterface, testFunc: func(t *testing.T, val value) {
   111  			implVal, ok := val.(interfaceValue).implVal.(structValue)
   112  			if !ok || implVal.StructName != "main.S" {
   113  				t.Fatalf("wrong type: %#v", implVal)
   114  			}
   115  			if implVal.fields["a"].(int64Value).val != 5 {
   116  				t.Errorf("wrong value: %s", implVal.fields)
   117  			}
   118  		}, testIfLaterThan: go1_11},
   119  		{funcAddr: testutils.TypePrintAddrPrintPtrInterface, testFunc: func(t *testing.T, val value) {
   120  			implVal, ok := val.(interfaceValue).implVal.(ptrValue).pointedVal.(structValue)
   121  			if !ok {
   122  				t.Fatalf("wrong type: %#v", implVal)
   123  			}
   124  			if implVal.fields["a"].(int64Value).val != 9 {
   125  				t.Errorf("wrong value: %s", implVal.fields)
   126  			}
   127  		}, testIfLaterThan: go1_11},
   128  		{funcAddr: testutils.TypePrintAddrPrintNilInterface, testFunc: func(t *testing.T, val value) {
   129  			if val.String() != "nil" {
   130  				t.Errorf("wrong val: %s", val)
   131  			}
   132  		}},
   133  		{funcAddr: testutils.TypePrintAddrPrintEmptyInterface, testFunc: func(t *testing.T, val value) {
   134  			implVal, ok := val.(interfaceValue).implVal.(structValue)
   135  			if !ok || implVal.StructName != "main.S" {
   136  				t.Fatalf("wrong type: %v", implVal)
   137  			}
   138  			if implVal.fields["a"].(int64Value).val != 9 {
   139  				t.Errorf("wrong value: %s", implVal.fields)
   140  			}
   141  		}, testIfLaterThan: go1_11},
   142  		{funcAddr: testutils.TypePrintAddrPrintNilEmptyInterface, testFunc: func(t *testing.T, val value) {
   143  			if val.String() != "nil" {
   144  				t.Errorf("wrong val: %s", val)
   145  			}
   146  		}},
   147  		{funcAddr: testutils.TypePrintAddrPrintMap, testFunc: func(t *testing.T, val value) {
   148  			mapVal := val.(mapValue)
   149  			if len(mapVal.val) != 20 {
   150  				t.Errorf("wrong len: %d", len(mapVal.val))
   151  			}
   152  			for k, v := range mapVal.val {
   153  				if k.(int64Value).val != v.(int64Value).val {
   154  					t.Errorf("wrong kv: %d, %d", k.(int64Value).val, v.(int64Value).val)
   155  				}
   156  			}
   157  		}},
   158  		{funcAddr: testutils.TypePrintAddrPrintNilMap, testFunc: func(t *testing.T, val value) {
   159  			mapVal := val.(mapValue)
   160  			if mapVal.val != nil {
   161  				t.Errorf("map not nil: %v", mapVal)
   162  			}
   163  		}},
   164  	} {
   165  		if !proc.GoVersion.LaterThan(testdata.testIfLaterThan) {
   166  			continue
   167  		}
   168  
   169  		if err := proc.SetBreakpoint(testdata.funcAddr); err != nil {
   170  			t.Fatalf("failed to set breakpoint: %v", err)
   171  		}
   172  		event, err := proc.ContinueAndWait()
   173  		if err != nil {
   174  			t.Fatalf("failed to continue and wait: %v", err)
   175  		}
   176  
   177  		tids := event.Data.([]int)
   178  		threadInfo, err := proc.CurrentThreadInfo(tids[0])
   179  		if err != nil {
   180  			t.Fatalf("failed to get CurrentThreadInfo: %v", err)
   181  		}
   182  		f, err := proc.Binary.FindFunction(testdata.funcAddr)
   183  		if err != nil {
   184  			t.Fatalf("failed to findFunction: %v", err)
   185  		}
   186  
   187  		typ := f.Parameters[0].Typ
   188  		buff := make([]byte, typ.Size())
   189  		if err := proc.debugapiClient.ReadMemory(threadInfo.CurrentStackAddr+8, buff); err != nil {
   190  			t.Fatalf("failed to ReadMemory: %v", err)
   191  		}
   192  		val := proc.valueParser.parseValue(typ, buff, 1)
   193  		testdata.testFunc(t, val)
   194  
   195  		proc.SingleStep(tids[0], testdata.funcAddr)
   196  	}
   197  }