...

Source file src/github.com/jackc/pgx/v5/internal/sanitize/sanitize_test.go

Documentation: github.com/jackc/pgx/v5/internal/sanitize

     1  package sanitize_test
     2  
     3  import (
     4  	"testing"
     5  	"time"
     6  
     7  	"github.com/jackc/pgx/v5/internal/sanitize"
     8  )
     9  
    10  func TestNewQuery(t *testing.T) {
    11  	successTests := []struct {
    12  		sql      string
    13  		expected sanitize.Query
    14  	}{
    15  		{
    16  			sql:      "select 42",
    17  			expected: sanitize.Query{Parts: []sanitize.Part{"select 42"}},
    18  		},
    19  		{
    20  			sql:      "select $1",
    21  			expected: sanitize.Query{Parts: []sanitize.Part{"select ", 1}},
    22  		},
    23  		{
    24  			sql:      "select 'quoted $42', $1",
    25  			expected: sanitize.Query{Parts: []sanitize.Part{"select 'quoted $42', ", 1}},
    26  		},
    27  		{
    28  			sql:      `select "doubled quoted $42", $1`,
    29  			expected: sanitize.Query{Parts: []sanitize.Part{`select "doubled quoted $42", `, 1}},
    30  		},
    31  		{
    32  			sql:      "select 'foo''bar', $1",
    33  			expected: sanitize.Query{Parts: []sanitize.Part{"select 'foo''bar', ", 1}},
    34  		},
    35  		{
    36  			sql:      `select "foo""bar", $1`,
    37  			expected: sanitize.Query{Parts: []sanitize.Part{`select "foo""bar", `, 1}},
    38  		},
    39  		{
    40  			sql:      "select '''', $1",
    41  			expected: sanitize.Query{Parts: []sanitize.Part{"select '''', ", 1}},
    42  		},
    43  		{
    44  			sql:      `select """", $1`,
    45  			expected: sanitize.Query{Parts: []sanitize.Part{`select """", `, 1}},
    46  		},
    47  		{
    48  			sql:      "select $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11",
    49  			expected: sanitize.Query{Parts: []sanitize.Part{"select ", 1, ", ", 2, ", ", 3, ", ", 4, ", ", 5, ", ", 6, ", ", 7, ", ", 8, ", ", 9, ", ", 10, ", ", 11}},
    50  		},
    51  		{
    52  			sql:      `select "adsf""$1""adsf", $1, 'foo''$$12bar', $2, '$3'`,
    53  			expected: sanitize.Query{Parts: []sanitize.Part{`select "adsf""$1""adsf", `, 1, `, 'foo''$$12bar', `, 2, `, '$3'`}},
    54  		},
    55  		{
    56  			sql:      `select E'escape string\' $42', $1`,
    57  			expected: sanitize.Query{Parts: []sanitize.Part{`select E'escape string\' $42', `, 1}},
    58  		},
    59  		{
    60  			sql:      `select e'escape string\' $42', $1`,
    61  			expected: sanitize.Query{Parts: []sanitize.Part{`select e'escape string\' $42', `, 1}},
    62  		},
    63  		{
    64  			sql:      `select /* a baby's toy */ 'barbie', $1`,
    65  			expected: sanitize.Query{Parts: []sanitize.Part{`select /* a baby's toy */ 'barbie', `, 1}},
    66  		},
    67  		{
    68  			sql:      `select /* *_* */ $1`,
    69  			expected: sanitize.Query{Parts: []sanitize.Part{`select /* *_* */ `, 1}},
    70  		},
    71  		{
    72  			sql:      `select 42 /* /* /* 42 */ */ */, $1`,
    73  			expected: sanitize.Query{Parts: []sanitize.Part{`select 42 /* /* /* 42 */ */ */, `, 1}},
    74  		},
    75  		{
    76  			sql:      "select -- a baby's toy\n'barbie', $1",
    77  			expected: sanitize.Query{Parts: []sanitize.Part{"select -- a baby's toy\n'barbie', ", 1}},
    78  		},
    79  		{
    80  			sql:      "select 42 -- is a Deep Thought's favorite number",
    81  			expected: sanitize.Query{Parts: []sanitize.Part{"select 42 -- is a Deep Thought's favorite number"}},
    82  		},
    83  		{
    84  			sql:      "select 42, -- \\nis a Deep Thought's favorite number\n$1",
    85  			expected: sanitize.Query{Parts: []sanitize.Part{"select 42, -- \\nis a Deep Thought's favorite number\n", 1}},
    86  		},
    87  		{
    88  			sql:      "select 42, -- \\nis a Deep Thought's favorite number\r$1",
    89  			expected: sanitize.Query{Parts: []sanitize.Part{"select 42, -- \\nis a Deep Thought's favorite number\r", 1}},
    90  		},
    91  		{
    92  			// https://github.com/jackc/pgx/issues/1380
    93  			sql:      "select 'hello w�rld'",
    94  			expected: sanitize.Query{Parts: []sanitize.Part{"select 'hello w�rld'"}},
    95  		},
    96  		{
    97  			// Unterminated quoted string
    98  			sql:      "select 'hello world",
    99  			expected: sanitize.Query{Parts: []sanitize.Part{"select 'hello world"}},
   100  		},
   101  	}
   102  
   103  	for i, tt := range successTests {
   104  		query, err := sanitize.NewQuery(tt.sql)
   105  		if err != nil {
   106  			t.Errorf("%d. %v", i, err)
   107  		}
   108  
   109  		if len(query.Parts) == len(tt.expected.Parts) {
   110  			for j := range query.Parts {
   111  				if query.Parts[j] != tt.expected.Parts[j] {
   112  					t.Errorf("%d. expected part %d to be %v but it was %v", i, j, tt.expected.Parts[j], query.Parts[j])
   113  				}
   114  			}
   115  		} else {
   116  			t.Errorf("%d. expected query parts to be %v but it was %v", i, tt.expected.Parts, query.Parts)
   117  		}
   118  	}
   119  }
   120  
   121  func TestQuerySanitize(t *testing.T) {
   122  	successfulTests := []struct {
   123  		query    sanitize.Query
   124  		args     []any
   125  		expected string
   126  	}{
   127  		{
   128  			query:    sanitize.Query{Parts: []sanitize.Part{"select 42"}},
   129  			args:     []any{},
   130  			expected: `select 42`,
   131  		},
   132  		{
   133  			query:    sanitize.Query{Parts: []sanitize.Part{"select ", 1}},
   134  			args:     []any{int64(42)},
   135  			expected: `select  42 `,
   136  		},
   137  		{
   138  			query:    sanitize.Query{Parts: []sanitize.Part{"select ", 1}},
   139  			args:     []any{float64(1.23)},
   140  			expected: `select  1.23 `,
   141  		},
   142  		{
   143  			query:    sanitize.Query{Parts: []sanitize.Part{"select ", 1}},
   144  			args:     []any{true},
   145  			expected: `select  true `,
   146  		},
   147  		{
   148  			query:    sanitize.Query{Parts: []sanitize.Part{"select ", 1}},
   149  			args:     []any{[]byte{0, 1, 2, 3, 255}},
   150  			expected: `select  '\x00010203ff' `,
   151  		},
   152  		{
   153  			query:    sanitize.Query{Parts: []sanitize.Part{"select ", 1}},
   154  			args:     []any{nil},
   155  			expected: `select  null `,
   156  		},
   157  		{
   158  			query:    sanitize.Query{Parts: []sanitize.Part{"select ", 1}},
   159  			args:     []any{"foobar"},
   160  			expected: `select  'foobar' `,
   161  		},
   162  		{
   163  			query:    sanitize.Query{Parts: []sanitize.Part{"select ", 1}},
   164  			args:     []any{"foo'bar"},
   165  			expected: `select  'foo''bar' `,
   166  		},
   167  		{
   168  			query:    sanitize.Query{Parts: []sanitize.Part{"select ", 1}},
   169  			args:     []any{`foo\'bar`},
   170  			expected: `select  'foo\''bar' `,
   171  		},
   172  		{
   173  			query:    sanitize.Query{Parts: []sanitize.Part{"insert ", 1}},
   174  			args:     []any{time.Date(2020, time.March, 1, 23, 59, 59, 999999999, time.UTC)},
   175  			expected: `insert  '2020-03-01 23:59:59.999999Z' `,
   176  		},
   177  		{
   178  			query:    sanitize.Query{Parts: []sanitize.Part{"select 1-", 1}},
   179  			args:     []any{int64(-1)},
   180  			expected: `select 1- -1 `,
   181  		},
   182  		{
   183  			query:    sanitize.Query{Parts: []sanitize.Part{"select 1-", 1}},
   184  			args:     []any{float64(-1)},
   185  			expected: `select 1- -1 `,
   186  		},
   187  	}
   188  
   189  	for i, tt := range successfulTests {
   190  		actual, err := tt.query.Sanitize(tt.args...)
   191  		if err != nil {
   192  			t.Errorf("%d. %v", i, err)
   193  			continue
   194  		}
   195  
   196  		if tt.expected != actual {
   197  			t.Errorf("%d. expected %s, but got %s", i, tt.expected, actual)
   198  		}
   199  	}
   200  
   201  	errorTests := []struct {
   202  		query    sanitize.Query
   203  		args     []any
   204  		expected string
   205  	}{
   206  		{
   207  			query:    sanitize.Query{Parts: []sanitize.Part{"select ", 1, ", ", 2}},
   208  			args:     []any{int64(42)},
   209  			expected: `insufficient arguments`,
   210  		},
   211  		{
   212  			query:    sanitize.Query{Parts: []sanitize.Part{"select 'foo'"}},
   213  			args:     []any{int64(42)},
   214  			expected: `unused argument: 0`,
   215  		},
   216  		{
   217  			query:    sanitize.Query{Parts: []sanitize.Part{"select ", 1}},
   218  			args:     []any{42},
   219  			expected: `invalid arg type: int`,
   220  		},
   221  	}
   222  
   223  	for i, tt := range errorTests {
   224  		_, err := tt.query.Sanitize(tt.args...)
   225  		if err == nil || err.Error() != tt.expected {
   226  			t.Errorf("%d. expected error %v, got %v", i, tt.expected, err)
   227  		}
   228  	}
   229  }
   230  

View as plain text