...

Source file src/github.com/cybertec-postgresql/pgwatch/v3/internal/sources/yaml_test.go

Documentation: github.com/cybertec-postgresql/pgwatch/v3/internal/sources

     1  package sources_test
     2  
     3  import (
     4  	"os"
     5  	"path/filepath"
     6  	"testing"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  
    10  	"github.com/cybertec-postgresql/pgwatch/v3/internal/sources"
    11  )
    12  
    13  // the number of entries in the sample.sources.yaml file
    14  const sampleEntriesNumber = 4
    15  
    16  const (
    17  	contribDir = "../../contrib/"
    18  	sampleFile = "../../contrib/sample.sources.yaml"
    19  )
    20  
    21  func TestNewYAMLSourcesReaderWriter(t *testing.T) {
    22  	a := assert.New(t)
    23  	yamlrw, err := sources.NewYAMLSourcesReaderWriter(ctx, sampleFile)
    24  	a.NoError(err)
    25  	a.NotNil(t, yamlrw)
    26  }
    27  
    28  func TestYAMLGetMonitoredDatabases(t *testing.T) {
    29  	a := assert.New(t)
    30  
    31  	t.Run("single file", func(*testing.T) {
    32  		yamlrw, err := sources.NewYAMLSourcesReaderWriter(ctx, sampleFile)
    33  		a.NoError(err)
    34  
    35  		dbs, err := yamlrw.GetSources()
    36  		a.NoError(err)
    37  		a.Len(dbs, sampleEntriesNumber)
    38  	})
    39  
    40  	t.Run("nonexistent file", func(*testing.T) {
    41  		yamlrw, err := sources.NewYAMLSourcesReaderWriter(ctx, "nonexistent.yaml")
    42  		a.NoError(err)
    43  		dbs, err := yamlrw.GetSources()
    44  		a.Error(err)
    45  		a.Nil(dbs)
    46  	})
    47  
    48  	t.Run("garbage file", func(*testing.T) {
    49  		yamlrw, err := sources.NewYAMLSourcesReaderWriter(ctx, filepath.Join(contribDir, "yaml.go"))
    50  		a.NoError(err)
    51  		dbs, err := yamlrw.GetSources()
    52  		a.Error(err)
    53  		a.Nil(dbs)
    54  	})
    55  
    56  	t.Run("duplicate in single file", func(t *testing.T) {
    57  		tmpFile := filepath.Join(t.TempDir(), "duplicate.yaml")
    58  		yamlContent := `
    59  - name: test1
    60    conn_str: postgresql://localhost/test1
    61  - name: test2
    62    conn_str: postgresql://localhost/test2
    63  - name: test1
    64    conn_str: postgresql://localhost/test1_duplicate
    65  `
    66  		err := os.WriteFile(tmpFile, []byte(yamlContent), 0644)
    67  		a.NoError(err)
    68  		yamlrw, err := sources.NewYAMLSourcesReaderWriter(ctx, tmpFile)
    69  		a.NoError(err)
    70  
    71  		dbs, err := yamlrw.GetSources()
    72  		a.Error(err)
    73  		a.Nil(dbs)
    74  	})
    75  
    76  	t.Run("duplicates across files", func(t *testing.T) {
    77  		tmpDir := t.TempDir()
    78  		yamlContent1 := `
    79  - name: test1
    80    conn_str: postgresql://localhost/test1
    81  - name: test2
    82    conn_str: postgresql://localhost/test2
    83  `
    84  		err := os.WriteFile(filepath.Join(tmpDir, "sources1.yaml"), []byte(yamlContent1), 0644)
    85  		a.NoError(err)
    86  
    87  		yamlContent2 := `
    88  - name: test1
    89    conn_str: postgresql://localhost/test1_duplicate
    90  `
    91  		err = os.WriteFile(filepath.Join(tmpDir, "sources2.yaml"), []byte(yamlContent2), 0644)
    92  		a.NoError(err)
    93  		yamlrw, err := sources.NewYAMLSourcesReaderWriter(ctx, tmpDir)
    94  		a.NoError(err)
    95  
    96  		dbs, err := yamlrw.GetSources()
    97  		a.Error(err)
    98  		a.Nil(dbs)
    99  	})
   100  }
   101  
   102  func TestYAMLDeleteDatabase(t *testing.T) {
   103  	a := assert.New(t)
   104  
   105  	t.Run("happy path", func(*testing.T) {
   106  		data, err := os.ReadFile(sampleFile)
   107  		a.NoError(err)
   108  		tmpSampleFile := filepath.Join(t.TempDir(), "sample.sources.yaml")
   109  		err = os.WriteFile(tmpSampleFile, data, 0644)
   110  		a.NoError(err)
   111  		defer os.Remove(tmpSampleFile)
   112  
   113  		yamlrw, err := sources.NewYAMLSourcesReaderWriter(ctx, tmpSampleFile)
   114  		a.NoError(err)
   115  
   116  		err = yamlrw.DeleteSource("test1")
   117  		a.NoError(err)
   118  
   119  		dbs, err := yamlrw.GetSources()
   120  		a.NoError(err)
   121  		a.Len(dbs, sampleEntriesNumber-1)
   122  	})
   123  
   124  	t.Run("nonexistent file", func(*testing.T) {
   125  		yamlrw, err := sources.NewYAMLSourcesReaderWriter(ctx, "nonexistent.yaml")
   126  		a.NoError(err)
   127  		err = yamlrw.DeleteSource("test1")
   128  		a.Error(err)
   129  	})
   130  }
   131  
   132  func TestYAMLUpdateDatabase(t *testing.T) {
   133  	a := assert.New(t)
   134  
   135  	t.Run("happy path", func(*testing.T) {
   136  		data, err := os.ReadFile(sampleFile)
   137  		a.NoError(err)
   138  		tmpSampleFile := filepath.Join(t.TempDir(), "sample.sources.yaml")
   139  		err = os.WriteFile(tmpSampleFile, data, 0644)
   140  		a.NoError(err)
   141  		defer os.Remove(tmpSampleFile)
   142  
   143  		yamlrw, err := sources.NewYAMLSourcesReaderWriter(ctx, tmpSampleFile)
   144  		a.NoError(err)
   145  
   146  		// change the connection string of the first database
   147  		md := sources.Source{}
   148  		md.Name = "test1"
   149  		md.ConnStr = "postgresql://localhost/test1"
   150  		err = yamlrw.UpdateSource(md)
   151  		a.NoError(err)
   152  
   153  		// add a new database
   154  		md = sources.Source{}
   155  		md.Name = "test5"
   156  		md.ConnStr = "postgresql://localhost/test5"
   157  		err = yamlrw.UpdateSource(md)
   158  		a.NoError(err)
   159  
   160  		dbs, err := yamlrw.GetSources()
   161  		a.NoError(err)
   162  		a.Len(dbs, sampleEntriesNumber+1)
   163  		dbs[0].ConnStr = "postgresql://localhost/test1"
   164  		dbs[sampleEntriesNumber].ConnStr = "postgresql://localhost/test5"
   165  	})
   166  
   167  	t.Run("nonexistent file", func(*testing.T) {
   168  		yamlrw, err := sources.NewYAMLSourcesReaderWriter(ctx, "")
   169  		a.NoError(err)
   170  		err = yamlrw.UpdateSource(sources.Source{})
   171  		a.Error(err)
   172  	})
   173  }
   174  
   175  func TestYAMLCreateSource(t *testing.T) {
   176  	a := assert.New(t)
   177  
   178  	t.Run("happy_path", func(*testing.T) {
   179  		data, err := os.ReadFile(sampleFile)
   180  		a.NoError(err)
   181  		tmpSampleFile := filepath.Join(t.TempDir(), "sample.sources.yaml")
   182  		err = os.WriteFile(tmpSampleFile, data, 0644)
   183  		a.NoError(err)
   184  		defer os.Remove(tmpSampleFile)
   185  
   186  		yamlrw, err := sources.NewYAMLSourcesReaderWriter(ctx, tmpSampleFile)
   187  		a.NoError(err)
   188  
   189  		// Create a new source
   190  		md := sources.Source{
   191  			Name:    "new_source",
   192  			ConnStr: "postgresql://localhost/new_db",
   193  			Kind:    sources.SourcePostgres,
   194  		}
   195  		err = yamlrw.CreateSource(md)
   196  		a.NoError(err)
   197  
   198  		// Verify it was created
   199  		dbs, err := yamlrw.GetSources()
   200  		a.NoError(err)
   201  		a.Len(dbs, sampleEntriesNumber+1)
   202  
   203  		// Try to create the same source again - should fail
   204  		err = yamlrw.CreateSource(md)
   205  		a.Error(err)
   206  		a.ErrorIs(sources.ErrSourceExists, err)
   207  	})
   208  
   209  	t.Run("duplicate_source", func(*testing.T) {
   210  		data, err := os.ReadFile(sampleFile)
   211  		a.NoError(err)
   212  		tmpSampleFile := filepath.Join(t.TempDir(), "sample.sources.yaml")
   213  		err = os.WriteFile(tmpSampleFile, data, 0644)
   214  		a.NoError(err)
   215  		defer os.Remove(tmpSampleFile)
   216  
   217  		yamlrw, err := sources.NewYAMLSourcesReaderWriter(ctx, tmpSampleFile)
   218  		a.NoError(err)
   219  
   220  		// Try to create a source that already exists
   221  		md := sources.Source{
   222  			Name:    "test1", // This name already exists in sample file
   223  			ConnStr: "postgresql://localhost/test1",
   224  			Kind:    sources.SourcePostgres,
   225  		}
   226  		err = yamlrw.CreateSource(md)
   227  		a.Error(err)
   228  		a.ErrorIs(sources.ErrSourceExists, err)
   229  	})
   230  }
   231