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 }