github.com/mithrandie/csvq@v1.18.1/lib/query/transaction_test.go (about)

     1  package query
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"os"
     7  	"strings"
     8  	"sync"
     9  	"testing"
    10  
    11  	"github.com/mithrandie/csvq/lib/option"
    12  
    13  	"github.com/mithrandie/go-text"
    14  
    15  	"github.com/mithrandie/csvq/lib/parser"
    16  	"github.com/mithrandie/csvq/lib/value"
    17  )
    18  
    19  func TestTransaction_Commit(t *testing.T) {
    20  	defer func() {
    21  		_ = TestTx.ReleaseResources()
    22  		_ = TestTx.CachedViews.Clean(TestTx.FileContainer)
    23  		TestTx.Session.SetStdout(NewDiscard())
    24  		initFlag(TestTx.Flags)
    25  	}()
    26  
    27  	TestTx.Flags.SetQuiet(false)
    28  
    29  	ch, _ := TestTx.FileContainer.CreateHandlerForCreate(GetTestFilePath("created_file.csv"))
    30  	uh, _ := TestTx.FileContainer.CreateHandlerForUpdate(context.Background(), GetTestFilePath("updated_file_1.csv"), TestTx.WaitTimeout, TestTx.RetryDelay)
    31  
    32  	TestTx.CachedViews = GenerateViewMap([]*View{
    33  		{
    34  			Header:    NewHeader("created_file", []string{"column1", "column2"}),
    35  			RecordSet: RecordSet{},
    36  			FileInfo: &FileInfo{
    37  				Path:      GetTestFilePath("created_file.csv"),
    38  				Handler:   ch,
    39  				Encoding:  text.UTF8,
    40  				Format:    option.CSV,
    41  				Delimiter: ',',
    42  				LineBreak: text.LF,
    43  			},
    44  		},
    45  		{
    46  			Header: NewHeader("table1", []string{"column1", "column2"}),
    47  			RecordSet: []Record{
    48  				NewRecord([]value.Primary{
    49  					value.NewString("1"),
    50  					value.NewString("str1"),
    51  				}),
    52  				NewRecord([]value.Primary{
    53  					value.NewString("update1"),
    54  					value.NewString("update2"),
    55  				}),
    56  				NewRecord([]value.Primary{
    57  					value.NewString("3"),
    58  					value.NewString("str3"),
    59  				}),
    60  			},
    61  			FileInfo: &FileInfo{
    62  				Path:      GetTestFilePath("updated_file_1.csv"),
    63  				Handler:   uh,
    64  				Encoding:  text.UTF8,
    65  				Format:    option.CSV,
    66  				Delimiter: ',',
    67  				LineBreak: text.LF,
    68  			},
    69  		},
    70  	})
    71  
    72  	TestTx.UncommittedViews = UncommittedViews{
    73  		mtx: &sync.RWMutex{},
    74  		Created: map[string]*FileInfo{
    75  			strings.ToUpper(GetTestFilePath("created_file.csv")): {
    76  				Path:      GetTestFilePath("created_file.csv"),
    77  				Handler:   ch,
    78  				Encoding:  text.UTF8,
    79  				Format:    option.CSV,
    80  				Delimiter: ',',
    81  				LineBreak: text.LF,
    82  			},
    83  		},
    84  		Updated: map[string]*FileInfo{
    85  			strings.ToUpper(GetTestFilePath("updated_file_1.csv")): {
    86  				Path:      GetTestFilePath("updated_file_1.csv"),
    87  				Handler:   uh,
    88  				Encoding:  text.UTF8,
    89  				Format:    option.CSV,
    90  				Delimiter: ',',
    91  				LineBreak: text.LF,
    92  			},
    93  		},
    94  	}
    95  
    96  	expect := fmt.Sprintf("Commit: file %q is created.\nCommit: file %q is updated.\n", GetTestFilePath("created_file.csv"), GetTestFilePath("updated_file_1.csv"))
    97  
    98  	tx := TestTx
    99  
   100  	out := NewOutput()
   101  	tx.Session.SetStdout(out)
   102  
   103  	err := TestTx.Commit(context.Background(), NewReferenceScope(tx), parser.TransactionControl{Token: parser.COMMIT})
   104  	if err != nil {
   105  		t.Fatalf("unexpected error %q", err.Error())
   106  	}
   107  
   108  	log := out.String()
   109  
   110  	if log != expect {
   111  		t.Errorf("Commit: log = %q, want %q", log, expect)
   112  	}
   113  
   114  	expectedCreatedContents := "column1,column2\n"
   115  	createdContents, err := os.ReadFile(GetTestFilePath("created_file.csv"))
   116  	if err != nil {
   117  		t.Fatalf("unexpected error %q", err.Error())
   118  	}
   119  
   120  	if expectedCreatedContents != string(createdContents) {
   121  		t.Errorf("created contents = %q, want %q", string(createdContents), expectedCreatedContents)
   122  	}
   123  
   124  	expectedUpdatedContents := "column1,column2\n1,str1\nupdate1,update2\n3,str3\n"
   125  	updatedContents, err := os.ReadFile(GetTestFilePath("updated_file_1.csv"))
   126  	if err != nil {
   127  		t.Fatalf("unexpected error %q", err.Error())
   128  	}
   129  
   130  	if expectedUpdatedContents != string(updatedContents) {
   131  		t.Errorf("updated contents = %q, want %q", string(updatedContents), expectedUpdatedContents)
   132  	}
   133  
   134  	// Flags.StripEndingLineBreak = true
   135  	TestTx.Flags.ExportOptions.StripEndingLineBreak = true
   136  	ch, _ = TestTx.FileContainer.CreateHandlerForCreate(GetTestFilePath("created_file_1.csv"))
   137  	uh, _ = TestTx.FileContainer.CreateHandlerForUpdate(context.Background(), GetTestFilePath("updated_file_1.csv"), TestTx.WaitTimeout, TestTx.RetryDelay)
   138  	TestTx.CachedViews = GenerateViewMap([]*View{
   139  		{
   140  			Header:    NewHeader("created_file_1", []string{"column1", "column2"}),
   141  			RecordSet: RecordSet{},
   142  			FileInfo: &FileInfo{
   143  				Path:      GetTestFilePath("created_file_1.csv"),
   144  				Handler:   ch,
   145  				Encoding:  text.UTF8,
   146  				Format:    option.CSV,
   147  				Delimiter: ',',
   148  				LineBreak: text.LF,
   149  			},
   150  		},
   151  		{
   152  			Header: NewHeader("table1", []string{"column1", "column2"}),
   153  			RecordSet: []Record{
   154  				NewRecord([]value.Primary{
   155  					value.NewString("1"),
   156  					value.NewString("str1"),
   157  				}),
   158  				NewRecord([]value.Primary{
   159  					value.NewString("update1"),
   160  					value.NewString("update2"),
   161  				}),
   162  				NewRecord([]value.Primary{
   163  					value.NewString("3"),
   164  					value.NewString("str3"),
   165  				}),
   166  			},
   167  			FileInfo: &FileInfo{
   168  				Path:      GetTestFilePath("updated_file_1.csv"),
   169  				Handler:   uh,
   170  				Encoding:  text.UTF8,
   171  				Format:    option.CSV,
   172  				Delimiter: ',',
   173  				LineBreak: text.LF,
   174  			},
   175  		},
   176  	})
   177  
   178  	TestTx.UncommittedViews = UncommittedViews{
   179  		mtx: &sync.RWMutex{},
   180  		Created: map[string]*FileInfo{
   181  			strings.ToUpper(GetTestFilePath("created_file_1.csv")): {
   182  				Path:      GetTestFilePath("created_file_1.csv"),
   183  				Handler:   ch,
   184  				Encoding:  text.UTF8,
   185  				Format:    option.CSV,
   186  				Delimiter: ',',
   187  				LineBreak: text.LF,
   188  			},
   189  		},
   190  		Updated: map[string]*FileInfo{
   191  			strings.ToUpper(GetTestFilePath("updated_file_1.csv")): {
   192  				Path:      GetTestFilePath("updated_file_1.csv"),
   193  				Handler:   uh,
   194  				Encoding:  text.UTF8,
   195  				Format:    option.CSV,
   196  				Delimiter: ',',
   197  				LineBreak: text.LF,
   198  			},
   199  		},
   200  	}
   201  
   202  	err = TestTx.Commit(context.Background(), NewReferenceScope(tx), parser.TransactionControl{Token: parser.COMMIT})
   203  	if err != nil {
   204  		t.Fatalf("unexpected error %q", err.Error())
   205  	}
   206  
   207  	expectedCreatedContents = "column1,column2"
   208  	createdContents, err = os.ReadFile(GetTestFilePath("created_file_1.csv"))
   209  	if err != nil {
   210  		t.Fatalf("unexpected error %q", err.Error())
   211  	}
   212  
   213  	if expectedCreatedContents != string(createdContents) {
   214  		t.Errorf("created contents = %q, want %q", string(createdContents), expectedCreatedContents)
   215  	}
   216  
   217  	expectedUpdatedContents = "column1,column2\n1,str1\nupdate1,update2\n3,str3"
   218  	updatedContents, err = os.ReadFile(GetTestFilePath("updated_file_1.csv"))
   219  	if err != nil {
   220  		t.Fatalf("unexpected error %q", err.Error())
   221  	}
   222  
   223  	if expectedUpdatedContents != string(updatedContents) {
   224  		t.Errorf("updated contents = %q, want %q", string(updatedContents), expectedUpdatedContents)
   225  	}
   226  }
   227  
   228  func TestTransaction_Rollback(t *testing.T) {
   229  	defer func() {
   230  		_ = TestTx.ReleaseResources()
   231  		_ = TestTx.CachedViews.Clean(TestTx.FileContainer)
   232  		TestTx.Session.SetStdout(NewDiscard())
   233  		initFlag(TestTx.Flags)
   234  	}()
   235  
   236  	TestTx.Flags.SetQuiet(false)
   237  
   238  	TestTx.UncommittedViews = UncommittedViews{
   239  		mtx: &sync.RWMutex{},
   240  		Created: map[string]*FileInfo{
   241  			strings.ToUpper(GetTestFilePath("created_file.csv")): {
   242  				Path: GetTestFilePath("created_file.csv"),
   243  			},
   244  		},
   245  		Updated: map[string]*FileInfo{
   246  			strings.ToUpper(GetTestFilePath("updated_file_1.csv")): {
   247  				Path: GetTestFilePath("updated_file_1.csv"),
   248  			},
   249  		},
   250  	}
   251  
   252  	expect := fmt.Sprintf("Rollback: file %q is deleted.\nRollback: file %q is restored.\n", GetTestFilePath("created_file.csv"), GetTestFilePath("updated_file_1.csv"))
   253  
   254  	tx := TestTx
   255  
   256  	out := NewOutput()
   257  	tx.Session.SetStdout(out)
   258  
   259  	_ = TestTx.Rollback(NewReferenceScope(tx), nil)
   260  
   261  	log := out.String()
   262  
   263  	if log != expect {
   264  		t.Errorf("Rollback: log = %q, want %q", log, expect)
   265  	}
   266  }