db_client_test.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. // Copyright The OpenTelemetry Authors
  2. // SPDX-License-Identifier: Apache-2.0
  3. package sqlqueryreceiver
  4. import (
  5. "context"
  6. "errors"
  7. "fmt"
  8. "testing"
  9. "github.com/stretchr/testify/assert"
  10. "github.com/stretchr/testify/require"
  11. "go.uber.org/multierr"
  12. "go.uber.org/zap"
  13. )
  14. func TestDBSQLClient_SingleRow(t *testing.T) {
  15. cl := dbSQLClient{
  16. db: fakeDB{rowVals: [][]any{{42, 123.4, "hello", true, []uint8{52, 46, 49}}}},
  17. logger: zap.NewNop(),
  18. sql: "",
  19. }
  20. rows, err := cl.queryRows(context.Background())
  21. require.NoError(t, err)
  22. assert.Len(t, rows, 1)
  23. assert.EqualValues(t, map[string]string{
  24. "col_0": "42",
  25. "col_1": "123.4",
  26. "col_2": "hello",
  27. "col_3": "true",
  28. "col_4": "4.1",
  29. }, rows[0])
  30. }
  31. func TestDBSQLClient_MultiRow(t *testing.T) {
  32. cl := dbSQLClient{
  33. db: fakeDB{rowVals: [][]any{
  34. {42, 123.4, "hello", true, []uint8{52, 46, 49}},
  35. {43, 123.5, "goodbye", false, []uint8{52, 46, 50}},
  36. }},
  37. logger: zap.NewNop(),
  38. sql: "",
  39. }
  40. rows, err := cl.queryRows(context.Background())
  41. require.NoError(t, err)
  42. assert.Len(t, rows, 2)
  43. assert.EqualValues(t, map[string]string{
  44. "col_0": "42",
  45. "col_1": "123.4",
  46. "col_2": "hello",
  47. "col_3": "true",
  48. "col_4": "4.1",
  49. }, rows[0])
  50. assert.EqualValues(t, map[string]string{
  51. "col_0": "43",
  52. "col_1": "123.5",
  53. "col_2": "goodbye",
  54. "col_3": "false",
  55. "col_4": "4.2",
  56. }, rows[1])
  57. }
  58. func TestDBSQLClient_Nulls(t *testing.T) {
  59. cl := dbSQLClient{
  60. db: fakeDB{rowVals: [][]any{
  61. {42, nil, 111}, // NULLs from the DB map to nil here
  62. }},
  63. logger: zap.NewNop(),
  64. sql: "",
  65. }
  66. rows, err := cl.queryRows(context.Background())
  67. assert.Error(t, err)
  68. assert.True(t, errors.Is(err, errNullValueWarning))
  69. assert.Len(t, rows, 1)
  70. assert.EqualValues(t, map[string]string{
  71. "col_0": "42",
  72. "col_2": "111",
  73. }, rows[0])
  74. }
  75. func TestDBSQLClient_Nulls_MultiRow(t *testing.T) {
  76. cl := dbSQLClient{
  77. db: fakeDB{rowVals: [][]any{
  78. {42, nil},
  79. {43, nil},
  80. }},
  81. logger: zap.NewNop(),
  82. sql: "",
  83. }
  84. rows, err := cl.queryRows(context.Background())
  85. assert.Error(t, err)
  86. errs := multierr.Errors(err)
  87. for _, err := range errs {
  88. assert.True(t, errors.Is(err, errNullValueWarning))
  89. }
  90. assert.Len(t, errs, 2)
  91. assert.Len(t, rows, 2)
  92. assert.EqualValues(t, map[string]string{
  93. "col_0": "42",
  94. }, rows[0])
  95. assert.EqualValues(t, map[string]string{
  96. "col_0": "43",
  97. }, rows[1])
  98. }
  99. type fakeDB struct {
  100. rowVals [][]any
  101. }
  102. func (db fakeDB) QueryContext(context.Context, string, ...any) (rows, error) {
  103. return &fakeRows{vals: db.rowVals}, nil
  104. }
  105. type fakeRows struct {
  106. vals [][]any
  107. row int
  108. }
  109. func (r *fakeRows) ColumnTypes() ([]colType, error) {
  110. var out []colType
  111. for i := 0; i < len(r.vals[0]); i++ {
  112. out = append(out, fakeCol{fmt.Sprintf("col_%d", i)})
  113. }
  114. return out, nil
  115. }
  116. func (r *fakeRows) Next() bool {
  117. return r.row < len(r.vals)
  118. }
  119. func (r *fakeRows) Scan(dest ...any) error {
  120. for i := range dest {
  121. ptr := dest[i].(*any)
  122. *ptr = r.vals[r.row][i]
  123. }
  124. r.row++
  125. return nil
  126. }
  127. type fakeCol struct {
  128. name string
  129. }
  130. func (c fakeCol) Name() string {
  131. return c.name
  132. }
  133. type fakeDBClient struct {
  134. requestCounter int
  135. stringMaps [][]stringMap
  136. err error
  137. }
  138. func (c *fakeDBClient) queryRows(context.Context, ...any) ([]stringMap, error) {
  139. if c.err != nil {
  140. return nil, c.err
  141. }
  142. idx := c.requestCounter
  143. c.requestCounter++
  144. return c.stringMaps[idx], nil
  145. }