github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/lorry/engines/postgres/query_test.go (about)

     1  /*
     2  Copyright (C) 2022-2023 ApeCloud Co., Ltd
     3  
     4  This file is part of KubeBlocks project
     5  
     6  This program is free software: you can redistribute it and/or modify
     7  it under the terms of the GNU Affero General Public License as published by
     8  the Free Software Foundation, either version 3 of the License, or
     9  (at your option) any later version.
    10  
    11  This program is distributed in the hope that it will be useful
    12  but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  GNU Affero General Public License for more details.
    15  
    16  You should have received a copy of the GNU Affero General Public License
    17  along with this program.  If not, see <http://www.gnu.org/licenses/>.
    18  */
    19  
    20  package postgres
    21  
    22  import (
    23  	"context"
    24  	"fmt"
    25  	"testing"
    26  
    27  	"github.com/pashagolub/pgxmock/v2"
    28  	"github.com/stretchr/testify/assert"
    29  
    30  	"github.com/1aal/kubeblocks/pkg/lorry/dcs"
    31  )
    32  
    33  const (
    34  	execTest  = "create database test"
    35  	queryTest = "select 1"
    36  )
    37  
    38  func TestQuery(t *testing.T) {
    39  	ctx := context.TODO()
    40  	manager, mock, _ := MockDatabase(t)
    41  	defer mock.Close()
    42  
    43  	t.Run("query success", func(t *testing.T) {
    44  		sql := queryTest
    45  		mock.ExpectQuery("select").
    46  			WillReturnRows(pgxmock.NewRows([]string{"1"}))
    47  
    48  		_, err := manager.Query(ctx, sql)
    49  		assert.Nil(t, err)
    50  	})
    51  
    52  	t.Run("query failed", func(t *testing.T) {
    53  		sql := queryTest
    54  		mock.ExpectQuery("select").
    55  			WillReturnError(fmt.Errorf("some error"))
    56  
    57  		_, err := manager.Query(ctx, sql)
    58  		assert.NotNil(t, err)
    59  	})
    60  
    61  	t.Run("parse rows failed", func(t *testing.T) {
    62  		sql := queryTest
    63  		var val chan string
    64  		mock.ExpectQuery("select").
    65  			WillReturnRows(pgxmock.NewRows([]string{"1"}).AddRow(val))
    66  		_, err := manager.Query(ctx, sql)
    67  		assert.NotNil(t, err)
    68  	})
    69  
    70  	t.Run("can't connect db", func(t *testing.T) {
    71  		sql := queryTest
    72  		resp, err := manager.QueryWithHost(ctx, sql, "localhost")
    73  		assert.NotNil(t, err)
    74  		assert.Nil(t, resp)
    75  	})
    76  
    77  	t.Run("query leader success", func(t *testing.T) {
    78  		sql := queryTest
    79  		mock.ExpectQuery("select").
    80  			WillReturnRows(pgxmock.NewRows([]string{"1"}).AddRow("1"))
    81  		cluster := &dcs.Cluster{
    82  			Leader: &dcs.Leader{
    83  				Name: manager.CurrentMemberName,
    84  			},
    85  		}
    86  		cluster.Members = append(cluster.Members, dcs.Member{
    87  			Name: manager.CurrentMemberName,
    88  		})
    89  
    90  		resp, err := manager.QueryLeader(ctx, sql, cluster)
    91  		if err != nil {
    92  			t.Errorf("expect query leader success but failed")
    93  		}
    94  
    95  		assert.Equal(t, []byte(`[{"1":"1"}]`), resp)
    96  	})
    97  
    98  	t.Run("query leader failed, cluster has no leader", func(t *testing.T) {
    99  		sql := queryTest
   100  		cluster := &dcs.Cluster{}
   101  
   102  		_, err := manager.QueryLeader(ctx, sql, cluster)
   103  		if err == nil {
   104  			t.Errorf("expect query leader success but failed")
   105  		}
   106  
   107  		assert.ErrorIs(t, ClusterHasNoLeader, err)
   108  	})
   109  
   110  	if err := mock.ExpectationsWereMet(); err != nil {
   111  		t.Errorf("there were unfulfilled expectations: %v", err)
   112  	}
   113  }
   114  
   115  func TestParseQuery(t *testing.T) {
   116  	t.Run("parse query success", func(t *testing.T) {
   117  		data := []byte(`[{"current_setting":"off"}]`)
   118  		resMap, err := ParseQuery(string(data))
   119  		assert.NotNil(t, resMap)
   120  		assert.Nil(t, err)
   121  		assert.Equal(t, 1, len(resMap))
   122  		assert.Equal(t, "off", resMap[0]["current_setting"].(string))
   123  	})
   124  
   125  	t.Run("parse query failed", func(t *testing.T) {
   126  		data := []byte(`{"current_setting":"off"}`)
   127  		resMap, err := ParseQuery(string(data))
   128  		assert.NotNil(t, err)
   129  		assert.Nil(t, resMap)
   130  	})
   131  }
   132  
   133  func TestExec(t *testing.T) {
   134  	ctx := context.TODO()
   135  	manager, mock, _ := MockDatabase(t)
   136  	defer mock.Close()
   137  
   138  	t.Run("exec success", func(t *testing.T) {
   139  		sql := execTest
   140  
   141  		mock.ExpectExec("create database").
   142  			WillReturnResult(pgxmock.NewResult("CREATE DATABASE", 1))
   143  
   144  		_, err := manager.Exec(ctx, sql)
   145  		assert.Nil(t, err)
   146  	})
   147  
   148  	t.Run("exec failed", func(t *testing.T) {
   149  		sql := execTest
   150  
   151  		mock.ExpectExec("create database").
   152  			WillReturnError(fmt.Errorf("some error"))
   153  
   154  		_, err := manager.Exec(ctx, sql)
   155  		assert.NotNil(t, err)
   156  	})
   157  
   158  	t.Run("can't connect db", func(t *testing.T) {
   159  		sql := execTest
   160  		resp, err := manager.ExecWithHost(ctx, sql, "test")
   161  		if err == nil {
   162  			t.Errorf("expect query failed, but success")
   163  		}
   164  		assert.Equal(t, int64(0), resp)
   165  	})
   166  
   167  	t.Run("exec leader success", func(t *testing.T) {
   168  		sql := execTest
   169  		mock.ExpectExec("create").
   170  			WillReturnResult(pgxmock.NewResult("CREATE", 1))
   171  		cluster := &dcs.Cluster{
   172  			Leader: &dcs.Leader{
   173  				Name: manager.CurrentMemberName,
   174  			},
   175  		}
   176  		cluster.Members = append(cluster.Members, dcs.Member{
   177  			Name: manager.CurrentMemberName,
   178  		})
   179  
   180  		resp, err := manager.ExecLeader(ctx, sql, cluster)
   181  		if err != nil {
   182  			t.Errorf("expect exec leader success but failed")
   183  		}
   184  		assert.Equal(t, int64(1), resp)
   185  	})
   186  
   187  	t.Run("exec leader failed, cluster has no leader", func(t *testing.T) {
   188  		sql := execTest
   189  		cluster := &dcs.Cluster{}
   190  
   191  		_, err := manager.ExecLeader(ctx, sql, cluster)
   192  		if err == nil {
   193  			t.Errorf("expect exec leader success but failed")
   194  		}
   195  
   196  		assert.ErrorIs(t, ClusterHasNoLeader, err)
   197  	})
   198  
   199  	if err := mock.ExpectationsWereMet(); err != nil {
   200  		t.Errorf("there were unfulfilled expectations: %v", err)
   201  	}
   202  }
   203  
   204  func TestGetPgCurrentSetting(t *testing.T) {
   205  	ctx := context.TODO()
   206  	manager, mock, _ := MockDatabase(t)
   207  	defer mock.Close()
   208  
   209  	t.Run("query failed", func(t *testing.T) {
   210  		mock.ExpectQuery("select").
   211  			WillReturnError(fmt.Errorf("some error"))
   212  
   213  		res, err := manager.GetPgCurrentSetting(ctx, "test")
   214  		assert.NotNil(t, err)
   215  		assert.Equal(t, "", res)
   216  	})
   217  
   218  	t.Run("parse query failed", func(t *testing.T) {
   219  		mock.ExpectQuery("select").
   220  			WillReturnRows(pgxmock.NewRows([]string{"current_setting"}))
   221  
   222  		res, err := manager.GetPgCurrentSetting(ctx, "test")
   223  		assert.NotNil(t, err)
   224  		assert.Equal(t, "", res)
   225  	})
   226  
   227  	t.Run("query success", func(t *testing.T) {
   228  		mock.ExpectQuery("select").
   229  			WillReturnRows(pgxmock.NewRows([]string{"current_setting"}).AddRow("test"))
   230  
   231  		res, err := manager.GetPgCurrentSetting(ctx, "test")
   232  		assert.Nil(t, err)
   233  		assert.Equal(t, "test", res)
   234  	})
   235  
   236  	if err := mock.ExpectationsWereMet(); err != nil {
   237  		t.Errorf("there were unfulfilled expectations: %v", err)
   238  	}
   239  }