...

Source file src/helm.sh/helm/v3/pkg/storage/driver/sql_test.go

Documentation: helm.sh/helm/v3/pkg/storage/driver

     1  /*
     2  Copyright The Helm Authors.
     3  Licensed under the Apache License, Version 2.0 (the "License");
     4  you may not use this file except in compliance with the License.
     5  You may obtain a copy of the License at
     6      http://www.apache.org/licenses/LICENSE-2.0
     7  Unless required by applicable law or agreed to in writing, software
     8  distributed under the License is distributed on an "AS IS" BASIS,
     9  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    10  See the License for the specific language governing permissions and
    11  limitations under the License.
    12  */
    13  
    14  package driver
    15  
    16  import (
    17  	"fmt"
    18  	"reflect"
    19  	"regexp"
    20  	"testing"
    21  	"time"
    22  
    23  	sqlmock "github.com/DATA-DOG/go-sqlmock"
    24  	migrate "github.com/rubenv/sql-migrate"
    25  
    26  	rspb "helm.sh/helm/v3/pkg/release"
    27  )
    28  
    29  func TestSQLName(t *testing.T) {
    30  	sqlDriver, _ := newTestFixtureSQL(t)
    31  	if sqlDriver.Name() != SQLDriverName {
    32  		t.Errorf("Expected name to be %s, got %s", SQLDriverName, sqlDriver.Name())
    33  	}
    34  }
    35  
    36  func TestSQLGet(t *testing.T) {
    37  	vers := int(1)
    38  	name := "smug-pigeon"
    39  	namespace := "default"
    40  	key := testKey(name, vers)
    41  	rel := releaseStub(name, vers, namespace, rspb.StatusDeployed)
    42  
    43  	body, _ := encodeRelease(rel)
    44  
    45  	sqlDriver, mock := newTestFixtureSQL(t)
    46  
    47  	query := fmt.Sprintf(
    48  		regexp.QuoteMeta("SELECT %s FROM %s WHERE %s = $1 AND %s = $2"),
    49  		sqlReleaseTableBodyColumn,
    50  		sqlReleaseTableName,
    51  		sqlReleaseTableKeyColumn,
    52  		sqlReleaseTableNamespaceColumn,
    53  	)
    54  
    55  	mock.
    56  		ExpectQuery(query).
    57  		WithArgs(key, namespace).
    58  		WillReturnRows(
    59  			mock.NewRows([]string{
    60  				sqlReleaseTableBodyColumn,
    61  			}).AddRow(
    62  				body,
    63  			),
    64  		).RowsWillBeClosed()
    65  
    66  	mockGetReleaseCustomLabels(mock, key, namespace, rel.Labels)
    67  
    68  	got, err := sqlDriver.Get(key)
    69  	if err != nil {
    70  		t.Fatalf("Failed to get release: %v", err)
    71  	}
    72  
    73  	if !reflect.DeepEqual(rel, got) {
    74  		t.Errorf("Expected release {%v}, got {%v}", rel, got)
    75  	}
    76  
    77  	if err := mock.ExpectationsWereMet(); err != nil {
    78  		t.Errorf("sql expectations weren't met: %v", err)
    79  	}
    80  }
    81  
    82  func TestSQLList(t *testing.T) {
    83  	releases := []*rspb.Release{}
    84  	releases = append(releases, releaseStub("key-1", 1, "default", rspb.StatusUninstalled))
    85  	releases = append(releases, releaseStub("key-2", 1, "default", rspb.StatusUninstalled))
    86  	releases = append(releases, releaseStub("key-3", 1, "default", rspb.StatusDeployed))
    87  	releases = append(releases, releaseStub("key-4", 1, "default", rspb.StatusDeployed))
    88  	releases = append(releases, releaseStub("key-5", 1, "default", rspb.StatusSuperseded))
    89  	releases = append(releases, releaseStub("key-6", 1, "default", rspb.StatusSuperseded))
    90  
    91  	sqlDriver, mock := newTestFixtureSQL(t)
    92  
    93  	for i := 0; i < 3; i++ {
    94  		query := fmt.Sprintf(
    95  			"SELECT %s, %s, %s FROM %s WHERE %s = $1 AND %s = $2",
    96  			sqlReleaseTableKeyColumn,
    97  			sqlReleaseTableNamespaceColumn,
    98  			sqlReleaseTableBodyColumn,
    99  			sqlReleaseTableName,
   100  			sqlReleaseTableOwnerColumn,
   101  			sqlReleaseTableNamespaceColumn,
   102  		)
   103  
   104  		rows := mock.NewRows([]string{
   105  			sqlReleaseTableBodyColumn,
   106  		})
   107  		for _, r := range releases {
   108  			body, _ := encodeRelease(r)
   109  			rows.AddRow(body)
   110  		}
   111  		mock.
   112  			ExpectQuery(regexp.QuoteMeta(query)).
   113  			WithArgs(sqlReleaseDefaultOwner, sqlDriver.namespace).
   114  			WillReturnRows(rows).RowsWillBeClosed()
   115  
   116  		for _, r := range releases {
   117  			mockGetReleaseCustomLabels(mock, "", r.Namespace, r.Labels)
   118  		}
   119  	}
   120  
   121  	// list all deleted releases
   122  	del, err := sqlDriver.List(func(rel *rspb.Release) bool {
   123  		return rel.Info.Status == rspb.StatusUninstalled
   124  	})
   125  	// check
   126  	if err != nil {
   127  		t.Errorf("Failed to list deleted: %v", err)
   128  	}
   129  	if len(del) != 2 {
   130  		t.Errorf("Expected 2 deleted, got %d:\n%v\n", len(del), del)
   131  	}
   132  
   133  	// list all deployed releases
   134  	dpl, err := sqlDriver.List(func(rel *rspb.Release) bool {
   135  		return rel.Info.Status == rspb.StatusDeployed
   136  	})
   137  	// check
   138  	if err != nil {
   139  		t.Errorf("Failed to list deployed: %v", err)
   140  	}
   141  	if len(dpl) != 2 {
   142  		t.Errorf("Expected 2 deployed, got %d:\n%v\n", len(dpl), dpl)
   143  	}
   144  
   145  	// list all superseded releases
   146  	ssd, err := sqlDriver.List(func(rel *rspb.Release) bool {
   147  		return rel.Info.Status == rspb.StatusSuperseded
   148  	})
   149  	// check
   150  	if err != nil {
   151  		t.Errorf("Failed to list superseded: %v", err)
   152  	}
   153  	if len(ssd) != 2 {
   154  		t.Errorf("Expected 2 superseded, got %d:\n%v\n", len(ssd), ssd)
   155  	}
   156  
   157  	if err := mock.ExpectationsWereMet(); err != nil {
   158  		t.Errorf("sql expectations weren't met: %v", err)
   159  	}
   160  
   161  	// Check if release having both system and custom labels, this is needed to ensure that selector filtering would work.
   162  	rls := ssd[0]
   163  	_, ok := rls.Labels["name"]
   164  	if !ok {
   165  		t.Fatalf("Expected 'name' label in results, actual %v", rls.Labels)
   166  	}
   167  	_, ok = rls.Labels["key1"]
   168  	if !ok {
   169  		t.Fatalf("Expected 'key1' label in results, actual %v", rls.Labels)
   170  	}
   171  }
   172  
   173  func TestSqlCreate(t *testing.T) {
   174  	vers := 1
   175  	name := "smug-pigeon"
   176  	namespace := "default"
   177  	key := testKey(name, vers)
   178  	rel := releaseStub(name, vers, namespace, rspb.StatusDeployed)
   179  
   180  	sqlDriver, mock := newTestFixtureSQL(t)
   181  	body, _ := encodeRelease(rel)
   182  
   183  	query := fmt.Sprintf(
   184  		"INSERT INTO %s (%s,%s,%s,%s,%s,%s,%s,%s,%s) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9)",
   185  		sqlReleaseTableName,
   186  		sqlReleaseTableKeyColumn,
   187  		sqlReleaseTableTypeColumn,
   188  		sqlReleaseTableBodyColumn,
   189  		sqlReleaseTableNameColumn,
   190  		sqlReleaseTableNamespaceColumn,
   191  		sqlReleaseTableVersionColumn,
   192  		sqlReleaseTableStatusColumn,
   193  		sqlReleaseTableOwnerColumn,
   194  		sqlReleaseTableCreatedAtColumn,
   195  	)
   196  
   197  	mock.ExpectBegin()
   198  	mock.
   199  		ExpectExec(regexp.QuoteMeta(query)).
   200  		WithArgs(key, sqlReleaseDefaultType, body, rel.Name, rel.Namespace, int(rel.Version), rel.Info.Status.String(), sqlReleaseDefaultOwner, int(time.Now().Unix())).
   201  		WillReturnResult(sqlmock.NewResult(1, 1))
   202  
   203  	labelsQuery := fmt.Sprintf(
   204  		"INSERT INTO %s (%s,%s,%s,%s) VALUES ($1,$2,$3,$4)",
   205  		sqlCustomLabelsTableName,
   206  		sqlCustomLabelsTableReleaseKeyColumn,
   207  		sqlCustomLabelsTableReleaseNamespaceColumn,
   208  		sqlCustomLabelsTableKeyColumn,
   209  		sqlCustomLabelsTableValueColumn,
   210  	)
   211  
   212  	mock.MatchExpectationsInOrder(false)
   213  	for k, v := range filterSystemLabels(rel.Labels) {
   214  		mock.
   215  			ExpectExec(regexp.QuoteMeta(labelsQuery)).
   216  			WithArgs(key, rel.Namespace, k, v).
   217  			WillReturnResult(sqlmock.NewResult(1, 1))
   218  	}
   219  	mock.ExpectCommit()
   220  
   221  	if err := sqlDriver.Create(key, rel); err != nil {
   222  		t.Fatalf("failed to create release with key %s: %v", key, err)
   223  	}
   224  
   225  	if err := mock.ExpectationsWereMet(); err != nil {
   226  		t.Errorf("sql expectations weren't met: %v", err)
   227  	}
   228  }
   229  
   230  func TestSqlCreateAlreadyExists(t *testing.T) {
   231  	vers := 1
   232  	name := "smug-pigeon"
   233  	namespace := "default"
   234  	key := testKey(name, vers)
   235  	rel := releaseStub(name, vers, namespace, rspb.StatusDeployed)
   236  
   237  	sqlDriver, mock := newTestFixtureSQL(t)
   238  	body, _ := encodeRelease(rel)
   239  
   240  	insertQuery := fmt.Sprintf(
   241  		"INSERT INTO %s (%s,%s,%s,%s,%s,%s,%s,%s,%s) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9)",
   242  		sqlReleaseTableName,
   243  		sqlReleaseTableKeyColumn,
   244  		sqlReleaseTableTypeColumn,
   245  		sqlReleaseTableBodyColumn,
   246  		sqlReleaseTableNameColumn,
   247  		sqlReleaseTableNamespaceColumn,
   248  		sqlReleaseTableVersionColumn,
   249  		sqlReleaseTableStatusColumn,
   250  		sqlReleaseTableOwnerColumn,
   251  		sqlReleaseTableCreatedAtColumn,
   252  	)
   253  
   254  	// Insert fails (primary key already exists)
   255  	mock.ExpectBegin()
   256  	mock.
   257  		ExpectExec(regexp.QuoteMeta(insertQuery)).
   258  		WithArgs(key, sqlReleaseDefaultType, body, rel.Name, rel.Namespace, int(rel.Version), rel.Info.Status.String(), sqlReleaseDefaultOwner, int(time.Now().Unix())).
   259  		WillReturnError(fmt.Errorf("dialect dependent SQL error"))
   260  
   261  	selectQuery := fmt.Sprintf(
   262  		regexp.QuoteMeta("SELECT %s FROM %s WHERE %s = $1 AND %s = $2"),
   263  		sqlReleaseTableKeyColumn,
   264  		sqlReleaseTableName,
   265  		sqlReleaseTableKeyColumn,
   266  		sqlReleaseTableNamespaceColumn,
   267  	)
   268  
   269  	// Let's check that we do make sure the error is due to a release already existing
   270  	mock.
   271  		ExpectQuery(selectQuery).
   272  		WithArgs(key, namespace).
   273  		WillReturnRows(
   274  			mock.NewRows([]string{
   275  				sqlReleaseTableKeyColumn,
   276  			}).AddRow(
   277  				key,
   278  			),
   279  		).RowsWillBeClosed()
   280  	mock.ExpectRollback()
   281  
   282  	if err := sqlDriver.Create(key, rel); err == nil {
   283  		t.Fatalf("failed to create release with key %s: %v", key, err)
   284  	}
   285  
   286  	if err := mock.ExpectationsWereMet(); err != nil {
   287  		t.Errorf("sql expectations weren't met: %v", err)
   288  	}
   289  }
   290  
   291  func TestSqlUpdate(t *testing.T) {
   292  	vers := 1
   293  	name := "smug-pigeon"
   294  	namespace := "default"
   295  	key := testKey(name, vers)
   296  	rel := releaseStub(name, vers, namespace, rspb.StatusDeployed)
   297  
   298  	sqlDriver, mock := newTestFixtureSQL(t)
   299  	body, _ := encodeRelease(rel)
   300  
   301  	query := fmt.Sprintf(
   302  		"UPDATE %s SET %s = $1, %s = $2, %s = $3, %s = $4, %s = $5, %s = $6 WHERE %s = $7 AND %s = $8",
   303  		sqlReleaseTableName,
   304  		sqlReleaseTableBodyColumn,
   305  		sqlReleaseTableNameColumn,
   306  		sqlReleaseTableVersionColumn,
   307  		sqlReleaseTableStatusColumn,
   308  		sqlReleaseTableOwnerColumn,
   309  		sqlReleaseTableModifiedAtColumn,
   310  		sqlReleaseTableKeyColumn,
   311  		sqlReleaseTableNamespaceColumn,
   312  	)
   313  
   314  	mock.
   315  		ExpectExec(regexp.QuoteMeta(query)).
   316  		WithArgs(body, rel.Name, int(rel.Version), rel.Info.Status.String(), sqlReleaseDefaultOwner, int(time.Now().Unix()), key, namespace).
   317  		WillReturnResult(sqlmock.NewResult(0, 1))
   318  
   319  	if err := sqlDriver.Update(key, rel); err != nil {
   320  		t.Fatalf("failed to update release with key %s: %v", key, err)
   321  	}
   322  
   323  	if err := mock.ExpectationsWereMet(); err != nil {
   324  		t.Errorf("sql expectations weren't met: %v", err)
   325  	}
   326  }
   327  
   328  func TestSqlQuery(t *testing.T) {
   329  	// Reflect actual use cases in ../storage.go
   330  	labelSetUnknown := map[string]string{
   331  		"name":   "smug-pigeon",
   332  		"owner":  sqlReleaseDefaultOwner,
   333  		"status": "unknown",
   334  	}
   335  	labelSetDeployed := map[string]string{
   336  		"name":   "smug-pigeon",
   337  		"owner":  sqlReleaseDefaultOwner,
   338  		"status": "deployed",
   339  	}
   340  	labelSetAll := map[string]string{
   341  		"name":  "smug-pigeon",
   342  		"owner": sqlReleaseDefaultOwner,
   343  	}
   344  
   345  	supersededRelease := releaseStub("smug-pigeon", 1, "default", rspb.StatusSuperseded)
   346  	supersededReleaseBody, _ := encodeRelease(supersededRelease)
   347  	deployedRelease := releaseStub("smug-pigeon", 2, "default", rspb.StatusDeployed)
   348  	deployedReleaseBody, _ := encodeRelease(deployedRelease)
   349  
   350  	// Let's actually start our test
   351  	sqlDriver, mock := newTestFixtureSQL(t)
   352  
   353  	query := fmt.Sprintf(
   354  		"SELECT %s, %s, %s FROM %s WHERE %s = $1 AND %s = $2 AND %s = $3 AND %s = $4",
   355  		sqlReleaseTableKeyColumn,
   356  		sqlReleaseTableNamespaceColumn,
   357  		sqlReleaseTableBodyColumn,
   358  		sqlReleaseTableName,
   359  		sqlReleaseTableNameColumn,
   360  		sqlReleaseTableOwnerColumn,
   361  		sqlReleaseTableStatusColumn,
   362  		sqlReleaseTableNamespaceColumn,
   363  	)
   364  
   365  	mock.
   366  		ExpectQuery(regexp.QuoteMeta(query)).
   367  		WithArgs("smug-pigeon", sqlReleaseDefaultOwner, "unknown", "default").
   368  		WillReturnRows(
   369  			mock.NewRows([]string{
   370  				sqlReleaseTableBodyColumn,
   371  			}),
   372  		).RowsWillBeClosed()
   373  
   374  	mock.
   375  		ExpectQuery(regexp.QuoteMeta(query)).
   376  		WithArgs("smug-pigeon", sqlReleaseDefaultOwner, "deployed", "default").
   377  		WillReturnRows(
   378  			mock.NewRows([]string{
   379  				sqlReleaseTableBodyColumn,
   380  			}).AddRow(
   381  				deployedReleaseBody,
   382  			),
   383  		).RowsWillBeClosed()
   384  
   385  	mockGetReleaseCustomLabels(mock, "", deployedRelease.Namespace, deployedRelease.Labels)
   386  
   387  	query = fmt.Sprintf(
   388  		"SELECT %s, %s, %s FROM %s WHERE %s = $1 AND %s = $2 AND %s = $3",
   389  		sqlReleaseTableKeyColumn,
   390  		sqlReleaseTableNamespaceColumn,
   391  		sqlReleaseTableBodyColumn,
   392  		sqlReleaseTableName,
   393  		sqlReleaseTableNameColumn,
   394  		sqlReleaseTableOwnerColumn,
   395  		sqlReleaseTableNamespaceColumn,
   396  	)
   397  
   398  	mock.
   399  		ExpectQuery(regexp.QuoteMeta(query)).
   400  		WithArgs("smug-pigeon", sqlReleaseDefaultOwner, "default").
   401  		WillReturnRows(
   402  			mock.NewRows([]string{
   403  				sqlReleaseTableBodyColumn,
   404  			}).AddRow(
   405  				supersededReleaseBody,
   406  			).AddRow(
   407  				deployedReleaseBody,
   408  			),
   409  		).RowsWillBeClosed()
   410  
   411  	mockGetReleaseCustomLabels(mock, "", supersededRelease.Namespace, supersededRelease.Labels)
   412  	mockGetReleaseCustomLabels(mock, "", deployedRelease.Namespace, deployedRelease.Labels)
   413  
   414  	_, err := sqlDriver.Query(labelSetUnknown)
   415  	if err == nil {
   416  		t.Errorf("Expected error {%v}, got nil", ErrReleaseNotFound)
   417  	} else if err != ErrReleaseNotFound {
   418  		t.Fatalf("failed to query for unknown smug-pigeon release: %v", err)
   419  	}
   420  
   421  	results, err := sqlDriver.Query(labelSetDeployed)
   422  	if err != nil {
   423  		t.Fatalf("failed to query for deployed smug-pigeon release: %v", err)
   424  	}
   425  
   426  	for _, res := range results {
   427  		if !reflect.DeepEqual(res, deployedRelease) {
   428  			t.Errorf("Expected release {%v}, got {%v}", deployedRelease, res)
   429  		}
   430  	}
   431  
   432  	results, err = sqlDriver.Query(labelSetAll)
   433  	if err != nil {
   434  		t.Fatalf("failed to query release history for smug-pigeon: %v", err)
   435  	}
   436  
   437  	if len(results) != 2 {
   438  		t.Errorf("expected a resultset of size 2, got %d", len(results))
   439  	}
   440  
   441  	for _, res := range results {
   442  		if !reflect.DeepEqual(res, deployedRelease) && !reflect.DeepEqual(res, supersededRelease) {
   443  			t.Errorf("Expected release {%v} or {%v}, got {%v}", deployedRelease, supersededRelease, res)
   444  		}
   445  	}
   446  
   447  	if err := mock.ExpectationsWereMet(); err != nil {
   448  		t.Errorf("sql expectations weren't met: %v", err)
   449  	}
   450  }
   451  
   452  func TestSqlDelete(t *testing.T) {
   453  	vers := 1
   454  	name := "smug-pigeon"
   455  	namespace := "default"
   456  	key := testKey(name, vers)
   457  	rel := releaseStub(name, vers, namespace, rspb.StatusDeployed)
   458  
   459  	body, _ := encodeRelease(rel)
   460  
   461  	sqlDriver, mock := newTestFixtureSQL(t)
   462  
   463  	selectQuery := fmt.Sprintf(
   464  		"SELECT %s FROM %s WHERE %s = $1 AND %s = $2",
   465  		sqlReleaseTableBodyColumn,
   466  		sqlReleaseTableName,
   467  		sqlReleaseTableKeyColumn,
   468  		sqlReleaseTableNamespaceColumn,
   469  	)
   470  
   471  	mock.ExpectBegin()
   472  	mock.
   473  		ExpectQuery(regexp.QuoteMeta(selectQuery)).
   474  		WithArgs(key, namespace).
   475  		WillReturnRows(
   476  			mock.NewRows([]string{
   477  				sqlReleaseTableBodyColumn,
   478  			}).AddRow(
   479  				body,
   480  			),
   481  		).RowsWillBeClosed()
   482  
   483  	deleteQuery := fmt.Sprintf(
   484  		"DELETE FROM %s WHERE %s = $1 AND %s = $2",
   485  		sqlReleaseTableName,
   486  		sqlReleaseTableKeyColumn,
   487  		sqlReleaseTableNamespaceColumn,
   488  	)
   489  
   490  	mock.
   491  		ExpectExec(regexp.QuoteMeta(deleteQuery)).
   492  		WithArgs(key, namespace).
   493  		WillReturnResult(sqlmock.NewResult(0, 1))
   494  
   495  	mockGetReleaseCustomLabels(mock, key, namespace, rel.Labels)
   496  
   497  	deleteLabelsQuery := fmt.Sprintf(
   498  		"DELETE FROM %s WHERE %s = $1 AND %s = $2",
   499  		sqlCustomLabelsTableName,
   500  		sqlCustomLabelsTableReleaseKeyColumn,
   501  		sqlCustomLabelsTableReleaseNamespaceColumn,
   502  	)
   503  	mock.
   504  		ExpectExec(regexp.QuoteMeta(deleteLabelsQuery)).
   505  		WithArgs(key, namespace).
   506  		WillReturnResult(sqlmock.NewResult(0, 1))
   507  
   508  	mock.ExpectCommit()
   509  
   510  	deletedRelease, err := sqlDriver.Delete(key)
   511  	if err := mock.ExpectationsWereMet(); err != nil {
   512  		t.Errorf("sql expectations weren't met: %v", err)
   513  	}
   514  	if err != nil {
   515  		t.Fatalf("failed to delete release with key %q: %v", key, err)
   516  	}
   517  
   518  	if !reflect.DeepEqual(rel, deletedRelease) {
   519  		t.Errorf("Expected release {%v}, got {%v}", rel, deletedRelease)
   520  	}
   521  }
   522  
   523  func mockGetReleaseCustomLabels(mock sqlmock.Sqlmock, key string, namespace string, labels map[string]string) {
   524  	query := fmt.Sprintf(
   525  		regexp.QuoteMeta("SELECT %s, %s FROM %s WHERE %s = $1 AND %s = $2"),
   526  		sqlCustomLabelsTableKeyColumn,
   527  		sqlCustomLabelsTableValueColumn,
   528  		sqlCustomLabelsTableName,
   529  		sqlCustomLabelsTableReleaseKeyColumn,
   530  		sqlCustomLabelsTableReleaseNamespaceColumn,
   531  	)
   532  
   533  	eq := mock.ExpectQuery(query).
   534  		WithArgs(key, namespace)
   535  
   536  	returnRows := mock.NewRows([]string{
   537  		sqlCustomLabelsTableKeyColumn,
   538  		sqlCustomLabelsTableValueColumn,
   539  	})
   540  	for k, v := range labels {
   541  		returnRows.AddRow(k, v)
   542  	}
   543  	eq.WillReturnRows(returnRows).RowsWillBeClosed()
   544  }
   545  
   546  func TestSqlChechkAppliedMigrations(t *testing.T) {
   547  	cases := []struct {
   548  		migrationsToApply    []*migrate.Migration
   549  		appliedMigrationsIDs []string
   550  		expectedResult       bool
   551  		errorExplanation     string
   552  	}{
   553  		{
   554  			migrationsToApply:    []*migrate.Migration{{Id: "init1"}, {Id: "init2"}, {Id: "init3"}},
   555  			appliedMigrationsIDs: []string{"1", "2", "init1", "3", "init2", "4", "5"},
   556  			expectedResult:       false,
   557  			errorExplanation:     "Has found one migration id \"init3\" as applied, that was not applied",
   558  		},
   559  		{
   560  			migrationsToApply:    []*migrate.Migration{{Id: "init1"}, {Id: "init2"}, {Id: "init3"}},
   561  			appliedMigrationsIDs: []string{"1", "2", "init1", "3", "init2", "4", "init3", "5"},
   562  			expectedResult:       true,
   563  			errorExplanation:     "Has not found one or more migration ids, that was applied",
   564  		},
   565  		{
   566  			migrationsToApply:    []*migrate.Migration{{Id: "init"}},
   567  			appliedMigrationsIDs: []string{"1", "2", "3", "inits", "4", "tinit", "5"},
   568  			expectedResult:       false,
   569  			errorExplanation:     "Has found single \"init\", that was not applied",
   570  		},
   571  		{
   572  			migrationsToApply:    []*migrate.Migration{{Id: "init"}},
   573  			appliedMigrationsIDs: []string{"1", "2", "init", "3", "init2", "4", "init3", "5"},
   574  			expectedResult:       true,
   575  			errorExplanation:     "Has not found single migration id \"init\", that was applied",
   576  		},
   577  	}
   578  	for i, c := range cases {
   579  		sqlDriver, mock := newTestFixtureSQL(t)
   580  		rows := sqlmock.NewRows([]string{"id", "applied_at"})
   581  		for _, id := range c.appliedMigrationsIDs {
   582  			rows.AddRow(id, time.Time{})
   583  		}
   584  		mock.
   585  			ExpectQuery("").
   586  			WillReturnRows(rows)
   587  		mock.ExpectCommit()
   588  		if sqlDriver.checkAlreadyApplied(c.migrationsToApply) != c.expectedResult {
   589  			t.Errorf("Test case: %v, Expected: %v, Have: %v, Explanation: %v", i, c.expectedResult, !c.expectedResult, c.errorExplanation)
   590  		}
   591  	}
   592  }
   593  

View as plain text