github.com/voedger/voedger@v0.0.0-20240520144910-273e84102129/pkg/istructsmem/internal/containers/impl_test.go (about)

     1  /*
     2   * Copyright (c) 2021-present Sigma-Soft, Ltd.
     3   * @author: Nikolay Nikitin
     4   */
     5  
     6  package containers
     7  
     8  import (
     9  	"errors"
    10  	"fmt"
    11  	"testing"
    12  
    13  	"github.com/stretchr/testify/require"
    14  
    15  	"github.com/voedger/voedger/pkg/appdef"
    16  	"github.com/voedger/voedger/pkg/istorage/mem"
    17  	istorageimpl "github.com/voedger/voedger/pkg/istorage/provider"
    18  	"github.com/voedger/voedger/pkg/istructs"
    19  	"github.com/voedger/voedger/pkg/istructsmem/internal/consts"
    20  	"github.com/voedger/voedger/pkg/istructsmem/internal/teststore"
    21  	"github.com/voedger/voedger/pkg/istructsmem/internal/utils"
    22  	"github.com/voedger/voedger/pkg/istructsmem/internal/vers"
    23  )
    24  
    25  func TestContainers(t *testing.T) {
    26  	require := require.New(t)
    27  
    28  	sp := istorageimpl.Provide(mem.Provide())
    29  	storage, err := sp.AppStorage(istructs.AppQName_test1_app1)
    30  	require.NoError(err)
    31  
    32  	versions := vers.New()
    33  	if err := versions.Prepare(storage); err != nil {
    34  		panic(err)
    35  	}
    36  
    37  	containerName := "test"
    38  
    39  	containers := New()
    40  	if err := containers.Prepare(storage, versions,
    41  		func() appdef.IAppDef {
    42  			objName := appdef.NewQName("test", "object")
    43  			adb := appdef.New()
    44  			adb.AddPackage("test", "test.com/test")
    45  			adb.AddObject(objName).
    46  				AddContainer(containerName, objName, 0, 1)
    47  			result, err := adb.Build()
    48  			require.NoError(err)
    49  			return result
    50  		}()); err != nil {
    51  		panic(err)
    52  	}
    53  
    54  	t.Run("basic Containers methods", func(t *testing.T) {
    55  
    56  		check := func(containers *Containers, name string) ContainerID {
    57  			id, err := containers.ID(name)
    58  			require.NoError(err)
    59  			require.NotEqual(NullContainerID, id)
    60  
    61  			n, err := containers.Container(id)
    62  			require.NoError(err)
    63  			require.Equal(name, n)
    64  
    65  			return id
    66  		}
    67  
    68  		id := check(containers, containerName)
    69  
    70  		t.Run("must be ok to load early stored names", func(t *testing.T) {
    71  			versions1 := vers.New()
    72  			if err := versions1.Prepare(storage); err != nil {
    73  				panic(err)
    74  			}
    75  
    76  			containers1 := New()
    77  			if err := containers1.Prepare(storage, versions, nil); err != nil {
    78  				panic(err)
    79  			}
    80  
    81  			require.Equal(id, check(containers1, containerName))
    82  		})
    83  
    84  		t.Run("must be ok to redeclare containers", func(t *testing.T) {
    85  			versions2 := vers.New()
    86  			if err := versions2.Prepare(storage); err != nil {
    87  				panic(err)
    88  			}
    89  
    90  			containers2 := New()
    91  			if err := containers2.Prepare(storage, versions,
    92  				func() appdef.IAppDef {
    93  					objName := appdef.NewQName("test", "object")
    94  					adb := appdef.New()
    95  					adb.AddPackage("test", "test.com/test")
    96  					adb.AddObject(objName).
    97  						AddContainer(containerName, objName, 0, 1)
    98  					result, err := adb.Build()
    99  					require.NoError(err)
   100  					return result
   101  				}()); err != nil {
   102  				panic(err)
   103  			}
   104  
   105  			require.Equal(id, check(containers2, containerName))
   106  		})
   107  	})
   108  
   109  	t.Run("must be error if unknown container", func(t *testing.T) {
   110  		id, err := containers.ID("unknown")
   111  		require.Equal(NullContainerID, id)
   112  		require.ErrorIs(err, ErrContainerNotFound)
   113  	})
   114  
   115  	t.Run("must be error if unknown id", func(t *testing.T) {
   116  		n, err := containers.Container(ContainerID(MaxAvailableContainerID))
   117  		require.Equal("", n)
   118  		require.ErrorIs(err, ErrContainerIDNotFound)
   119  	})
   120  }
   121  
   122  func TestContainersPrepareErrors(t *testing.T) {
   123  	require := require.New(t)
   124  
   125  	t.Run("must be error if unknown system view version", func(t *testing.T) {
   126  		sp := istorageimpl.Provide(mem.Provide())
   127  		storage, _ := sp.AppStorage(istructs.AppQName_test1_app1)
   128  
   129  		versions := vers.New()
   130  		if err := versions.Prepare(storage); err != nil {
   131  			panic(err)
   132  		}
   133  
   134  		versions.Put(vers.SysContainersVersion, latestVersion+1)
   135  
   136  		names := New()
   137  		err := names.Prepare(storage, versions, nil)
   138  		require.ErrorIs(err, vers.ErrorInvalidVersion)
   139  	})
   140  
   141  	t.Run("must be error if invalid Container loaded from system view ", func(t *testing.T) {
   142  		sp := istorageimpl.Provide(mem.Provide())
   143  		storage, _ := sp.AppStorage(istructs.AppQName_test1_app1)
   144  
   145  		versions := vers.New()
   146  		if err := versions.Prepare(storage); err != nil {
   147  			panic(err)
   148  		}
   149  
   150  		versions.Put(vers.SysContainersVersion, latestVersion)
   151  		const badName = "-test-error-name-"
   152  		storage.Put(utils.ToBytes(consts.SysView_Containers, ver01), []byte(badName), utils.ToBytes(ContainerID(512)))
   153  
   154  		names := New()
   155  		err := names.Prepare(storage, versions, nil)
   156  		require.ErrorIs(err, appdef.ErrInvalidError)
   157  	})
   158  
   159  	t.Run("must be ok if deleted Container loaded from system view ", func(t *testing.T) {
   160  		sp := istorageimpl.Provide(mem.Provide())
   161  		storage, _ := sp.AppStorage(istructs.AppQName_test1_app1)
   162  
   163  		versions := vers.New()
   164  		if err := versions.Prepare(storage); err != nil {
   165  			panic(err)
   166  		}
   167  
   168  		versions.Put(vers.SysContainersVersion, latestVersion)
   169  		storage.Put(utils.ToBytes(consts.SysView_Containers, ver01), []byte("deleted"), utils.ToBytes(NullContainerID))
   170  
   171  		names := New()
   172  		err := names.Prepare(storage, versions, nil)
   173  		require.NoError(err)
   174  	})
   175  
   176  	t.Run("must be error if invalid (small) ContainerID loaded from system view ", func(t *testing.T) {
   177  		sp := istorageimpl.Provide(mem.Provide())
   178  		storage, _ := sp.AppStorage(istructs.AppQName_test1_app1)
   179  
   180  		versions := vers.New()
   181  		if err := versions.Prepare(storage); err != nil {
   182  			panic(err)
   183  		}
   184  
   185  		versions.Put(vers.SysContainersVersion, latestVersion)
   186  		storage.Put(utils.ToBytes(consts.SysView_Containers, ver01), []byte("test"), utils.ToBytes(ContainerID(1)))
   187  
   188  		names := New()
   189  		err := names.Prepare(storage, versions, nil)
   190  		require.ErrorIs(err, ErrWrongContainerID)
   191  	})
   192  
   193  	t.Run("must be error if too many Containers", func(t *testing.T) {
   194  		sp := istorageimpl.Provide(mem.Provide())
   195  		storage, _ := sp.AppStorage(istructs.AppQName_test1_app1)
   196  
   197  		versions := vers.New()
   198  		if err := versions.Prepare(storage); err != nil {
   199  			panic(err)
   200  		}
   201  
   202  		names := New()
   203  		err := names.Prepare(storage, versions,
   204  			func() appdef.IAppDef {
   205  				adb := appdef.New()
   206  				adb.AddPackage("test", "test.com/test")
   207  				qName := appdef.NewQName("test", "test")
   208  				obj := adb.AddObject(qName)
   209  				for i := 0; i <= MaxAvailableContainerID; i++ {
   210  					obj.AddContainer(fmt.Sprintf("cont_%d", i), qName, 0, 1)
   211  				}
   212  				result, err := adb.Build()
   213  				require.NoError(err)
   214  				return result
   215  			}())
   216  		require.ErrorIs(err, ErrContainerIDsExceeds)
   217  	})
   218  
   219  	t.Run("must be error if write to storage failed", func(t *testing.T) {
   220  		containerName := "testContainerName"
   221  		writeError := errors.New("storage write error")
   222  
   223  		t.Run("must be error if write some name failed", func(t *testing.T) {
   224  			storage := teststore.NewStorage()
   225  
   226  			versions := vers.New()
   227  			if err := versions.Prepare(storage); err != nil {
   228  				panic(err)
   229  			}
   230  
   231  			storage.SchedulePutError(writeError, utils.ToBytes(consts.SysView_Containers, ver01), []byte(containerName))
   232  
   233  			names := New()
   234  			err := names.Prepare(storage, versions,
   235  				func() appdef.IAppDef {
   236  					objName := appdef.NewQName("test", "object")
   237  					adb := appdef.New()
   238  					adb.AddPackage("test", "test.com/test")
   239  					adb.AddObject(objName).
   240  						AddContainer(containerName, objName, 0, 1)
   241  					result, err := adb.Build()
   242  					require.NoError(err)
   243  					return result
   244  				}())
   245  			require.ErrorIs(err, writeError)
   246  		})
   247  
   248  		t.Run("must be error if write system view version failed", func(t *testing.T) {
   249  			storage := teststore.NewStorage()
   250  
   251  			versions := vers.New()
   252  			if err := versions.Prepare(storage); err != nil {
   253  				panic(err)
   254  			}
   255  
   256  			storage.SchedulePutError(writeError, utils.ToBytes(consts.SysView_Versions), utils.ToBytes(vers.SysContainersVersion))
   257  
   258  			names := New()
   259  			err := names.Prepare(storage, versions,
   260  				func() appdef.IAppDef {
   261  					objName := appdef.NewQName("test", "object")
   262  					adb := appdef.New()
   263  					adb.AddPackage("test", "test.com/test")
   264  					adb.AddObject(objName).
   265  						AddContainer(containerName, objName, 0, 1)
   266  					result, err := adb.Build()
   267  					require.NoError(err)
   268  					return result
   269  				}())
   270  			require.ErrorIs(err, writeError)
   271  		})
   272  	})
   273  }