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 }