go.mercari.io/datastore@v1.8.2/dsmiddleware/fishbone/fishbone_test.go (about) 1 package fishbone 2 3 import ( 4 "context" 5 "fmt" 6 "strings" 7 "testing" 8 9 "github.com/MakeNowJust/heredoc/v2" 10 "go.mercari.io/datastore" 11 "go.mercari.io/datastore/dsmiddleware/dslog" 12 "go.mercari.io/datastore/internal/testutils" 13 "google.golang.org/api/iterator" 14 ) 15 16 func TestFishBone_QueryWithoutTx(t *testing.T) { 17 ctx, client, cleanUp := testutils.SetupCloudDatastore(t) 18 defer cleanUp() 19 20 var logs []string 21 logf := func(ctx context.Context, format string, args ...interface{}) { 22 t.Logf(format, args...) 23 logs = append(logs, fmt.Sprintf(format, args...)) 24 } 25 26 // setup. strategies are first in - first apply. 27 28 bLog := dslog.NewLogger("before: ", logf) 29 client.AppendMiddleware(bLog) 30 defer func() { 31 // stop logging before cleanUp func called. 32 client.RemoveMiddleware(bLog) 33 }() 34 35 m := New() 36 client.AppendMiddleware(m) 37 defer func() { 38 // stop logging before cleanUp func called. 39 client.RemoveMiddleware(m) 40 }() 41 42 aLog := dslog.NewLogger("after: ", logf) 43 client.AppendMiddleware(aLog) 44 defer func() { 45 // stop logging before cleanUp func called. 46 client.RemoveMiddleware(aLog) 47 }() 48 49 // exec. 50 51 type Data struct { 52 Name string 53 } 54 55 const size = 3 56 57 keys := make([]datastore.Key, size) 58 list := make([]*Data, size) 59 for i := 0; i < size; i++ { 60 keys[i] = client.NameKey("Data", fmt.Sprintf("#%d", i+1), nil) 61 list[i] = &Data{ 62 Name: fmt.Sprintf("#%d", i+1), 63 } 64 } 65 _, err := client.PutMulti(ctx, keys, list) 66 if err != nil { 67 t.Fatal(err) 68 } 69 70 q := client.NewQuery("Data").Order("-Name") 71 72 // Run 73 iter := client.Run(ctx, q) 74 75 // Next 76 cnt := 0 77 for { 78 obj := &Data{} 79 key, err := iter.Next(obj) 80 if err == iterator.Done { 81 break 82 } else if err != nil { 83 t.Fatal(err) 84 } 85 if v := obj.Name; v == "" || v != key.Name() { 86 t.Errorf("unexpected: %v", cnt) 87 } 88 cnt++ 89 } 90 if cnt != size { 91 t.Errorf("unexpected: %v", cnt) 92 } 93 94 // GetAll 95 q = client.NewQuery("Data").Order("-Name") 96 list = nil 97 keys, err = client.GetAll(ctx, q, &list) 98 if err != nil { 99 t.Fatal(err) 100 } 101 if v := len(list); v != size { 102 t.Errorf("unexpected: %v", v) 103 } 104 for idx, obj := range list { 105 if v := obj.Name; v == "" || v != keys[idx].Name() { 106 t.Errorf("unexpected: %v", v) 107 } 108 } 109 110 expected := heredoc.Doc(` 111 before: PutMultiWithoutTx #1, len(keys)=3, keys=[/Data,#1, /Data,#2, /Data,#3] 112 after: PutMultiWithoutTx #1, len(keys)=3, keys=[/Data,#1, /Data,#2, /Data,#3] 113 after: PutMultiWithoutTx #1, keys=[/Data,#1, /Data,#2, /Data,#3] 114 before: PutMultiWithoutTx #1, keys=[/Data,#1, /Data,#2, /Data,#3] 115 before: Run #2, q=v1:Data&or=-Name 116 after: Run #2, q=v1:Data&or=-Name&k=t 117 before: Next #3, q=v1:Data&or=-Name 118 after: Next #3, q=v1:Data&or=-Name 119 after: Next #3, key=/Data,#3 120 before: GetMultiWithoutTx #4, len(keys)=1, keys=[/Data,#3] 121 after: GetMultiWithoutTx #4, len(keys)=1, keys=[/Data,#3] 122 before: Next #3, key=/Data,#3 123 before: Next #5, q=v1:Data&or=-Name 124 after: Next #5, q=v1:Data&or=-Name 125 after: Next #5, key=/Data,#2 126 before: GetMultiWithoutTx #6, len(keys)=1, keys=[/Data,#2] 127 after: GetMultiWithoutTx #6, len(keys)=1, keys=[/Data,#2] 128 before: Next #5, key=/Data,#2 129 before: Next #7, q=v1:Data&or=-Name 130 after: Next #7, q=v1:Data&or=-Name 131 after: Next #7, key=/Data,#1 132 before: GetMultiWithoutTx #8, len(keys)=1, keys=[/Data,#1] 133 after: GetMultiWithoutTx #8, len(keys)=1, keys=[/Data,#1] 134 before: Next #7, key=/Data,#1 135 before: Next #9, q=v1:Data&or=-Name 136 after: Next #9, q=v1:Data&or=-Name 137 after: Next #9, err=no more items in iterator 138 before: Next #9, err=no more items in iterator 139 before: GetAll #10, q=v1:Data&or=-Name 140 after: GetAll #10, q=v1:Data&or=-Name&k=t 141 after: GetAll #10, len(keys)=3, keys=[/Data,#3, /Data,#2, /Data,#1] 142 before: GetMultiWithoutTx #11, len(keys)=3, keys=[/Data,#3, /Data,#2, /Data,#1] 143 after: GetMultiWithoutTx #11, len(keys)=3, keys=[/Data,#3, /Data,#2, /Data,#1] 144 before: GetAll #10, len(keys)=3, keys=[/Data,#3, /Data,#2, /Data,#1] 145 `) 146 147 if v := strings.Join(logs, "\n") + "\n"; v != expected { 148 t.Errorf("unexpected: %v", v) 149 } 150 } 151 152 func TestFishBone_QueryWithTx(t *testing.T) { 153 ctx, client, cleanUp := testutils.SetupCloudDatastore(t) 154 defer cleanUp() 155 156 var logs []string 157 logf := func(ctx context.Context, format string, args ...interface{}) { 158 t.Logf(format, args...) 159 logs = append(logs, fmt.Sprintf(format, args...)) 160 } 161 162 // setup. strategies are first in - first apply. 163 164 bLog := dslog.NewLogger("before: ", logf) 165 client.AppendMiddleware(bLog) 166 defer func() { 167 // stop logging before cleanUp func called. 168 client.RemoveMiddleware(bLog) 169 }() 170 171 m := New() 172 client.AppendMiddleware(m) 173 defer func() { 174 // stop logging before cleanUp func called. 175 client.RemoveMiddleware(m) 176 }() 177 178 aLog := dslog.NewLogger("after: ", logf) 179 client.AppendMiddleware(aLog) 180 defer func() { 181 // stop logging before cleanUp func called. 182 client.RemoveMiddleware(aLog) 183 }() 184 185 // exec. 186 187 type Data struct { 188 Name string 189 } 190 191 const size = 3 192 193 parentKey := client.NameKey("Parent", "p", nil) 194 keys := make([]datastore.Key, size) 195 list := make([]*Data, size) 196 for i := 0; i < size; i++ { 197 keys[i] = client.NameKey("Data", fmt.Sprintf("#%d", i+1), parentKey) 198 list[i] = &Data{ 199 Name: fmt.Sprintf("#%d", i+1), 200 } 201 } 202 _, err := client.PutMulti(ctx, keys, list) 203 if err != nil { 204 t.Fatal(err) 205 } 206 207 tx, err := client.NewTransaction(ctx) 208 if err != nil { 209 t.Fatal(err) 210 } 211 defer func() { 212 err := tx.Rollback() 213 if err != nil { 214 t.Fatal(err) 215 } 216 }() 217 218 q := client.NewQuery("Data").Order("-Name").Ancestor(parentKey).Transaction(tx) 219 220 // Run 221 iter := client.Run(ctx, q) 222 223 // Next 224 cnt := 0 225 for { 226 obj := &Data{} 227 key, err := iter.Next(obj) 228 if err == iterator.Done { 229 break 230 } else if err != nil { 231 t.Fatal(err) 232 } 233 if v := obj.Name; v == "" || v != key.Name() { 234 t.Errorf("unexpected: %v", cnt) 235 } 236 cnt++ 237 } 238 if cnt != size { 239 t.Errorf("unexpected: %v", cnt) 240 } 241 242 // GetAll 243 q = client.NewQuery("Data").Order("-Name").Ancestor(parentKey).Transaction(tx) 244 list = nil 245 keys, err = client.GetAll(ctx, q, &list) 246 if err != nil { 247 t.Fatal(err) 248 } 249 if v := len(list); v != size { 250 t.Errorf("unexpected: %v", v) 251 } 252 for idx, obj := range list { 253 if v := obj.Name; v == "" || v != keys[idx].Name() { 254 t.Errorf("unexpected: %v", v) 255 } 256 } 257 258 expected := heredoc.Doc(` 259 before: PutMultiWithoutTx #1, len(keys)=3, keys=[/Parent,p/Data,#1, /Parent,p/Data,#2, /Parent,p/Data,#3] 260 after: PutMultiWithoutTx #1, len(keys)=3, keys=[/Parent,p/Data,#1, /Parent,p/Data,#2, /Parent,p/Data,#3] 261 after: PutMultiWithoutTx #1, keys=[/Parent,p/Data,#1, /Parent,p/Data,#2, /Parent,p/Data,#3] 262 before: PutMultiWithoutTx #1, keys=[/Parent,p/Data,#1, /Parent,p/Data,#2, /Parent,p/Data,#3] 263 before: Run #2, q=v1:Data&a=/Parent,p&t=t&or=-Name 264 after: Run #2, q=v1:Data&a=/Parent,p&t=t&or=-Name&k=t 265 before: Next #3, q=v1:Data&a=/Parent,p&t=t&or=-Name 266 after: Next #3, q=v1:Data&a=/Parent,p&t=t&or=-Name 267 after: Next #3, key=/Parent,p/Data,#3 268 before: GetMultiWithTx #4, len(keys)=1, keys=[/Parent,p/Data,#3] 269 after: GetMultiWithTx #4, len(keys)=1, keys=[/Parent,p/Data,#3] 270 before: Next #3, key=/Parent,p/Data,#3 271 before: Next #5, q=v1:Data&a=/Parent,p&t=t&or=-Name 272 after: Next #5, q=v1:Data&a=/Parent,p&t=t&or=-Name 273 after: Next #5, key=/Parent,p/Data,#2 274 before: GetMultiWithTx #6, len(keys)=1, keys=[/Parent,p/Data,#2] 275 after: GetMultiWithTx #6, len(keys)=1, keys=[/Parent,p/Data,#2] 276 before: Next #5, key=/Parent,p/Data,#2 277 before: Next #7, q=v1:Data&a=/Parent,p&t=t&or=-Name 278 after: Next #7, q=v1:Data&a=/Parent,p&t=t&or=-Name 279 after: Next #7, key=/Parent,p/Data,#1 280 before: GetMultiWithTx #8, len(keys)=1, keys=[/Parent,p/Data,#1] 281 after: GetMultiWithTx #8, len(keys)=1, keys=[/Parent,p/Data,#1] 282 before: Next #7, key=/Parent,p/Data,#1 283 before: Next #9, q=v1:Data&a=/Parent,p&t=t&or=-Name 284 after: Next #9, q=v1:Data&a=/Parent,p&t=t&or=-Name 285 after: Next #9, err=no more items in iterator 286 before: Next #9, err=no more items in iterator 287 before: GetAll #10, q=v1:Data&a=/Parent,p&t=t&or=-Name 288 after: GetAll #10, q=v1:Data&a=/Parent,p&t=t&or=-Name&k=t 289 after: GetAll #10, len(keys)=3, keys=[/Parent,p/Data,#3, /Parent,p/Data,#2, /Parent,p/Data,#1] 290 before: GetMultiWithTx #11, len(keys)=3, keys=[/Parent,p/Data,#3, /Parent,p/Data,#2, /Parent,p/Data,#1] 291 after: GetMultiWithTx #11, len(keys)=3, keys=[/Parent,p/Data,#3, /Parent,p/Data,#2, /Parent,p/Data,#1] 292 before: GetAll #10, len(keys)=3, keys=[/Parent,p/Data,#3, /Parent,p/Data,#2, /Parent,p/Data,#1] 293 `) 294 295 if v := strings.Join(logs, "\n") + "\n"; v != expected { 296 t.Errorf("unexpected: %v", v) 297 } 298 }