go.temporal.io/server@v1.23.0/common/persistence/sql/sqlplugin/tests/history_shard.go (about)

     1  // The MIT License
     2  //
     3  // Copyright (c) 2020 Temporal Technologies Inc.  All rights reserved.
     4  //
     5  // Copyright (c) 2020 Uber Technologies, Inc.
     6  //
     7  // Permission is hereby granted, free of charge, to any person obtaining a copy
     8  // of this software and associated documentation files (the "Software"), to deal
     9  // in the Software without restriction, including without limitation the rights
    10  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    11  // copies of the Software, and to permit persons to whom the Software is
    12  // furnished to do so, subject to the following conditions:
    13  //
    14  // The above copyright notice and this permission notice shall be included in
    15  // all copies or substantial portions of the Software.
    16  //
    17  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    18  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    19  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    20  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    21  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    22  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    23  // THE SOFTWARE.
    24  
    25  package tests
    26  
    27  import (
    28  	"math/rand"
    29  	"testing"
    30  
    31  	"github.com/stretchr/testify/require"
    32  	"github.com/stretchr/testify/suite"
    33  
    34  	"go.temporal.io/server/common/persistence/sql/sqlplugin"
    35  	"go.temporal.io/server/common/shuffle"
    36  )
    37  
    38  type (
    39  	historyShardSuite struct {
    40  		suite.Suite
    41  		*require.Assertions
    42  
    43  		store sqlplugin.HistoryShard
    44  	}
    45  )
    46  
    47  const (
    48  	testHistoryShardEncoding = "random encoding"
    49  )
    50  
    51  var (
    52  	testHistoryShardData = []byte("random history shard data")
    53  )
    54  
    55  func NewHistoryShardSuite(
    56  	t *testing.T,
    57  	store sqlplugin.HistoryShard,
    58  ) *historyShardSuite {
    59  	return &historyShardSuite{
    60  		Assertions: require.New(t),
    61  		store:      store,
    62  	}
    63  }
    64  
    65  func (s *historyShardSuite) SetupSuite() {
    66  
    67  }
    68  
    69  func (s *historyShardSuite) TearDownSuite() {
    70  
    71  }
    72  
    73  func (s *historyShardSuite) SetupTest() {
    74  	s.Assertions = require.New(s.T())
    75  }
    76  
    77  func (s *historyShardSuite) TearDownTest() {
    78  
    79  }
    80  
    81  func (s *historyShardSuite) TestInsert_Success() {
    82  	shardID := rand.Int31()
    83  	rangeID := int64(1)
    84  
    85  	shard := s.newRandomShardRow(shardID, rangeID)
    86  	result, err := s.store.InsertIntoShards(newExecutionContext(), &shard)
    87  	s.NoError(err)
    88  	rowsAffected, err := result.RowsAffected()
    89  	s.NoError(err)
    90  	s.Equal(1, int(rowsAffected))
    91  }
    92  
    93  func (s *historyShardSuite) TestInsert_Fail_Duplicate() {
    94  	shardID := rand.Int31()
    95  	rangeID := int64(1)
    96  
    97  	shard := s.newRandomShardRow(shardID, rangeID)
    98  	result, err := s.store.InsertIntoShards(newExecutionContext(), &shard)
    99  	s.NoError(err)
   100  	rowsAffected, err := result.RowsAffected()
   101  	s.NoError(err)
   102  	s.Equal(1, int(rowsAffected))
   103  
   104  	shard = s.newRandomShardRow(shardID, rangeID)
   105  	_, err = s.store.InsertIntoShards(newExecutionContext(), &shard)
   106  	s.Error(err) // TODO persistence layer should do proper error translation
   107  }
   108  
   109  func (s *historyShardSuite) TestInsertSelect() {
   110  	shardID := rand.Int31()
   111  	rangeID := int64(1)
   112  
   113  	shard := s.newRandomShardRow(shardID, rangeID)
   114  	result, err := s.store.InsertIntoShards(newExecutionContext(), &shard)
   115  	s.NoError(err)
   116  	rowsAffected, err := result.RowsAffected()
   117  	s.NoError(err)
   118  	s.Equal(1, int(rowsAffected))
   119  
   120  	filter := sqlplugin.ShardsFilter{
   121  		ShardID: shardID,
   122  	}
   123  	row, err := s.store.SelectFromShards(newExecutionContext(), filter)
   124  	s.NoError(err)
   125  	s.Equal(&shard, row)
   126  }
   127  
   128  func (s *historyShardSuite) TestInsertUpdate_Success() {
   129  	shardID := rand.Int31()
   130  	rangeID := int64(1)
   131  
   132  	shard := s.newRandomShardRow(shardID, rangeID)
   133  	rangeID += 100
   134  	result, err := s.store.InsertIntoShards(newExecutionContext(), &shard)
   135  	s.NoError(err)
   136  	rowsAffected, err := result.RowsAffected()
   137  	s.NoError(err)
   138  	s.Equal(1, int(rowsAffected))
   139  
   140  	shard = s.newRandomShardRow(shardID, rangeID)
   141  	result, err = s.store.UpdateShards(newExecutionContext(), &shard)
   142  	s.NoError(err)
   143  	rowsAffected, err = result.RowsAffected()
   144  	s.NoError(err)
   145  	s.Equal(1, int(rowsAffected))
   146  }
   147  
   148  func (s *historyShardSuite) TestUpdate_Fail() {
   149  	shardID := rand.Int31()
   150  	rangeID := int64(1)
   151  
   152  	shard := s.newRandomShardRow(shardID, rangeID)
   153  	result, err := s.store.UpdateShards(newExecutionContext(), &shard)
   154  	s.NoError(err)
   155  	rowsAffected, err := result.RowsAffected()
   156  	s.NoError(err)
   157  	s.Equal(0, int(rowsAffected))
   158  }
   159  
   160  func (s *historyShardSuite) TestInsertUpdateSelect() {
   161  	shardID := rand.Int31()
   162  	rangeID := int64(1)
   163  
   164  	shard := s.newRandomShardRow(shardID, rangeID)
   165  	rangeID += 100
   166  	result, err := s.store.InsertIntoShards(newExecutionContext(), &shard)
   167  	s.NoError(err)
   168  	rowsAffected, err := result.RowsAffected()
   169  	s.NoError(err)
   170  	s.Equal(1, int(rowsAffected))
   171  
   172  	shard = s.newRandomShardRow(shardID, rangeID)
   173  	result, err = s.store.UpdateShards(newExecutionContext(), &shard)
   174  	s.NoError(err)
   175  	rowsAffected, err = result.RowsAffected()
   176  	s.NoError(err)
   177  	s.Equal(1, int(rowsAffected))
   178  
   179  	filter := sqlplugin.ShardsFilter{
   180  		ShardID: shardID,
   181  	}
   182  	row, err := s.store.SelectFromShards(newExecutionContext(), filter)
   183  	s.NoError(err)
   184  	s.Equal(&shard, row)
   185  }
   186  
   187  func (s *historyShardSuite) TestInsertReadLock() {
   188  	shardID := rand.Int31()
   189  	rangeID := int64(rand.Int31())
   190  
   191  	shard := s.newRandomShardRow(shardID, rangeID)
   192  	result, err := s.store.InsertIntoShards(newExecutionContext(), &shard)
   193  	s.NoError(err)
   194  	rowsAffected, err := result.RowsAffected()
   195  	s.NoError(err)
   196  	s.Equal(1, int(rowsAffected))
   197  
   198  	// NOTE: lock without transaction is equivalent to select
   199  	//  this test only test the select functionality
   200  	filter := sqlplugin.ShardsFilter{
   201  		ShardID: shardID,
   202  	}
   203  	shardRange, err := s.store.ReadLockShards(newExecutionContext(), filter)
   204  	s.NoError(err)
   205  	s.Equal(rangeID, shardRange)
   206  }
   207  
   208  func (s *historyShardSuite) TestInsertWriteLock() {
   209  	shardID := rand.Int31()
   210  	rangeID := int64(rand.Int31())
   211  
   212  	shard := s.newRandomShardRow(shardID, rangeID)
   213  	result, err := s.store.InsertIntoShards(newExecutionContext(), &shard)
   214  	s.NoError(err)
   215  	rowsAffected, err := result.RowsAffected()
   216  	s.NoError(err)
   217  	s.Equal(1, int(rowsAffected))
   218  
   219  	// NOTE: lock without transaction is equivalent to select
   220  	//  this test only test the select functionality
   221  	filter := sqlplugin.ShardsFilter{
   222  		ShardID: shardID,
   223  	}
   224  	shardRange, err := s.store.WriteLockShards(newExecutionContext(), filter)
   225  	s.NoError(err)
   226  	s.Equal(rangeID, shardRange)
   227  }
   228  
   229  func (s *historyShardSuite) newRandomShardRow(
   230  	shardID int32,
   231  	rangeID int64,
   232  ) sqlplugin.ShardsRow {
   233  	return sqlplugin.ShardsRow{
   234  		ShardID:      shardID,
   235  		RangeID:      rangeID,
   236  		Data:         shuffle.Bytes(testHistoryShardData),
   237  		DataEncoding: testHistoryShardEncoding,
   238  	}
   239  }