1package libkb 2 3import ( 4 "os" 5 "path/filepath" 6 "sync" 7 "testing" 8 9 "github.com/stretchr/testify/require" 10) 11 12type JSONTestFile struct { 13 *JSONFile 14} 15 16type JSONTestReader interface { 17 JSONReader 18} 19type JSONTestWriter interface { 20 JSONWriter 21} 22 23func TestJsonTransaction(t *testing.T) { 24 tc := SetupTest(t, "json", 1) 25 defer tc.Cleanup() 26 27 var wg sync.WaitGroup 28 for i := 0; i < 20; i++ { 29 wg.Add(1) 30 go func() { 31 tx, err := tc.G.Env.GetConfigWriter().BeginTransaction() 32 if err == nil { 33 _ = tx.Abort() 34 } 35 wg.Done() 36 }() 37 } 38 for i := 0; i < 20; i++ { 39 wg.Add(1) 40 go func() { 41 tx, err := tc.G.Env.GetConfigWriter().BeginTransaction() 42 if err == nil { 43 _ = tx.Commit() 44 } 45 wg.Done() 46 }() 47 } 48 wg.Wait() 49} 50 51func buildNewJSONFile(m MetaContext) (JSONTestReader, JSONTestWriter, *JSONTestFile) { 52 path := filepath.Join(m.G().Env.GetConfigDir(), "test-json-file") 53 jsonFile := JSONTestFile{NewJSONFile(m.G(), path, "test file from buildNewJSONFile")} 54 _ = jsonFile.Load(false) 55 return &jsonFile, &jsonFile, &jsonFile 56} 57 58func TestJsonSetAndGetString(t *testing.T) { 59 tc := SetupTest(t, "json", 1) 60 defer tc.Cleanup() 61 m := NewMetaContextForTest(tc) 62 reader, writer, rawFile := buildNewJSONFile(m) 63 defer func() { _ = rawFile.Nuke() }() 64 65 //verify that the path is empty first 66 path := "america.montana.bozeman" 67 value := "The American Computer Museum" 68 firstRead, isRet := reader.GetStringAtPath(path) 69 require.False(tc.T, isRet) 70 require.Equal(tc.T, firstRead, "") 71 72 //set, get, inspect 73 err := writer.SetStringAtPath(path, value) 74 require.NoError(tc.T, err) 75 secondRead, isRet := reader.GetStringAtPath(path) 76 require.True(tc.T, isRet) 77 require.Equal(tc.T, secondRead, value) 78} 79 80func TestJsonSetAndGetInt(t *testing.T) { 81 tc := SetupTest(t, "json", 1) 82 defer tc.Cleanup() 83 m := NewMetaContextForTest(tc) 84 reader, writer, rawFile := buildNewJSONFile(m) 85 defer func() { _ = rawFile.Nuke() }() 86 87 //verify that the path is empty first 88 path := "candy.skittles.count" 89 value := 12 90 firstRead, isRet := reader.GetIntAtPath(path) 91 require.False(tc.T, isRet) 92 require.Equal(tc.T, firstRead, 0) 93 94 //set, get, inspect 95 err := writer.SetIntAtPath(path, value) 96 require.NoError(tc.T, err) 97 secondRead, isRet := reader.GetIntAtPath(path) 98 require.True(tc.T, isRet) 99 require.Equal(tc.T, secondRead, value) 100} 101 102func TestJsonSetAndGetBool(t *testing.T) { 103 tc := SetupTest(t, "json", 1) 104 defer tc.Cleanup() 105 m := NewMetaContextForTest(tc) 106 reader, writer, rawFile := buildNewJSONFile(m) 107 defer func() { _ = rawFile.Nuke() }() 108 109 //verify that the path is empty first 110 path := "colors.orange.appetizing" 111 value := true 112 firstRead, isRet := reader.GetBoolAtPath(path) 113 require.False(tc.T, isRet) 114 require.Equal(tc.T, firstRead, false) 115 116 //set, get, inspect 117 err := writer.SetBoolAtPath(path, value) 118 require.NoError(tc.T, err) 119 secondRead, isRet := reader.GetBoolAtPath(path) 120 require.True(tc.T, isRet) 121 require.True(tc.T, secondRead) 122} 123 124func TestJsonSetAndGetNull(t *testing.T) { 125 tc := SetupTest(t, "json", 1) 126 defer tc.Cleanup() 127 m := NewMetaContextForTest(tc) 128 reader, writer, rawFile := buildNewJSONFile(m) 129 defer func() { _ = rawFile.Nuke() }() 130 131 //verify that the path is empty first 132 //and that GetNull knows the path wasn't set 133 path := "worldcup.victories.croatia" 134 value := 2018 135 isRet := reader.GetNullAtPath(path) 136 require.False(tc.T, isRet) 137 138 //set, get, inspect 139 _ = writer.SetIntAtPath(path, value) 140 secondRead, _ := reader.GetIntAtPath(path) 141 require.Equal(tc.T, secondRead, value) 142 // null it out and verify 143 err := writer.SetNullAtPath(path) 144 require.NoError(tc.T, err) 145 isRet = reader.GetNullAtPath(path) 146 require.True(tc.T, isRet) 147} 148 149func TestJsonTxRollback(t *testing.T) { 150 tc := SetupTest(t, "json", 1) 151 defer tc.Cleanup() 152 m := NewMetaContextForTest(tc) 153 G := m.G() 154 155 // Make a tx, write something, then commit. Expecting to be able 156 // to read that back during the transaction and after commit. 157 w := G.Env.GetConfigWriter() 158 tx, err := w.BeginTransaction() 159 require.NoError(t, err) 160 require.NoError(t, w.SetStringAtPath("bbbbar", "world, over?")) 161 i, err := G.Env.GetConfig().GetInterfaceAtPath("bbbbar") 162 require.NoError(t, err) 163 require.Equal(t, "world, over?", i) 164 require.NoError(t, tx.Commit()) 165 i, err = G.Env.GetConfig().GetInterfaceAtPath("bbbbar") 166 require.NoError(t, err) 167 require.Equal(t, "world, over?", i) 168 169 // Make a tx, write something, then Rollback and Abort. It should 170 // be as the write never happened. 171 w = G.Env.GetConfigWriter() 172 tx, err = w.BeginTransaction() 173 require.NoError(t, err) 174 require.NoError(t, w.SetStringAtPath("fooozzzz", "hello World")) 175 i, err = G.Env.GetConfig().GetInterfaceAtPath("fooozzzz") 176 require.NoError(t, err) 177 require.Equal(t, "hello World", i) 178 require.NoError(t, tx.Rollback()) 179 require.NoError(t, tx.Abort()) 180 _, err = G.Env.GetConfig().GetInterfaceAtPath("fooozzzz") 181 require.Error(t, err) 182 require.Contains(t, err.Error(), "no such key") 183 i, err = G.Env.GetConfig().GetInterfaceAtPath("bbbbar") 184 require.NoError(t, err) 185 require.Equal(t, "world, over?", i) 186} 187 188func TestJsonNonExistingFileRollback(t *testing.T) { 189 tc := SetupTest(t, "json", 1) 190 defer tc.Cleanup() 191 m := NewMetaContextForTest(tc) 192 reader, writer, rawFile := buildNewJSONFile(m) 193 defer func() { _ = rawFile.Nuke() }() 194 195 tx, err := rawFile.BeginTransaction() 196 require.NoError(t, err) 197 require.NoError(t, writer.SetStringAtPath("test1", "this is value 1")) 198 require.NoError(t, writer.SetIntAtPath("test two", 2)) 199 200 i, err := reader.GetInterfaceAtPath("test1") 201 require.NoError(t, err) 202 require.Equal(t, "this is value 1", i) 203 204 i, err = reader.GetInterfaceAtPath("test two") 205 require.NoError(t, err) 206 require.Equal(t, 2, i) 207 208 require.NoError(t, tx.Rollback()) 209 require.NoError(t, tx.Abort()) 210 211 _, err = os.Stat(rawFile.filename) 212 require.Error(t, err) 213 require.True(t, os.IsNotExist(err)) 214 215 _, err = reader.GetInterfaceAtPath("test1") 216 require.Error(t, err) 217 require.Contains(t, err.Error(), "no such key") 218 219 _, err = reader.GetInterfaceAtPath("test two") 220 require.Error(t, err) 221 require.Contains(t, err.Error(), "no such key") 222} 223