diff --git a/contrib/integration/bank/.gitignore b/contrib/integration/bank/.gitignore deleted file mode 100644 index d282090a0..000000000 --- a/contrib/integration/bank/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/bank diff --git a/contrib/integration/bank/Dockerfile b/contrib/integration/bank/Dockerfile deleted file mode 100644 index dae443ce7..000000000 --- a/contrib/integration/bank/Dockerfile +++ /dev/null @@ -1,3 +0,0 @@ -FROM gcr.io/distroless/base -COPY ./bank / -CMD ["/bank"] diff --git a/contrib/integration/bank/Makefile b/contrib/integration/bank/Makefile deleted file mode 100644 index db2b7d589..000000000 --- a/contrib/integration/bank/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -.PHONY: build - -DOCKER_REPO ?= dgraph - -build: - go build -o bank - docker build -t $(DOCKER_REPO)/bank:latest . diff --git a/contrib/integration/bank/main.go b/contrib/integration/bank/main.go deleted file mode 100644 index c4d6cda05..000000000 --- a/contrib/integration/bank/main.go +++ /dev/null @@ -1,387 +0,0 @@ -/* - * Copyright 2017-2018 Dgraph Labs, Inc. and Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package main - -import ( - "bufio" - "bytes" - "context" - "crypto/tls" - "crypto/x509" - "encoding/json" - "flag" - "fmt" - "log" - "math/rand" - "net/http" - _ "net/http/pprof" // http profiler - "sort" - "strings" - "sync" - "sync/atomic" - "time" - - "github.com/outcaste-io/dgo/v210" - "github.com/outcaste-io/dgo/v210/protos/api" - "github.com/outcaste-io/outserv/x" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials" -) - -var ( - users = flag.Int("users", 100, "Number of accounts.") - conc = flag.Int("txns", 3, "Number of concurrent transactions per client.") - queryCheck = flag.Int("check_every", 5, "Check total accounts and balances after every N mutations.") - dur = flag.String("dur", "1m", "How long to run the transactions.") - alpha = flag.String("alpha", "localhost:9080", "Address of Dgraph alpha.") - verbose = flag.Bool("verbose", true, "Output all logs in verbose mode.") - login = flag.Bool("login", true, "Login as groot. Used for ACL-enabled cluster.") - slashToken = flag.String("slash-token", "", "Slash GraphQL API token") - debugHttp = flag.String("http", "localhost:6060", - "Address to serve http (pprof).") -) - -var startBal = 10 - -type account struct { - Uid string `json:"uid"` - Key int `json:"key,omitempty"` - Bal int `json:"bal,omitempty"` - Typ string `json:"typ"` -} - -type state struct { - aborts int32 - runs int32 -} - -func (s *state) createAccounts(dg *dgo.Dgraph) { - op := api.Operation{DropAll: true} - x.Check(dg.Alter(context.Background(), &op)) - - op.DropAll = false - op.Schema = ` - key: int @index(int) @upsert . - bal: int . - typ: string @index(exact) @upsert . - ` - x.Check(dg.Alter(context.Background(), &op)) - - var all []account - for i := 1; i <= *users; i++ { - a := account{ - Key: i, - Bal: startBal, - Typ: "ba", - } - all = append(all, a) - } - data, err := json.Marshal(all) - x.Check(err) - - txn := dg.NewTxn() - defer func() { - if err := txn.Discard(context.Background()); err != nil { - log.Fatalf("Discarding transaction failed: %+v\n", err) - } - }() - - var mu api.Mutation - mu.SetJson = data - resp, err := txn.Mutate(context.Background(), &mu) - if *verbose { - if resp.Txn == nil { - log.Printf("[resp.Txn: %+v] Mutation: %s\n", resp.Txn, mu.SetJson) - } else { - log.Printf("[StartTs: %v] Mutation: %s\n", resp.Txn.StartTs, mu.SetJson) - } - } - x.Check(err) - x.Check(txn.Commit(context.Background())) -} - -func (s *state) runTotal(dg *dgo.Dgraph) error { - query := ` - { - q(func: eq(typ, "ba")) { - uid - key - bal - } - } - ` - txn := dg.NewReadOnlyTxn() - defer func() { - if err := txn.Discard(context.Background()); err != nil { - log.Fatalf("Discarding transaction failed: %+v\n", err) - } - }() - - resp, err := txn.Query(context.Background(), query) - if err != nil { - return err - } - - m := make(map[string][]account) - if err := json.Unmarshal(resp.Json, &m); err != nil { - return err - } - accounts := m["q"] - sort.Slice(accounts, func(i, j int) bool { - return accounts[i].Key < accounts[j].Key - }) - var total int - for _, a := range accounts { - total += a.Bal - } - if *verbose { - log.Printf("[StartTs: %v] Read: %v. Total: %d\n", resp.Txn.StartTs, accounts, total) - } - if len(accounts) > *users { - log.Fatalf("len(accounts) = %d", len(accounts)) - } - if total != *users*startBal { - log.Fatalf("Total = %d", total) - } - return nil -} - -func (s *state) findAccount(txn *dgo.Txn, key int) (account, error) { - query := fmt.Sprintf(`{ q(func: eq(key, %d)) { key, uid, bal, typ }}`, key) - resp, err := txn.Query(context.Background(), query) - if err != nil { - return account{}, err - } - m := make(map[string][]account) - if err := json.Unmarshal(resp.Json, &m); err != nil { - log.Fatal(err) - } - accounts := m["q"] - if len(accounts) > 1 { - log.Printf("[StartTs: %v] Query: %s. Response: %s\n", resp.Txn.StartTs, query, resp.Json) - log.Fatal("Found multiple accounts") - } - if len(accounts) == 0 { - if *verbose { - log.Printf("[StartTs: %v] Unable to find account for K_%02d. JSON: %s\n", resp.Txn.StartTs, key, resp.Json) - } - return account{Key: key, Typ: "ba"}, nil - } - return accounts[0], nil -} - -func (s *state) runTransaction(dg *dgo.Dgraph, buf *bytes.Buffer) error { - w := bufio.NewWriter(buf) - fmt.Fprintf(w, "==>\n") - defer func() { - fmt.Fprintf(w, "---\n") - _ = w.Flush() - }() - - ctx := context.Background() - txn := dg.NewTxn() - defer func() { - if err := txn.Discard(context.Background()); err != nil { - log.Fatalf("Discarding transaction failed: %+v\n", err) - } - }() - - var sk, sd int - for { - sk = rand.Intn(*users + 1) - sd = rand.Intn(*users + 1) - if sk == 0 || sd == 0 { // Don't touch zero. - continue - } - if sk != sd { - break - } - } - - src, err := s.findAccount(txn, sk) - if err != nil { - return err - } - dst, err := s.findAccount(txn, sd) - if err != nil { - return err - } - if src.Key == dst.Key { - return nil - } - - amount := rand.Intn(10) - if src.Bal-amount <= 0 { - amount = src.Bal - } - fmt.Fprintf(w, "Moving [$%d, K_%02d -> K_%02d]. Src:%+v. Dst: %+v\n", - amount, src.Key, dst.Key, src, dst) - src.Bal -= amount - dst.Bal += amount - var mu api.Mutation - if len(src.Uid) > 0 { - // If there was no src.Uid, then don't run any mutation. - if src.Bal == 0 { - pb, err := json.Marshal(src) - x.Check(err) - mu.DeleteJson = pb - fmt.Fprintf(w, "Deleting K_%02d: %s\n", src.Key, mu.DeleteJson) - } else { - data, err := json.Marshal(src) - x.Check(err) - mu.SetJson = data - } - _, err := txn.Mutate(ctx, &mu) - if err != nil { - fmt.Fprintf(w, "Error while mutate: %v", err) - return err - } - } - - mu = api.Mutation{} - data, err := json.Marshal(dst) - x.Check(err) - mu.SetJson = data - assigned, err := txn.Mutate(ctx, &mu) - if err != nil { - fmt.Fprintf(w, "Error while mutate: %v", err) - return err - } - - if err := txn.Commit(ctx); err != nil { - return err - } - if len(assigned.GetUids()) > 0 { - fmt.Fprintf(w, "[StartTs: %v] CREATED K_%02d: %+v for %+v\n", assigned.Txn.StartTs, dst.Key, assigned.GetUids(), dst) - for _, uid := range assigned.GetUids() { - dst.Uid = uid - } - } - fmt.Fprintf(w, "[StartTs: %v] MOVED [$%d, K_%02d -> K_%02d]. Src:%+v. Dst: %+v\n", - assigned.Txn.StartTs, amount, src.Key, dst.Key, src, dst) - return nil -} - -func (s *state) loop(dg *dgo.Dgraph, wg *sync.WaitGroup) { - defer wg.Done() - dur, err := time.ParseDuration(*dur) - if err != nil { - log.Fatal(err) - } - end := time.Now().Add(dur) - - var buf bytes.Buffer - for i := 0; ; i++ { - if i%*queryCheck == 0 { - if err := s.runTotal(dg); err != nil { - log.Printf("Error while runTotal: %v", err) - } - } - - buf.Reset() - err := s.runTransaction(dg, &buf) - if *verbose { - log.Printf("Final error: %v. %s", err, buf.String()) - } - if err != nil { - atomic.AddInt32(&s.aborts, 1) - } else { - r := atomic.AddInt32(&s.runs, 1) - if r%100 == 0 { - a := atomic.LoadInt32(&s.aborts) - fmt.Printf("Runs: %d. Aborts: %d\n", r, a) - } - if time.Now().After(end) { - return - } - } - } -} - -type authorizationCredentials struct { - token string -} - -func (a *authorizationCredentials) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { - return map[string]string{"Authorization": a.token}, nil -} - -func (a *authorizationCredentials) RequireTransportSecurity() bool { - return true -} - -func grpcConnection(one string) (*grpc.ClientConn, error) { - if slashToken == nil || *slashToken == "" { - return grpc.Dial(one, grpc.WithInsecure()) - } - pool, err := x509.SystemCertPool() - if err != nil { - return nil, err - } - return grpc.Dial( - one, - grpc.WithTransportCredentials(credentials.NewTLS(&tls.Config{ - RootCAs: pool, - ServerName: strings.Split(one, ":")[0], - })), - grpc.WithPerRPCCredentials(&authorizationCredentials{*slashToken}), - ) -} - -func main() { - flag.Parse() - go func() { - log.Printf("Listening for /debug HTTP requests at address: %v\n", *debugHttp) - log.Fatal(http.ListenAndServe(*debugHttp, nil)) - }() - - all := strings.Split(*alpha, ",") - x.AssertTrue(len(all) > 0) - - var clients []*dgo.Dgraph - for _, one := range all { - conn, err := grpcConnection(one) - if err != nil { - log.Fatal(err) - } - dc := api.NewDgraphClient(conn) - dg := dgo.NewDgraphClient(dc) - if *login { - // login as groot to perform the DropAll operation later - x.Check(dg.Login(context.Background(), "groot", "password")) - } - clients = append(clients, dg) - } - - s := state{} - s.createAccounts(clients[0]) - - var wg sync.WaitGroup - for i := 0; i < *conc; i++ { - for _, dg := range clients { - wg.Add(1) - go s.loop(dg, &wg) - } - } - wg.Wait() - fmt.Println() - fmt.Println("Total aborts", s.aborts) - fmt.Println("Total success", s.runs) - if err := s.runTotal(clients[0]); err != nil { - log.Fatal(err) - } -} diff --git a/contrib/integration/bigdata/main.go b/contrib/integration/bigdata/main.go deleted file mode 100644 index 4c91bf962..000000000 --- a/contrib/integration/bigdata/main.go +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright 2018 Dgraph Labs, Inc. and Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package main - -import ( - "context" - "encoding/json" - "flag" - "fmt" - "math/rand" - "net/url" - "os" - "strings" - "sync/atomic" - "time" - - "github.com/outcaste-io/dgo/v210" - "github.com/outcaste-io/dgo/v210/protos/api" - "github.com/outcaste-io/outserv/x" - "google.golang.org/grpc" -) - -var addrs = flag.String("addrs", "", "comma separated dgraph addresses") -var mode = flag.String("mode", "", "mode to run in ('mutate' or 'query')") -var conc = flag.Int("j", 1, "number of operations to run in parallel") - -func init() { - rand.Seed(time.Now().Unix()) -} - -var ctx = context.Background() - -func main() { - flag.Parse() - c := makeClient() - - // Install the schema automatically on the first run. This allows the same - // command to be used when running this program for the first and - // subsequent times. We guess if it's the first run based on the number of - // schema items. - resp, err := c.NewTxn().Query(ctx, "schema {}") - x.Check(err) - if len(resp.Json) < 5 { - // Run each schema alter separately so that there is an even - // distribution among all groups. - for _, s := range schema() { - x.Check(c.Alter(ctx, &api.Operation{ - Schema: s, - })) - } - x.Check2(c.NewTxn().Mutate(ctx, &api.Mutation{ - CommitNow: true, - SetNquads: []byte(initialData()), - })) - } - - switch *mode { - case "mutate": - var errCount int64 - var mutateCount int64 - for i := 0; i < *conc; i++ { - go func() { - for { - err := mutate(c) - if err == nil { - atomic.AddInt64(&mutateCount, 1) - } else { - atomic.AddInt64(&errCount, 1) - } - } - }() - } - for { - time.Sleep(time.Second) - fmt.Printf("Status: success_mutations=%d errors=%d\n", - atomic.LoadInt64(&mutateCount), atomic.LoadInt64(&errCount)) - } - case "query": - var errCount int64 - var queryCount int64 - for i := 0; i < *conc; i++ { - go func() { - for { - err := showNode(c) - if err == nil { - atomic.AddInt64(&queryCount, 1) - } else { - atomic.AddInt64(&errCount, 1) - } - } - }() - } - for { - time.Sleep(time.Second) - fmt.Printf("Status: success_queries=%d errors=%d\n", - atomic.LoadInt64(&queryCount), atomic.LoadInt64(&errCount)) - } - default: - fmt.Printf("unknown mode: %q\n", *mode) - os.Exit(1) - } -} - -func schema() []string { - s := []string{"xid: string @index(exact) .\n"} - for char := 'a'; char <= 'z'; char++ { - s = append(s, fmt.Sprintf("count_%c: int .\n", char)) - } - for char := 'a'; char <= 'z'; char++ { - s = append(s, fmt.Sprintf("attr_%c: string .\n", char)) - } - return s -} - -func initialData() string { - rdfs := "_:root \"root\" .\n" - for char := 'a'; char <= 'z'; char++ { - rdfs += fmt.Sprintf("_:root \"0\" .\n", char) - } - return rdfs -} - -func makeClient() *dgo.Dgraph { - var dgcs []api.DgraphClient - for _, addr := range strings.Split(*addrs, ",") { - c, err := grpc.Dial(addr, grpc.WithInsecure()) - x.Check(err) - dgcs = append(dgcs, api.NewDgraphClient(c)) - } - return dgo.NewDgraphClient(dgcs...) -} - -type runner struct { - txn *dgo.Txn -} - -func mutate(c *dgo.Dgraph) error { - r := &runner{ - txn: c.NewTxn(), - } - defer func() { _ = r.txn.Discard(ctx) }() - - char := 'a' + rune(rand.Intn(26)) - - var result struct { - Q []struct { - Uid *string - Count *int - } - } - if err := r.query(&result, ` - { - q(func: eq(xid, "root")) { - uid - count: count_%c - } - } - `, char); err != nil { - return err - } - - x.AssertTrue(len(result.Q) > 0 && result.Q[0].Count != nil && result.Q[0].Uid != nil) - - if _, err := r.txn.Mutate(ctx, &api.Mutation{ - SetNquads: []byte(fmt.Sprintf("<%s> \"%d\" .\n", - *result.Q[0].Uid, char, *result.Q[0].Count+1)), - }); err != nil { - return err - } - - rdfs := fmt.Sprintf("_:node \"%c_%d\" .\n", char, *result.Q[0].Count) - for char := 'a'; char <= 'z'; char++ { - if rand.Float64() < 0.9 { - continue - } - payload := make([]byte, 16+rand.Intn(16)) - if _, err := rand.Read(payload); err != nil { - return err - } - rdfs += fmt.Sprintf("_:node \"%s\" .\n", char, url.QueryEscape(string(payload))) - } - if _, err := r.txn.Mutate(ctx, &api.Mutation{ - SetNquads: []byte(rdfs), - }); err != nil { - return err - } - - return r.txn.Commit(ctx) -} - -func showNode(c *dgo.Dgraph) error { - r := &runner{ - txn: c.NewTxn(), - } - defer func() { _ = r.txn.Discard(ctx) }() - - char := 'a' + rune(rand.Intn(26)) - var result struct { - Q []struct { - Count *int - } - } - - q := fmt.Sprintf(` - { - q(func: eq(xid, "root")) { - uid - count: count_%c - } - } - `, char) - resp, err := r.txn.Query(ctx, q) - if err != nil { - return err - } - if err := json.Unmarshal(resp.Json, &result); err != nil { - return err - } - x.AssertTruef(len(result.Q) > 0 && result.Q[0].Count != nil, "%v %+v", string(resp.Json), result) - - var m map[string]interface{} - return r.query(&m, ` - { - q(func: eq(xid, "%c_%d")) { - expand(_all_) - } - } - `, char, rand.Intn(*result.Q[0].Count)) -} - -func (r *runner) query(out interface{}, q string, args ...interface{}) error { - q = fmt.Sprintf(q, args...) - resp, err := r.txn.Query(ctx, q) - if err != nil { - return err - } - return json.Unmarshal(resp.Json, out) -} diff --git a/contrib/integration/mutates/.gitignore b/contrib/integration/mutates/.gitignore deleted file mode 100644 index 9b86bcbdc..000000000 --- a/contrib/integration/mutates/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/mutates diff --git a/contrib/integration/mutates/main.go b/contrib/integration/mutates/main.go deleted file mode 100644 index ee64f4f90..000000000 --- a/contrib/integration/mutates/main.go +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2017-2018 Dgraph Labs, Inc. and Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package main - -import ( - "bytes" - "context" - "flag" - "fmt" - "log" - - "github.com/outcaste-io/dgo/v210" - "github.com/outcaste-io/dgo/v210/protos/api" - "github.com/outcaste-io/outserv/x" - "google.golang.org/grpc" -) - -var alpha = flag.String("alpha", "localhost:9080", "Dgraph alpha addr") -var insert = flag.Bool("add", false, "Insert") - -func main() { - flag.Parse() - - // Setup dgraph client - ctx := context.Background() - conn, err := grpc.Dial(*alpha, grpc.WithInsecure()) - if err != nil { - log.Fatal(err) - } - pc := api.NewDgraphClient(conn) - c := dgo.NewDgraphClient(pc) - err = c.Login(ctx, "groot", "password") - x.Check(err) - - // Ingest - if *insert { - testInsert3Quads(ctx, c) - } else { - testQuery3Quads(ctx, c) - } -} - -func testInsert3Quads(ctx context.Context, c *dgo.Dgraph) { - // Set schema - op := &api.Operation{} - op.Schema = `name: string @index(fulltext) .` - x.Check(c.Alter(ctx, op)) - - txn := c.NewTxn() - - mu := &api.Mutation{} - quad := &api.NQuad{ - Subject: "200", - Predicate: "name", - ObjectValue: &api.Value{Val: &api.Value_StrVal{StrVal: "ok 200"}}, - } - mu.Set = []*api.NQuad{quad} - _, err := txn.Mutate(ctx, mu) - if err != nil { - log.Fatalf("Error while running mutation: %v\n", err) - } - - mu = &api.Mutation{} - quad = &api.NQuad{ - Subject: "300", - Predicate: "name", - ObjectValue: &api.Value{Val: &api.Value_StrVal{StrVal: "ok 300"}}, - } - mu.Set = []*api.NQuad{quad} - // mu.SetNquads = []byte(`<300> "ok 300" .`) - _, err = txn.Mutate(ctx, mu) - if err != nil { - log.Fatalf("Error while running mutation: %v\n", err) - } - - mu = &api.Mutation{} - quad = &api.NQuad{ - Subject: "400", - Predicate: "name", - ObjectValue: &api.Value{Val: &api.Value_StrVal{StrVal: "ok 400"}}, - } - mu.Set = []*api.NQuad{quad} - // mu.SetNquads = []byte(`<400> "ok 400" .`) - _, err = txn.Mutate(ctx, mu) - if err != nil { - log.Fatalf("Error while running mutation: %v\n", err) - } - - x.Check(txn.Commit(ctx)) - fmt.Println("Commit OK") -} - -func testQuery3Quads(ctx context.Context, c *dgo.Dgraph) { - txn := c.NewTxn() - q := fmt.Sprint(`{ me(func: uid(200, 300, 400)) { name }}`) - resp, err := txn.Query(ctx, q) - if err != nil { - log.Fatalf("Error while running query: %v\n", err) - } - fmt.Printf("Response JSON: %q\n", resp.Json) - x.AssertTrue(bytes.Equal(resp.Json, []byte( - "{\"me\":[{\"name\":\"ok 200\"},{\"name\":\"ok 300\"},{\"name\":\"ok 400\"}]}"))) - x.AssertTrue(resp.Txn.StartTs > 0) - x.Check(txn.Commit(ctx)) -} diff --git a/contrib/integration/swap/.gitignore b/contrib/integration/swap/.gitignore deleted file mode 100644 index b7a2088ff..000000000 --- a/contrib/integration/swap/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/swap diff --git a/contrib/integration/swap/main.go b/contrib/integration/swap/main.go deleted file mode 100644 index 7afe3031b..000000000 --- a/contrib/integration/swap/main.go +++ /dev/null @@ -1,379 +0,0 @@ -/* - * Copyright 2017-2018 Dgraph Labs, Inc. and Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package main - -import ( - "context" - "encoding/json" - "flag" - "fmt" - "math/rand" - "reflect" - "sort" - "strings" - "sync/atomic" - "time" - - "github.com/outcaste-io/dgo/v210" - "github.com/outcaste-io/dgo/v210/protos/api" - "github.com/outcaste-io/outserv/testutil" - "github.com/outcaste-io/outserv/x" - "github.com/pkg/errors" -) - -var ( - alpha = flag.String("alpha", "localhost:9180", "Dgraph alpha address") - timeout = flag.Int("timeout", 60, "query/mutation timeout") - numSents = flag.Int("sentences", 100, "number of sentences") - numSwaps = flag.Int("swaps", 1000, "number of swaps to attempt") - concurr = flag.Int("concurrency", 10, "number of concurrent swaps to run concurrently") - invPerSec = flag.Int("inv", 10, "number of times to check invariants per second") -) - -var ( - successCount uint64 - failCount uint64 - invChecks uint64 -) - -func main() { - flag.Parse() - - sents := createSentences(*numSents) - sort.Strings(sents) - wordCount := make(map[string]int) - for _, s := range sents { - words := strings.Split(s, " ") - for _, w := range words { - wordCount[w]++ - } - } - type wc struct { - word string - count int - } - var wcs []wc - for w, c := range wordCount { - wcs = append(wcs, wc{w, c}) - } - sort.Slice(wcs, func(i, j int) bool { - wi := wcs[i] - wj := wcs[j] - return wi.word < wj.word - }) - for _, w := range wcs { - fmt.Printf("%15s: %3d\n", w.word, w.count) - } - - c, err := testutil.DgraphClientWithGroot(*alpha) - x.Check(err) - uids := setup(c, sents) - - // Check invariants before doing any mutations as a sanity check. - x.Check(checkInvariants(c, uids, sents)) - - go func() { - ticker := time.NewTicker(time.Second / time.Duration(*invPerSec)) - for range ticker.C { - for { - if err := checkInvariants(c, uids, sents); err == nil { - break - } else { - fmt.Printf("Error while running inv: %v\n", err) - } - } - atomic.AddUint64(&invChecks, 1) - } - }() - - done := make(chan struct{}) - go func() { - pending := make(chan struct{}, *concurr) - for i := 0; i < *numSwaps; i++ { - pending <- struct{}{} - go func() { - swapSentences(c, - uids[rand.Intn(len(uids))], - uids[rand.Intn(len(uids))], - ) - <-pending - }() - } - for i := 0; i < *concurr; i++ { - pending <- struct{}{} - } - close(done) - }() - - for { - select { - case <-time.After(time.Second): - fmt.Printf("Success:%d Fail:%d Check:%d\n", - atomic.LoadUint64(&successCount), - atomic.LoadUint64(&failCount), - atomic.LoadUint64(&invChecks), - ) - case <-done: - // One final check for invariants. - x.Check(checkInvariants(c, uids, sents)) - return - } - } - -} - -func createSentences(n int) []string { - sents := make([]string, n) - for i := range sents { - sents[i] = nextWord() - } - - // add trailing words -- some will be common between sentences - same := 2 - for { - var w string - var count int - for i := range sents { - if i%same == 0 { - w = nextWord() - count++ - } - sents[i] += " " + w - } - if count == 1 { - // Every sentence got the same trailing word, no point going any further. Sort the - // words within each sentence. - for i, one := range sents { - splits := strings.Split(one, " ") - sort.Strings(splits) - sents[i] = strings.Join(splits, " ") - } - return sents - } - same *= 2 - } -} - -func setup(c *dgo.Dgraph, sentences []string) []string { - ctx, cancel := context.WithTimeout(context.Background(), time.Duration(*timeout)*time.Second) - defer cancel() - x.Check(c.Alter(ctx, &api.Operation{ - DropAll: true, - })) - x.Check(c.Alter(ctx, &api.Operation{ - Schema: `sentence: string @index(term) .`, - })) - - rdfs := "" - for i, s := range sentences { - rdfs += fmt.Sprintf("_:s%d %q .\n", i, s) - } - txn := c.NewTxn() - defer func() { - if err := txn.Discard(ctx); err != nil { - fmt.Printf("Discarding transaction failed: %+v\n", err) - } - }() - - assigned, err := txn.Mutate(ctx, &api.Mutation{ - SetNquads: []byte(rdfs), - }) - x.Check(err) - x.Check(txn.Commit(ctx)) - - var uids []string - for _, uid := range assigned.GetUids() { - uids = append(uids, uid) - } - return uids -} - -func swapSentences(c *dgo.Dgraph, node1, node2 string) { - ctx, cancel := context.WithTimeout(context.Background(), time.Duration(*timeout)*time.Second) - defer cancel() - - txn := c.NewTxn() - defer func() { - if err := txn.Discard(ctx); err != nil { - fmt.Printf("Discarding transaction failed: %+v\n", err) - } - }() - - resp, err := txn.Query(ctx, fmt.Sprintf(` - { - node1(func: uid(%s)) { - sentence - } - node2(func: uid(%s)) { - sentence - } - } - `, node1, node2)) - x.Check(err) - - decode := struct { - Node1 []struct { - Sentence *string - } - Node2 []struct { - Sentence *string - } - }{} - err = json.Unmarshal(resp.GetJson(), &decode) - x.Check(err) - x.AssertTrue(len(decode.Node1) == 1) - x.AssertTrue(len(decode.Node2) == 1) - x.AssertTrue(decode.Node1[0].Sentence != nil) - x.AssertTrue(decode.Node2[0].Sentence != nil) - - // Delete sentences as an intermediate step. - delRDFs := fmt.Sprintf(` - <%s> %q . - <%s> %q . - `, - node1, *decode.Node1[0].Sentence, - node2, *decode.Node2[0].Sentence, - ) - if _, err := txn.Mutate(ctx, &api.Mutation{ - DelNquads: []byte(delRDFs), - }); err != nil { - atomic.AddUint64(&failCount, 1) - return - } - - // Add garbage data as an intermediate step. - garbageRDFs := fmt.Sprintf(` - <%s> "...garbage..." . - <%s> "...garbage..." . - `, - node1, node2, - ) - if _, err := txn.Mutate(ctx, &api.Mutation{ - SetNquads: []byte(garbageRDFs), - }); err != nil { - atomic.AddUint64(&failCount, 1) - return - } - - // Perform swap. - rdfs := fmt.Sprintf(` - <%s> %q . - <%s> %q . - `, - node1, *decode.Node2[0].Sentence, - node2, *decode.Node1[0].Sentence, - ) - if _, err := txn.Mutate(ctx, &api.Mutation{ - SetNquads: []byte(rdfs), - }); err != nil { - atomic.AddUint64(&failCount, 1) - return - } - if err := txn.Commit(ctx); err != nil { - atomic.AddUint64(&failCount, 1) - return - } - atomic.AddUint64(&successCount, 1) -} - -func checkInvariants(c *dgo.Dgraph, uids []string, sentences []string) error { - ctx, cancel := context.WithTimeout(context.Background(), time.Duration(*timeout)*time.Second) - defer cancel() - - // Get the sentence for each node. Then build (in memory) a term index. - // Then we can query dgraph for each term, and make sure the posting list - // is the same. - - txn := c.NewTxn() - uidList := strings.Join(uids, ",") - resp, err := txn.Query(ctx, fmt.Sprintf(` - { - q(func: uid(%s)) { - sentence - uid - } - } - `, uidList)) - if err != nil { - return err - } - decode := struct { - Q []struct { - Sentence *string - Uid *string - } - }{} - x.Check(json.Unmarshal(resp.GetJson(), &decode)) - x.AssertTrue(len(decode.Q) == len(sentences)) - - index := map[string][]string{} // term to uid list - var gotSentences []string - for _, node := range decode.Q { - x.AssertTrue(node.Sentence != nil) - x.AssertTrue(node.Uid != nil) - gotSentences = append(gotSentences, *node.Sentence) - for _, word := range strings.Split(*node.Sentence, " ") { - index[word] = append(index[word], *node.Uid) - } - } - sort.Strings(gotSentences) - for i := 0; i < len(sentences); i++ { - if sentences[i] != gotSentences[i] { - fmt.Printf("Sentence doesn't match. Wanted: %q. Got: %q\n", sentences[i], gotSentences[i]) - fmt.Printf("All sentences: %v\n", sentences) - fmt.Printf("Got sentences: %v\n", gotSentences) - x.AssertTrue(false) - } - } - - for word, uids := range index { - q := fmt.Sprintf(` - { - q(func: anyofterms(sentence, %q)) { - uid - } - } - `, word) - - resp, err := txn.Query(ctx, q) - if err != nil { - return err - } - decode := struct { - Q []struct { - Uid *string - } - }{} - x.Check(json.Unmarshal(resp.GetJson(), &decode)) - var gotUids []string - for _, node := range decode.Q { - x.AssertTrue(node.Uid != nil) - gotUids = append(gotUids, *node.Uid) - } - - sort.Strings(gotUids) - sort.Strings(uids) - if !reflect.DeepEqual(gotUids, uids) { - x.Panic(errors.Errorf(`query: %s\n - Uids in index for %q didn't match - calculated: %v. Len: %d - got: %v - `, q, word, uids, len(uids), gotUids)) - } - } - return nil -} diff --git a/contrib/integration/swap/words.go b/contrib/integration/swap/words.go deleted file mode 100644 index f28cfade1..000000000 --- a/contrib/integration/swap/words.go +++ /dev/null @@ -1,2272 +0,0 @@ -/* - * Copyright 2017-2018 Dgraph Labs, Inc. and Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package main - -var wordIdx = 0 - -func nextWord() string { - // TODO: Nicer to not use global. Also check for index out of range. - w := words[wordIdx] - wordIdx++ - return w -} - -var words = []string{ - "information", - "available", - "copyright", - "university", - "management", - "international", - "development", - "education", - "community", - "technology", - "following", - "resources", - "including", - "directory", - "government", - "department", - "description", - "insurance", - "different", - "categories", - "conditions", - "accessories", - "september", - "questions", - "application", - "financial", - "equipment", - "performance", - "experience", - "important", - "activities", - "additional", - "something", - "professional", - "committee", - "washington", - "california", - "reference", - "companies", - "computers", - "president", - "australia", - "discussion", - "entertainment", - "agreement", - "marketing", - "association", - "collection", - "solutions", - "electronics", - "technical", - "microsoft", - "conference", - "environment", - "statement", - "downloads", - "applications", - "requirements", - "individual", - "subscribe", - "everything", - "production", - "commercial", - "advertising", - "treatment", - "newsletter", - "knowledge", - "currently", - "construction", - "registered", - "protection", - "engineering", - "published", - "corporate", - "customers", - "materials", - "countries", - "standards", - "political", - "advertise", - "environmental", - "availability", - "employment", - "commission", - "administration", - "institute", - "sponsored", - "electronic", - "condition", - "effective", - "organization", - "selection", - "corporation", - "executive", - "necessary", - "according", - "particular", - "facilities", - "opportunities", - "appropriate", - "statistics", - "investment", - "christmas", - "registration", - "furniture", - "wednesday", - "structure", - "distribution", - "industrial", - "potential", - "responsible", - "communications", - "associated", - "foundation", - "documents", - "communication", - "independent", - "operating", - "developed", - "telephone", - "population", - "navigation", - "operations", - "therefore", - "christian", - "understand", - "publications", - "worldwide", - "connection", - "publisher", - "introduction", - "properties", - "accommodation", - "excellent", - "opportunity", - "assessment", - "especially", - "interface", - "operation", - "restaurants", - "beautiful", - "locations", - "significant", - "technologies", - "manufacturer", - "providing", - "authority", - "considered", - "programme", - "enterprise", - "educational", - "employees", - "alternative", - "processing", - "responsibility", - "resolution", - "publication", - "relations", - "photography", - "components", - "assistance", - "completed", - "organizations", - "otherwise", - "transportation", - "disclaimer", - "membership", - "recommended", - "background", - "character", - "maintenance", - "functions", - "trademarks", - "phentermine", - "submitted", - "television", - "interested", - "throughout", - "established", - "programming", - "regarding", - "instructions", - "increased", - "understanding", - "beginning", - "associates", - "instruments", - "businesses", - "specified", - "restaurant", - "procedures", - "relationship", - "traditional", - "sometimes", - "themselves", - "transport", - "interesting", - "evaluation", - "implementation", - "galleries", - "references", - "presented", - "literature", - "respective", - "definition", - "secretary", - "networking", - "australian", - "magazines", - "francisco", - "individuals", - "guidelines", - "installation", - "described", - "attention", - "difference", - "regulations", - "certificate", - "directions", - "documentation", - "automotive", - "successful", - "communities", - "situation", - "publishing", - "emergency", - "developing", - "determine", - "temperature", - "announcements", - "historical", - "ringtones", - "difficult", - "scientific", - "satellite", - "particularly", - "functional", - "monitoring", - "architecture", - "recommend", - "dictionary", - "accounting", - "manufacturing", - "professor", - "generally", - "continued", - "techniques", - "permission", - "generation", - "component", - "guarantee", - "processes", - "interests", - "paperback", - "classifieds", - "supported", - "competition", - "providers", - "characters", - "thousands", - "apartments", - "generated", - "administrative", - "practices", - "reporting", - "essential", - "affiliate", - "immediately", - "designated", - "integrated", - "configuration", - "comprehensive", - "universal", - "presentation", - "languages", - "compliance", - "improvement", - "pennsylvania", - "challenge", - "acceptance", - "strategies", - "affiliates", - "multimedia", - "certified", - "computing", - "interactive", - "procedure", - "leadership", - "religious", - "breakfast", - "developer", - "approximately", - "recommendations", - "comparison", - "automatically", - "minnesota", - "adventure", - "institutions", - "assistant", - "advertisement", - "headlines", - "yesterday", - "determined", - "wholesale", - "extension", - "statements", - "completely", - "electrical", - "applicable", - "manufacturers", - "classical", - "dedicated", - "direction", - "basketball", - "wisconsin", - "personnel", - "identified", - "professionals", - "advantage", - "newsletters", - "estimated", - "anonymous", - "miscellaneous", - "integration", - "interview", - "framework", - "installed", - "massachusetts", - "associate", - "frequently", - "discussions", - "laboratory", - "destination", - "intelligence", - "specifications", - "tripadvisor", - "residential", - "decisions", - "industries", - "partnership", - "editorial", - "expression", - "provisions", - "principles", - "suggestions", - "replacement", - "strategic", - "economics", - "compatible", - "apartment", - "netherlands", - "consulting", - "recreation", - "participants", - "favorites", - "translation", - "estimates", - "protected", - "philadelphia", - "officials", - "contained", - "legislation", - "parameters", - "relationships", - "tennessee", - "representative", - "frequency", - "introduced", - "departments", - "residents", - "displayed", - "performed", - "administrator", - "addresses", - "permanent", - "agriculture", - "constitutes", - "portfolio", - "practical", - "delivered", - "collectibles", - "infrastructure", - "exclusive", - "originally", - "utilities", - "philosophy", - "regulation", - "reduction", - "nutrition", - "recording", - "secondary", - "wonderful", - "announced", - "prevention", - "mentioned", - "automatic", - "healthcare", - "maintained", - "increasing", - "connected", - "directors", - "participation", - "containing", - "combination", - "amendment", - "guaranteed", - "libraries", - "distributed", - "singapore", - "enterprises", - "convention", - "principal", - "certification", - "previously", - "buildings", - "household", - "batteries", - "positions", - "subscription", - "contemporary", - "panasonic", - "permalink", - "signature", - "provision", - "certainly", - "newspaper", - "liability", - "trademark", - "trackback", - "americans", - "promotion", - "conversion", - "reasonable", - "broadband", - "influence", - "importance", - "webmaster", - "prescription", - "specifically", - "represent", - "conservation", - "louisiana", - "javascript", - "marketplace", - "evolution", - "certificates", - "objectives", - "suggested", - "concerned", - "structures", - "encyclopedia", - "continuing", - "interracial", - "competitive", - "suppliers", - "preparation", - "receiving", - "accordance", - "discussed", - "elizabeth", - "reservations", - "playstation", - "instruction", - "annotation", - "differences", - "establish", - "expressed", - "paragraph", - "mathematics", - "compensation", - "conducted", - "percentage", - "mississippi", - "requested", - "connecticut", - "personals", - "immediate", - "agricultural", - "supporting", - "collections", - "participate", - "specialist", - "experienced", - "investigation", - "institution", - "searching", - "proceedings", - "transmission", - "characteristics", - "experiences", - "extremely", - "verzeichnis", - "contracts", - "concerning", - "developers", - "equivalent", - "chemistry", - "neighborhood", - "variables", - "continues", - "curriculum", - "psychology", - "responses", - "circumstances", - "identification", - "appliances", - "elementary", - "unlimited", - "printable", - "enforcement", - "hardcover", - "celebrity", - "chocolate", - "hampshire", - "bluetooth", - "controlled", - "requirement", - "authorities", - "representatives", - "pregnancy", - "biography", - "attractions", - "transactions", - "authorized", - "retirement", - "financing", - "efficiency", - "efficient", - "commitment", - "specialty", - "interviews", - "qualified", - "discovery", - "classified", - "confidence", - "lifestyle", - "consistent", - "clearance", - "connections", - "inventory", - "converter", - "organisation", - "objective", - "indicated", - "securities", - "volunteer", - "democratic", - "switzerland", - "parameter", - "processor", - "dimensions", - "contribute", - "challenges", - "recognition", - "submission", - "encourage", - "regulatory", - "inspection", - "consumers", - "territory", - "transaction", - "manchester", - "contributions", - "continuous", - "resulting", - "cambridge", - "initiative", - "execution", - "disability", - "increases", - "contractor", - "examination", - "indicates", - "committed", - "extensive", - "affordable", - "candidate", - "databases", - "outstanding", - "perspective", - "messenger", - "tournament", - "consideration", - "discounts", - "catalogue", - "publishers", - "caribbean", - "reservation", - "remaining", - "depending", - "expansion", - "purchased", - "performing", - "collected", - "absolutely", - "featuring", - "implement", - "scheduled", - "calculator", - "significantly", - "temporary", - "sufficient", - "awareness", - "vancouver", - "contribution", - "measurement", - "constitution", - "packaging", - "consultation", - "northwest", - "classroom", - "democracy", - "wallpaper", - "merchandise", - "resistance", - "baltimore", - "candidates", - "charlotte", - "biological", - "transition", - "preferences", - "instrument", - "classification", - "physician", - "hollywood", - "wikipedia", - "spiritual", - "photographs", - "relatively", - "satisfaction", - "represents", - "pittsburgh", - "preferred", - "intellectual", - "comfortable", - "interaction", - "listening", - "effectively", - "experimental", - "revolution", - "consolidation", - "landscape", - "dependent", - "mechanical", - "consultants", - "applicant", - "cooperation", - "acquisition", - "implemented", - "directories", - "recognized", - "notification", - "licensing", - "textbooks", - "diversity", - "cleveland", - "investments", - "accessibility", - "sensitive", - "templates", - "completion", - "universities", - "technique", - "contractors", - "subscriptions", - "calculate", - "alexander", - "broadcast", - "converted", - "anniversary", - "improvements", - "specification", - "accessible", - "accessory", - "typically", - "representation", - "arrangements", - "conferences", - "uniprotkb", - "consumption", - "birmingham", - "afternoon", - "consultant", - "controller", - "ownership", - "committees", - "legislative", - "researchers", - "unsubscribe", - "molecular", - "residence", - "attorneys", - "operators", - "sustainable", - "philippines", - "statistical", - "innovation", - "employers", - "definitions", - "elections", - "stainless", - "newspapers", - "hospitals", - "exception", - "successfully", - "indonesia", - "primarily", - "capabilities", - "recommendation", - "recruitment", - "organized", - "improving", - "expensive", - "organisations", - "explained", - "programmes", - "expertise", - "mechanism", - "jewellery", - "eventually", - "agreements", - "considering", - "innovative", - "conclusion", - "disorders", - "collaboration", - "detection", - "formation", - "engineers", - "proposals", - "moderator", - "tutorials", - "settlement", - "collectables", - "fantastic", - "governments", - "purchasing", - "appointed", - "operational", - "corresponding", - "descriptions", - "determination", - "animation", - "productions", - "telecommunications", - "instructor", - "approaches", - "highlights", - "designers", - "melbourne", - "scientists", - "blackjack", - "argentina", - "possibility", - "commissioner", - "dangerous", - "reliability", - "unfortunately", - "respectively", - "volunteers", - "attachment", - "appointment", - "workshops", - "hurricane", - "represented", - "mortgages", - "responsibilities", - "carefully", - "productivity", - "investors", - "underground", - "diagnosis", - "principle", - "vacations", - "calculated", - "appearance", - "incorporated", - "notebooks", - "algorithm", - "valentine", - "involving", - "investing", - "christopher", - "admission", - "terrorism", - "parliament", - "situations", - "allocated", - "corrections", - "structural", - "municipal", - "describes", - "disabilities", - "substance", - "prohibited", - "addressed", - "simulation", - "initiatives", - "concentration", - "interpretation", - "bankruptcy", - "optimization", - "substances", - "discovered", - "restrictions", - "participating", - "exhibition", - "composition", - "nationwide", - "definitely", - "existence", - "commentary", - "limousines", - "developments", - "immigration", - "destinations", - "necessarily", - "attribute", - "apparently", - "surrounding", - "mountains", - "popularity", - "postposted", - "coordinator", - "obviously", - "fundamental", - "substantial", - "progressive", - "championship", - "sacramento", - "impossible", - "depression", - "testimonials", - "memorabilia", - "cartridge", - "explanation", - "cincinnati", - "subsection", - "electricity", - "permitted", - "workplace", - "confirmed", - "wallpapers", - "infection", - "eligibility", - "involvement", - "placement", - "observations", - "vbulletin", - "subsequent", - "motorcycle", - "disclosure", - "establishment", - "presentations", - "undergraduate", - "occupation", - "donations", - "associations", - "citysearch", - "radiation", - "seriously", - "elsewhere", - "pollution", - "conservative", - "guestbook", - "effectiveness", - "demonstrate", - "atmosphere", - "experiment", - "purchases", - "federation", - "assignment", - "chemicals", - "everybody", - "nashville", - "counseling", - "acceptable", - "satisfied", - "measurements", - "milwaukee", - "medication", - "warehouse", - "shareware", - "violation", - "configure", - "stability", - "southwest", - "institutional", - "expectations", - "independence", - "metabolism", - "personally", - "excellence", - "somewhere", - "attributes", - "recognize", - "screening", - "thumbnail", - "forgotten", - "intelligent", - "edinburgh", - "obligation", - "regardless", - "restricted", - "republican", - "merchants", - "attendance", - "arguments", - "amsterdam", - "adventures", - "announcement", - "appreciate", - "regularly", - "mechanisms", - "customize", - "tradition", - "indicators", - "emissions", - "physicians", - "complaint", - "experiments", - "afghanistan", - "scholarship", - "governance", - "supplements", - "camcorder", - "implementing", - "ourselves", - "conversation", - "capability", - "producing", - "precision", - "contributed", - "reproduction", - "ingredients", - "franchise", - "complaints", - "promotions", - "rehabilitation", - "maintaining", - "environments", - "reception", - "correctly", - "consequences", - "geography", - "appearing", - "integrity", - "discrimination", - "processed", - "implications", - "functionality", - "intermediate", - "emotional", - "platforms", - "overnight", - "geographic", - "preliminary", - "districts", - "introduce", - "promotional", - "chevrolet", - "specialists", - "generator", - "suspension", - "correction", - "authentication", - "communicate", - "supplement", - "showtimes", - "promoting", - "machinery", - "bandwidth", - "probability", - "dimension", - "schedules", - "admissions", - "quarterly", - "illustrated", - "continental", - "alternate", - "achievement", - "limitations", - "automated", - "passenger", - "convenient", - "orientation", - "childhood", - "flexibility", - "jurisdiction", - "displaying", - "encouraged", - "cartridges", - "declaration", - "automation", - "advantages", - "preparing", - "recipient", - "extensions", - "athletics", - "southeast", - "alternatives", - "determining", - "personalized", - "conditioning", - "partnerships", - "destruction", - "increasingly", - "migration", - "basically", - "conventional", - "applicants", - "occupational", - "adjustment", - "treatments", - "camcorders", - "difficulty", - "collective", - "coalition", - "enrollment", - "producers", - "collector", - "interfaces", - "advertisers", - "representing", - "observation", - "restoration", - "convenience", - "returning", - "opposition", - "container", - "defendant", - "confirmation", - "supervisor", - "peripherals", - "bestsellers", - "departure", - "minneapolis", - "interactions", - "intervention", - "attraction", - "modification", - "customized", - "understood", - "assurance", - "happening", - "amendments", - "metropolitan", - "compilation", - "verification", - "attractive", - "recordings", - "jefferson", - "gardening", - "obligations", - "orchestra", - "polyphonic", - "outsourcing", - "adjustable", - "allocation", - "discipline", - "demonstrated", - "identifying", - "alphabetical", - "dispatched", - "installing", - "voluntary", - "photographer", - "messaging", - "constructed", - "additions", - "requiring", - "engagement", - "refinance", - "calendars", - "arrangement", - "conclusions", - "bibliography", - "compatibility", - "furthermore", - "cooperative", - "measuring", - "jacksonville", - "headquarters", - "transfers", - "transformation", - "attachments", - "administrators", - "personality", - "facilitate", - "subscriber", - "priorities", - "bookstore", - "parenting", - "incredible", - "commonwealth", - "pharmaceutical", - "manhattan", - "workforce", - "organizational", - "portuguese", - "everywhere", - "discharge", - "halloween", - "hazardous", - "methodology", - "housewares", - "reputation", - "resistant", - "democrats", - "recycling", - "qualifications", - "slideshow", - "variation", - "transferred", - "photograph", - "distributor", - "underlying", - "wrestling", - "photoshop", - "gathering", - "projection", - "mathematical", - "specialized", - "diagnostic", - "indianapolis", - "corporations", - "criticism", - "automobile", - "confidential", - "statutory", - "accommodations", - "northeast", - "downloaded", - "paintings", - "injection", - "yorkshire", - "populations", - "protective", - "initially", - "indicator", - "eliminate", - "sunglasses", - "preference", - "threshold", - "venezuela", - "exploration", - "sequences", - "astronomy", - "translate", - "announces", - "compression", - "establishing", - "constitutional", - "perfectly", - "instantly", - "litigation", - "submissions", - "broadcasting", - "horizontal", - "terrorist", - "informational", - "ecommerce", - "suffering", - "prospective", - "ultimately", - "artificial", - "spectacular", - "coordination", - "connector", - "affiliated", - "activation", - "naturally", - "subscribers", - "mitsubishi", - "underwear", - "potentially", - "constraints", - "inclusive", - "dimensional", - "considerable", - "selecting", - "processors", - "pantyhose", - "difficulties", - "complexity", - "constantly", - "barcelona", - "presidential", - "documentary", - "territories", - "palestinian", - "legislature", - "hospitality", - "procurement", - "theoretical", - "exercises", - "surveillance", - "protocols", - "highlight", - "substitute", - "inclusion", - "hopefully", - "brilliant", - "evaluated", - "assignments", - "termination", - "households", - "authentic", - "montgomery", - "architectural", - "louisville", - "macintosh", - "movements", - "amenities", - "virtually", - "authorization", - "projector", - "comparative", - "psychological", - "surprised", - "genealogy", - "expenditure", - "liverpool", - "connectivity", - "algorithms", - "similarly", - "collaborative", - "excluding", - "commander", - "suggestion", - "spotlight", - "investigate", - "connecting", - "logistics", - "proportion", - "significance", - "symposium", - "essentials", - "protecting", - "transmitted", - "screenshots", - "intensive", - "switching", - "correspondence", - "supervision", - "expenditures", - "separation", - "testimony", - "celebrities", - "mandatory", - "boundaries", - "syndication", - "celebration", - "filtering", - "luxembourg", - "offensive", - "deployment", - "colleagues", - "separated", - "directive", - "governing", - "retailers", - "occasionally", - "attending", - "recruiting", - "instructional", - "traveling", - "permissions", - "biotechnology", - "prescribed", - "catherine", - "reproduced", - "calculation", - "consolidated", - "occasions", - "equations", - "exceptional", - "respondents", - "considerations", - "queensland", - "musicians", - "composite", - "unavailable", - "essentially", - "designing", - "assessments", - "brunswick", - "sensitivity", - "preservation", - "streaming", - "intensity", - "technological", - "syndicate", - "antivirus", - "addressing", - "discounted", - "bangladesh", - "constitute", - "concluded", - "desperate", - "demonstration", - "governmental", - "manufactured", - "graduation", - "variations", - "addiction", - "springfield", - "synthesis", - "undefined", - "unemployment", - "enhancement", - "newcastle", - "performances", - "societies", - "brazilian", - "identical", - "petroleum", - "norwegian", - "retention", - "exchanges", - "soundtrack", - "wondering", - "profession", - "separately", - "physiology", - "collecting", - "participant", - "scholarships", - "recreational", - "dominican", - "friendship", - "expanding", - "provincial", - "investigations", - "medications", - "rochester", - "advertiser", - "encryption", - "downloadable", - "sophisticated", - "possession", - "laboratories", - "vegetables", - "thumbnails", - "stockings", - "respondent", - "destroyed", - "manufacture", - "wordpress", - "vulnerability", - "accountability", - "celebrate", - "accredited", - "appliance", - "compressed", - "scheduling", - "perspectives", - "mortality", - "christians", - "therapeutic", - "impressive", - "accordingly", - "architect", - "challenging", - "microwave", - "accidents", - "relocation", - "contributors", - "violations", - "temperatures", - "competitions", - "discretion", - "cosmetics", - "repository", - "concentrations", - "christianity", - "negotiations", - "realistic", - "generating", - "christina", - "congressional", - "photographic", - "modifications", - "millennium", - "achieving", - "fisheries", - "exceptions", - "reactions", - "macromedia", - "companion", - "divisions", - "additionally", - "fellowship", - "victorian", - "copyrights", - "lithuania", - "mastercard", - "chronicles", - "obtaining", - "distribute", - "decorative", - "enlargement", - "campaigns", - "conjunction", - "instances", - "indigenous", - "validation", - "corruption", - "incentives", - "cholesterol", - "differential", - "scientist", - "starsmerchant", - "arthritis", - "nevertheless", - "practitioners", - "transcript", - "inflation", - "compounds", - "contracting", - "structured", - "reasonably", - "graduates", - "recommends", - "controlling", - "distributors", - "arlington", - "particles", - "extraordinary", - "indicating", - "coordinate", - "exclusively", - "limitation", - "widescreen", - "illustration", - "construct", - "inquiries", - "inspiration", - "affecting", - "downloading", - "aggregate", - "forecasts", - "complicated", - "shopzilla", - "decorating", - "expressions", - "shakespeare", - "connectors", - "conflicts", - "travelers", - "offerings", - "incorrect", - "furnishings", - "guatemala", - "perception", - "renaissance", - "pathology", - "ordinance", - "photographers", - "infections", - "configured", - "festivals", - "possibilities", - "contributing", - "analytical", - "circulation", - "assumption", - "jerusalem", - "transexuales", - "invention", - "technician", - "executives", - "enquiries", - "cognitive", - "exploring", - "registrar", - "supporters", - "withdrawal", - "predicted", - "saskatchewan", - "cancellation", - "ministers", - "veterinary", - "prostores", - "relevance", - "incentive", - "butterfly", - "mechanics", - "numerical", - "reflection", - "accompanied", - "invitation", - "princeton", - "spirituality", - "meanwhile", - "proprietary", - "childrens", - "thumbzilla", - "porcelain", - "pichunter", - "translated", - "columnists", - "consensus", - "delivering", - "journalism", - "intention", - "undertaken", - "statewide", - "semiconductor", - "illustrations", - "happiness", - "substantially", - "identifier", - "calculations", - "conducting", - "accomplished", - "calculators", - "impression", - "correlation", - "fragrance", - "neighbors", - "transparent", - "charleston", - "champions", - "selections", - "projectors", - "inappropriate", - "comparing", - "vocational", - "pharmacies", - "introducing", - "appreciated", - "albuquerque", - "distinguished", - "projected", - "assumptions", - "shareholders", - "developmental", - "regulated", - "anticipated", - "completing", - "comparable", - "confusion", - "copyrighted", - "warranties", - "documented", - "paperbacks", - "keyboards", - "vulnerable", - "reflected", - "respiratory", - "notifications", - "transexual", - "mainstream", - "evaluating", - "subcommittee", - "maternity", - "journalists", - "foundations", - "volleyball", - "liabilities", - "decreased", - "tolerance", - "creativity", - "describing", - "lightning", - "quotations", - "inspector", - "bookmarks", - "behavioral", - "riverside", - "bathrooms", - "abilities", - "initiated", - "nonprofit", - "lancaster", - "suspended", - "containers", - "attitudes", - "simultaneously", - "integrate", - "sociology", - "screenshot", - "exhibitions", - "confident", - "retrieved", - "officially", - "consortium", - "recipients", - "delicious", - "traditions", - "periodically", - "hungarian", - "referring", - "transform", - "educators", - "vegetable", - "humanities", - "independently", - "alignment", - "masturbating", - "henderson", - "britannica", - "competitors", - "visibility", - "consciousness", - "encounter", - "resolutions", - "accessing", - "attempted", - "witnesses", - "administered", - "strengthen", - "frederick", - "aggressive", - "advertisements", - "sublimedirectory", - "disturbed", - "determines", - "sculpture", - "motivation", - "pharmacology", - "passengers", - "quantities", - "petersburg", - "consistently", - "powerpoint", - "obituaries", - "punishment", - "appreciation", - "subsequently", - "providence", - "restriction", - "incorporate", - "backgrounds", - "treasurer", - "lightweight", - "transcription", - "complications", - "scripting", - "remembered", - "synthetic", - "testament", - "specifics", - "partially", - "wilderness", - "generations", - "tournaments", - "sponsorship", - "headphones", - "proceeding", - "volkswagen", - "uncertainty", - "breakdown", - "reconstruction", - "subsidiary", - "strengths", - "encouraging", - "furnished", - "terrorists", - "comparisons", - "beneficial", - "distributions", - "viewpicture", - "threatened", - "republicans", - "discusses", - "responded", - "abstracts", - "prediction", - "pharmaceuticals", - "thesaurus", - "individually", - "battlefield", - "literally", - "ecological", - "appraisal", - "consisting", - "submitting", - "citations", - "geographical", - "mozambique", - "disclaimers", - "championships", - "sheffield", - "finishing", - "wellington", - "prospects", - "bulgarian", - "aboriginal", - "remarkable", - "preventing", - "productive", - "boulevard", - "compliant", - "penalties", - "imagination", - "refurbished", - "activated", - "conferencing", - "armstrong", - "politicians", - "trackbacks", - "accommodate", - "christine", - "accepting", - "precipitation", - "isolation", - "sustained", - "approximate", - "programmer", - "greetings", - "inherited", - "incomplete", - "chronicle", - "legitimate", - "biographies", - "investigator", - "plaintiff", - "prisoners", - "mediterranean", - "nightlife", - "architects", - "entrepreneur", - "freelance", - "excessive", - "screensaver", - "valuation", - "unexpected", - "cigarette", - "characteristic", - "metallica", - "consequently", - "appointments", - "narrative", - "academics", - "quantitative", - "screensavers", - "subdivision", - "distinction", - "livestock", - "exemption", - "sustainability", - "formatting", - "nutritional", - "nicaragua", - "affiliation", - "relatives", - "satisfactory", - "revolutionary", - "bracelets", - "telephony", - "breathing", - "thickness", - "adjustments", - "graphical", - "discussing", - "aerospace", - "meaningful", - "maintains", - "shortcuts", - "voyeurweb", - "extending", - "specifies", - "accreditation", - "blackberry", - "meditation", - "microphone", - "macedonia", - "combining", - "instrumental", - "organizing", - "moderators", - "kazakhstan", - "standings", - "partition", - "invisible", - "translations", - "commodity", - "kilometers", - "thanksgiving", - "guarantees", - "indication", - "congratulations", - "cigarettes", - "controllers", - "consultancy", - "conventions", - "coordinates", - "responding", - "physically", - "stakeholders", - "hydrocodone", - "consecutive", - "attempting", - "representations", - "competing", - "peninsula", - "accurately", - "considers", - "ministries", - "vacancies", - "parliamentary", - "acknowledge", - "thoroughly", - "nottingham", - "identifies", - "questionnaire", - "qualification", - "modelling", - "miniature", - "interstate", - "consequence", - "systematic", - "perceived", - "madagascar", - "presenting", - "troubleshooting", - "uzbekistan", - "centuries", - "magnitude", - "richardson", - "fragrances", - "vocabulary", - "earthquake", - "fundraising", - "geological", - "assessing", - "introduces", - "webmasters", - "computational", - "acdbentity", - "participated", - "handhelds", - "answering", - "impressed", - "conspiracy", - "organizer", - "combinations", - "preceding", - "cumulative", - "amplifier", - "arbitrary", - "prominent", - "lexington", - "contacted", - "recorders", - "occasional", - "innovations", - "postcards", - "reviewing", - "explicitly", - "transsexual", - "citizenship", - "informative", - "girlfriend", - "bloomberg", - "hierarchy", - "influenced", - "abandoned", - "complement", - "mauritius", - "checklist", - "requesting", - "lauderdale", - "scenarios", - "extraction", - "elevation", - "utilization", - "beverages", - "calibration", - "efficiently", - "entertaining", - "prerequisite", - "hypothesis", - "medicines", - "regression", - "enhancements", - "renewable", - "intersection", - "passwords", - "consistency", - "collectors", - "azerbaijan", - "astrology", - "occurring", - "supplemental", - "travelling", - "induction", - "precisely", - "spreading", - "provinces", - "widespread", - "incidence", - "incidents", - "enhancing", - "interference", - "palestine", - "listprice", - "atmospheric", - "knowledgestorm", - "referenced", - "publicity", - "proposition", - "allowance", - "designation", - "duplicate", - "criterion", - "civilization", - "vietnamese", - "tremendous", - "corrected", - "encountered", - "internationally", - "surrounded", - "creatures", - "commented", - "accomplish", - "vegetarian", - "newfoundland", - "investigated", - "ambassador", - "stephanie", - "contacting", - "vegetation", - "findarticles", - "specially", - "infectious", - "continuity", - "phenomenon", - "conscious", - "referrals", - "differently", - "integrating", - "revisions", - "reasoning", - "charitable", - "annotated", - "convinced", - "burlington", - "replacing", - "researcher", - "watershed", - "occupations", - "acknowledged", - "equilibrium", - "characterized", - "privilege", - "qualifying", - "estimation", - "pediatric", - "techrepublic", - "institutes", - "brochures", - "traveller", - "appropriations", - "suspected", - "benchmark", - "beginners", - "instructors", - "highlighted", - "stationery", - "unauthorized", - "competent", - "contributor", - "demonstrates", - "gradually", - "desirable", - "journalist", - "afterwards", - "religions", - "explosion", - "signatures", - "disciplines", - "daughters", - "conversations", - "simplified", - "motherboard", - "bibliographic", - "champagne", - "deviation", - "superintendent", - "housewives", - "influences", - "inspections", - "irrigation", - "hydraulic", - "robertson", - "penetration", - "conviction", - "omissions", - "retrieval", - "qualities", - "prototype", - "importantly", - "apparatus", - "explaining", - "nomination", - "empirical", - "dependence", - "sexuality", - "polyester", - "commitments", - "suggesting", - "remainder", - "privileges", - "televisions", - "specializing", - "commodities", - "motorcycles", - "concentrate", - "reproductive", - "molecules", - "refrigerator", - "intervals", - "sentences", - "exclusion", - "workstation", - "holocaust", - "receivers", - "disposition", - "navigator", - "investigators", - "marijuana", - "cathedral", - "fairfield", - "fascinating", - "landscapes", - "lafayette", - "computation", - "cardiovascular", - "salvation", - "predictions", - "accompanying", - "selective", - "arbitration", - "configuring", - "editorials", - "sacrifice", - "removable", - "convergence", - "gibraltar", - "anthropology", - "malpractice", - "reporters", - "necessity", - "rendering", - "hepatitis", - "nationally", - "waterproof", - "specialties", - "humanitarian", - "invitations", - "functioning", - "economies", - "alexandria", - "bacterial", - "undertake", - "continuously", - "achievements", - "convertible", - "secretariat", - "paragraphs", - "adolescent", - "nominations", - "cancelled", - "introductory", - "reservoir", - "occurrence", - "worcester", - "demographic", - "disciplinary", - "respected", - "portraits", - "interpreted", - "evaluations", - "elimination", - "hypothetical", - "immigrants", - "complimentary", - "helicopter", - "performer", - "commissions", - "powerseller", - "graduated", - "surprising", - "unnecessary", - "dramatically", - "yugoslavia", - "characterization", - "likelihood", - "fundamentals", - "contamination", - "endangered", - "compromise", - "masturbation", - "expiration", - "namespace", - "peripheral", - "negotiation", - "opponents", - "nominated", - "confidentiality", - "electoral", - "changelog", - "alternatively", - "greensboro", - "controversial", - "recovered", - "upgrading", - "frontpage", - "demanding", - "defensive", - "forbidden", - "programmers", - "monitored", - "installations", - "deutschland", - "practitioner", - "motivated", - "smithsonian", - "examining", - "revelation", - "delegation", - "dictionaries", - "greenhouse", - "transparency", - "currencies", - "survivors", - "positioning", - "descending", - "temporarily", - "frequencies", - "reflections", - "municipality", - "detective", - "experiencing", - "fireplace", - "endorsement", - "psychiatry", - "persistent", - "summaries", - "looksmart", - "magnificent", - "colleague", - "adaptation", - "paintball", - "enclosure", - "supervisors", - "westminster", - "distances", - "absorption", - "treasures", - "transcripts", - "disappointed", - "continually", - "communist", - "collectible", - "entrepreneurs", - "creations", - "acquisitions", - "biodiversity", - "excitement", - "presently", - "mysterious", - "librarian", - "subsidiaries", - "stockholm", - "indonesian", - "therapist", - "promising", - "relaxation", - "thereafter", - "commissioners", - "forwarding", - "nightmare", - "reductions", - "southampton", - "organisms", - "telescope", - "portsmouth", - "advancement", - "harassment", - "generators", - "generates", - "replication", - "inexpensive", - "receptors", - "interventions", - "huntington", - "internship", - "aluminium", - "snowboard", - "beastality", - "evanescence", - "coordinated", - "shipments", - "antarctica", - "chancellor", - "controversy", - "legendary", - "beautifully", - "antibodies", - "examinations", - "immunology", - "departmental", - "terminology", - "gentleman", - "reproduce", - "convicted", - "roommates", - "threatening", - "spokesman", - "activists", - "frankfurt", - "encourages", - "assembled", - "restructuring", - "terminals", - "simulations", - "sufficiently", - "conditional", - "crossword", - "conceptual", - "liechtenstein", - "translator", - "automobiles", - "continent", - "longitude", - "challenged", - "telecharger", - "insertion", - "instrumentation", - "constraint", - "groundwater", - "strengthening", - "insulation", - "infringement", - "subjective", - "swaziland", - "varieties", - "mediawiki", - "configurations", -} diff --git a/contrib/integration/testtxn/.gitignore b/contrib/integration/testtxn/.gitignore deleted file mode 100644 index 5a12fa844..000000000 --- a/contrib/integration/testtxn/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/testtxn diff --git a/contrib/integration/testtxn/main_test.go b/contrib/integration/testtxn/main_test.go deleted file mode 100644 index 76b59f115..000000000 --- a/contrib/integration/testtxn/main_test.go +++ /dev/null @@ -1,935 +0,0 @@ -/* - * Copyright 2017-2018 Dgraph Labs, Inc. and Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package main_test - -import ( - "bytes" - "context" - "fmt" - "log" - "os" - "sort" - "strconv" - "strings" - "sync" - "testing" - "time" - - "github.com/outcaste-io/dgo/v210" - "github.com/outcaste-io/dgo/v210/protos/api" - "github.com/outcaste-io/outserv/testutil" - "github.com/outcaste-io/outserv/x" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -type state struct { - dg *dgo.Dgraph -} - -var s state - -func TestMain(m *testing.M) { - log.SetFlags(log.LstdFlags | log.Lshortfile) - testutil.AssignUids(200) - dg, err := testutil.DgraphClientWithGroot(testutil.SockAddr) - x.CheckfNoTrace(err) - s.dg = dg - - r := m.Run() - os.Exit(r) -} - -// readTs == startTs -func TestTxnRead1(t *testing.T) { - op := &api.Operation{} - op.DropAll = true - require.NoError(t, s.dg.Alter(context.Background(), op)) - - txn := s.dg.NewTxn() - mu := &api.Mutation{} - mu.SetJson = []byte(`{"name": "Manish"}`) - assigned, err := txn.Mutate(context.Background(), mu) - if err != nil { - log.Fatalf("Error while running mutation: %v\n", err) - } - if len(assigned.Uids) != 1 { - log.Fatalf("Error. Nothing assigned. %+v\n", assigned) - } - uid := retrieveUids(assigned.Uids)[0] - q := fmt.Sprintf(`{ me(func: uid(%s)) { name }}`, uid) - resp, err := txn.Query(context.Background(), q) - if err != nil { - log.Fatalf("Error while running query: %v\n", err) - } - x.AssertTrue(bytes.Equal(resp.Json, []byte("{\"me\":[{\"name\":\"Manish\"}]}"))) - require.NoError(t, txn.Commit(context.Background())) -} - -// readTs < commitTs -func TestTxnRead2(t *testing.T) { - txn := s.dg.NewTxn() - - mu := &api.Mutation{} - mu.SetJson = []byte(`{"name": "Manish"}`) - assigned, err := txn.Mutate(context.Background(), mu) - if err != nil { - log.Fatalf("Error while running mutation: %v\n", err) - } - if len(assigned.Uids) != 1 { - log.Fatalf("Error. Nothing assigned. %+v\n", assigned) - } - var uid string - for _, u := range assigned.Uids { - uid = u - } - - txn2 := s.dg.NewTxn() - - q := fmt.Sprintf(`{ me(func: uid(%s)) { name }}`, uid) - resp, err := txn2.Query(context.Background(), q) - if err != nil { - log.Fatalf("Error while running query: %v\n", err) - } - x.AssertTruef(bytes.Equal(resp.Json, []byte("{\"me\":[]}")), "%s", resp.Json) - require.NoError(t, txn.Commit(context.Background())) -} - -// readTs > commitTs -func TestTxnRead3(t *testing.T) { - op := &api.Operation{} - op.DropAttr = "name" - attempts := 0 - for attempts < 10 { - if err := s.dg.Alter(context.Background(), op); err == nil { - break - } - attempts++ - } - - txn := s.dg.NewTxn() - - mu := &api.Mutation{} - mu.SetJson = []byte(`{"name": "Manish"}`) - assigned, err := txn.Mutate(context.Background(), mu) - if err != nil { - log.Fatalf("Error while running mutation: %v\n", err) - } - if len(assigned.Uids) != 1 { - log.Fatalf("Error. Nothing assigned. %+v\n", assigned) - } - var uid string - for _, u := range assigned.Uids { - uid = u - } - - require.NoError(t, txn.Commit(context.Background())) - txn = s.dg.NewTxn() - q := fmt.Sprintf(`{ me(func: uid(%s)) { name }}`, uid) - resp, err := txn.Query(context.Background(), q) - if err != nil { - log.Fatalf("Error while running query: %v\n", err) - } - x.AssertTrue(bytes.Equal(resp.Json, []byte("{\"me\":[{\"name\":\"Manish\"}]}"))) -} - -// readTs > commitTs -func TestTxnRead4(t *testing.T) { - txn := s.dg.NewTxn() - - mu := &api.Mutation{} - mu.SetJson = []byte(`{"name": "Manish"}`) - assigned, err := txn.Mutate(context.Background(), mu) - if err != nil { - log.Fatalf("Error while running mutation: %v\n", err) - } - if len(assigned.Uids) != 1 { - log.Fatalf("Error. Nothing assigned. %+v\n", assigned) - } - var uid string - for _, u := range assigned.Uids { - uid = u - } - - require.NoError(t, txn.Commit(context.Background())) - txn2 := s.dg.NewTxn() - - txn3 := s.dg.NewTxn() - mu = &api.Mutation{} - mu.SetJson = []byte(fmt.Sprintf(`{"uid": "%s", "name": "Manish2"}`, uid)) - _, err = txn3.Mutate(context.Background(), mu) - if err != nil { - log.Fatalf("Error while running mutation: %v\n", err) - } - q := fmt.Sprintf(`{ me(func: uid(%s)) { name }}`, uid) - resp, err := txn2.Query(context.Background(), q) - if err != nil { - log.Fatalf("Error while running query: %v\n", err) - } - x.AssertTrue(bytes.Equal(resp.Json, []byte("{\"me\":[{\"name\":\"Manish\"}]}"))) - - require.NoError(t, txn3.Commit(context.Background())) - - txn4 := s.dg.NewTxn() - q = fmt.Sprintf(`{ me(func: uid(%s)) { name }}`, uid) - resp, err = txn4.Query(context.Background(), q) - if err != nil { - log.Fatalf("Error while running query: %v\n", err) - } - x.AssertTrue(bytes.Equal(resp.Json, []byte("{\"me\":[{\"name\":\"Manish2\"}]}"))) -} - -func TestTxnRead5(t *testing.T) { - txn := s.dg.NewTxn() - - mu := &api.Mutation{} - mu.SetJson = []byte(`{"name": "Manish"}`) - assigned, err := txn.Mutate(context.Background(), mu) - if err != nil { - log.Fatalf("Error while running mutation: %v\n", err) - } - if len(assigned.Uids) != 1 { - log.Fatalf("Error. Nothing assigned. %+v\n", assigned) - } - var uid string - for _, u := range assigned.Uids { - uid = u - } - - require.NoError(t, txn.Commit(context.Background())) - q := fmt.Sprintf(`{ me(func: uid(%s)) { name }}`, uid) - - txn = s.dg.NewReadOnlyTxn() - resp, err := txn.Query(context.Background(), q) - if err != nil { - log.Fatalf("Error while running query: %v\n", err) - } - x.AssertTrue(bytes.Equal(resp.Json, []byte("{\"me\":[{\"name\":\"Manish\"}]}"))) - x.AssertTrue(resp.Txn.StartTs > 0) - - mu = &api.Mutation{CommitNow: true} - mu.SetJson = []byte(fmt.Sprintf("{\"uid\": \"%s\", \"name\": \"Manish2\"}", uid)) - - txn = s.dg.NewTxn() - res, err := txn.Mutate(context.Background(), mu) - if err != nil { - log.Fatalf("Error while running mutation: %v\n", err) - } - x.AssertTrue(res.Txn.StartTs > 0) - txn = s.dg.NewReadOnlyTxn() - resp, err = txn.Query(context.Background(), q) - if err != nil { - log.Fatalf("Error while running query: %v\n", err) - } - x.AssertTrue(bytes.Equal(resp.Json, []byte(`{"me":[{"name":"Manish2"}]}`))) -} - -func TestConflict(t *testing.T) { - op := &api.Operation{} - op.DropAll = true - require.NoError(t, s.dg.Alter(context.Background(), op)) - - txn := s.dg.NewTxn() - - mu := &api.Mutation{} - mu.SetJson = []byte(`{"name": "Manish"}`) - assigned, err := txn.Mutate(context.Background(), mu) - if err != nil { - log.Fatalf("Error while running mutation: %v\n", err) - } - if len(assigned.Uids) != 1 { - log.Fatalf("Error. Nothing assigned. %+v\n", assigned) - } - var uid string - for _, u := range assigned.Uids { - uid = u - } - - txn2 := s.dg.NewTxn() - mu = &api.Mutation{} - mu.SetJson = []byte(fmt.Sprintf(`{"uid": "%s", "name": "Manish"}`, uid)) - x.Check2(txn2.Mutate(context.Background(), mu)) - - require.NoError(t, txn.Commit(context.Background())) - err = txn2.Commit(context.Background()) - x.AssertTrue(err != nil) - - txn = s.dg.NewTxn() - q := fmt.Sprintf(`{ me(func: uid(%s)) { name }}`, uid) - resp, err := txn.Query(context.Background(), q) - if err != nil { - log.Fatalf("Error while running query: %v\n", err) - } - x.AssertTrue(bytes.Equal(resp.Json, []byte("{\"me\":[{\"name\":\"Manish\"}]}"))) -} - -func TestConflictTimeout(t *testing.T) { - var uid string - txn := s.dg.NewTxn() - { - mu := &api.Mutation{} - mu.SetJson = []byte(`{"name": "Manish"}`) - assigned, err := txn.Mutate(context.Background(), mu) - if err != nil { - log.Fatalf("Error while running mutation: %v\n", err) - } - if len(assigned.Uids) != 1 { - log.Fatalf("Error. Nothing assigned. %+v\n", assigned) - } - for _, u := range assigned.Uids { - uid = u - } - } - - txn2 := s.dg.NewTxn() - q := fmt.Sprintf(`{ me(func: uid(%s)) { name }}`, uid) - _, err := txn2.Query(context.Background(), q) - require.NoError(t, err) - - mu := &api.Mutation{} - mu.SetJson = []byte(fmt.Sprintf(`{"uid": "%s", "name": "Jan the man"}`, uid)) - _, err = txn2.Mutate(context.Background(), mu) - if err == nil { - require.NoError(t, txn2.Commit(context.Background())) - } - - err = txn.Commit(context.Background()) - x.AssertTrue(err != nil) - - txn3 := s.dg.NewTxn() - q = fmt.Sprintf(`{ me(func: uid(%s)) { name }}`, uid) - _, err = txn3.Query(context.Background(), q) - require.NoError(t, err) -} - -func TestConflictTimeout2(t *testing.T) { - var uid string - txn := s.dg.NewTxn() - { - - mu := &api.Mutation{} - mu.SetJson = []byte(`{"name": "Manish"}`) - assigned, err := txn.Mutate(context.Background(), mu) - if err != nil { - log.Fatalf("Error while running mutation: %v\n", err) - } - if len(assigned.Uids) != 1 { - log.Fatalf("Error. Nothing assigned. %+v\n", assigned) - } - for _, u := range assigned.Uids { - uid = u - } - } - - txn2 := s.dg.NewTxn() - mu := &api.Mutation{} - mu.SetJson = []byte(fmt.Sprintf(`{"uid": "%s", "name": "Jan the man"}`, uid)) - x.Check2(txn2.Mutate(context.Background(), mu)) - - require.NoError(t, txn.Commit(context.Background())) - err := txn2.Commit(context.Background()) - x.AssertTrue(err != nil) - - txn3 := s.dg.NewTxn() - mu = &api.Mutation{} - mu.SetJson = []byte(fmt.Sprintf(`{"uid": "%s", "name": "Jan the man"}`, uid)) - assigned, err := txn3.Mutate(context.Background(), mu) - if err == nil { - require.NoError(t, txn3.Commit(context.Background())) - } - for _, u := range assigned.Uids { - uid = u - } - - txn4 := s.dg.NewTxn() - q := fmt.Sprintf(`{ me(func: uid(%s)) { name }}`, uid) - _, err = txn4.Query(context.Background(), q) - require.NoError(t, err) -} - -func TestIgnoreIndexConflict(t *testing.T) { - op := &api.Operation{} - op.DropAll = true - require.NoError(t, s.dg.Alter(context.Background(), op)) - - op = &api.Operation{} - op.Schema = `name: string @index(exact) .` - if err := s.dg.Alter(context.Background(), op); err != nil { - log.Fatal(err) - } - - txn := s.dg.NewTxn() - mu := &api.Mutation{} - mu.SetJson = []byte(`{"name": "Manish"}`) - assigned, err := txn.Mutate(context.Background(), mu) - if err != nil { - log.Fatalf("Error while running mutation: %v\n", err) - } - if len(assigned.Uids) != 1 { - log.Fatalf("Error. Nothing assigned. %+v\n", assigned) - } - var uid1, uid2 string - for _, u := range assigned.Uids { - uid1 = u - } - - txn2 := s.dg.NewTxn() - mu = &api.Mutation{} - mu.SetJson = []byte(`{"name": "Manish"}`) - assigned, err = txn2.Mutate(context.Background(), mu) - if err != nil { - log.Fatalf("Error while running mutation: %v\n", err) - } - if len(assigned.Uids) != 1 { - log.Fatalf("Error. Nothing assigned. %+v\n", assigned) - } - for _, u := range assigned.Uids { - uid2 = u - } - - require.NoError(t, txn.Commit(context.Background())) - require.NoError(t, txn2.Commit(context.Background())) - - txn = s.dg.NewTxn() - q := `{ me(func: eq(name, "Manish")) { uid }}` - resp, err := txn.Query(context.Background(), q) - require.NoError(t, err) - expectedResp := []byte(fmt.Sprintf(`{"me":[{"uid":"%s"},{"uid":"%s"}]}`, uid1, uid2)) - require.Equal(t, expectedResp, resp.Json) -} - -func TestReadIndexKeySameTxn(t *testing.T) { - op := &api.Operation{} - op.DropAll = true - require.NoError(t, s.dg.Alter(context.Background(), op)) - - op = &api.Operation{} - op.Schema = `name: string @index(exact) .` - if err := s.dg.Alter(context.Background(), op); err != nil { - log.Fatal(err) - } - - txn := s.dg.NewTxn() - mu := &api.Mutation{ - CommitNow: true, - SetJson: []byte(`{"name": "Manish"}`), - } - assigned, err := txn.Mutate(context.Background(), mu) - if err != nil { - log.Fatalf("Error while running mutation: %v\n", err) - } - if len(assigned.Uids) != 1 { - log.Fatalf("Error. Nothing assigned. %+v\n", assigned) - } - var uid string - for _, u := range assigned.Uids { - uid = u - } - - txn = s.dg.NewTxn() - defer txn.Discard(context.Background()) - q := `{ me(func: le(name, "Manish")) { uid }}` - resp, err := txn.Query(context.Background(), q) - if err != nil { - log.Fatalf("Error while running query: %v\n", err) - } - expectedResp := []byte(fmt.Sprintf(`{"me":[{"uid":"%s"}]}`, uid)) - x.AssertTrue(bytes.Equal(resp.Json, expectedResp)) -} - -func TestEmailUpsert(t *testing.T) { - op := &api.Operation{} - op.DropAll = true - require.NoError(t, s.dg.Alter(context.Background(), op)) - - op = &api.Operation{} - op.Schema = `email: string @index(exact) @upsert .` - if err := s.dg.Alter(context.Background(), op); err != nil { - log.Fatal(err) - } - - txn1 := s.dg.NewTxn() - mu := &api.Mutation{} - mu.SetJson = []byte(`{"uid": "_:user1", "email": "email@email.org"}`) - _, err := txn1.Mutate(context.Background(), mu) - assert.Nil(t, err) - - txn2 := s.dg.NewTxn() - mu = &api.Mutation{} - mu.SetJson = []byte(`{"uid": "_:user2", "email": "email@email.org"}`) - _, err = txn2.Mutate(context.Background(), mu) - assert.Nil(t, err) - - txn3 := s.dg.NewTxn() - mu = &api.Mutation{} - mu.SetJson = []byte(`{"uid": "_:user3", "email": "email3@email.org"}`) - _, err = txn3.Mutate(context.Background(), mu) - assert.Nil(t, err) - - require.NoError(t, txn1.Commit(context.Background())) - require.NotNil(t, txn2.Commit(context.Background())) - require.NoError(t, txn3.Commit(context.Background())) -} - -// TestFriendList tests that we are not able to set a node to node edge between -// the same nodes concurrently. -func TestFriendList(t *testing.T) { - op := &api.Operation{} - op.DropAll = true - require.NoError(t, s.dg.Alter(context.Background(), op)) - - op = &api.Operation{} - op.Schema = ` - friend: [uid] @reverse .` - if err := s.dg.Alter(context.Background(), op); err != nil { - log.Fatal(err) - } - - txn1 := s.dg.NewTxn() - mu := &api.Mutation{} - mu.SetJson = []byte(`{"uid": "0x01", "friend": [{"uid": "0x02"}]}`) - _, err := txn1.Mutate(context.Background(), mu) - assert.Nil(t, err) - - txn2 := s.dg.NewTxn() - mu = &api.Mutation{} - mu.SetJson = []byte(`{"uid": "0x01", "friend": [{"uid": "0x02"}]}`) - _, err = txn2.Mutate(context.Background(), mu) - assert.Nil(t, err) - - txn3 := s.dg.NewTxn() - mu = &api.Mutation{} - mu.SetJson = []byte(`{"uid": "0x01", "friend": [{"uid": "0x03"}]}`) - _, err = txn3.Mutate(context.Background(), mu) - assert.Nil(t, err) - - require.NoError(t, txn1.Commit(context.Background())) - require.NotNil(t, txn2.Commit(context.Background())) - require.NoError(t, txn3.Commit(context.Background())) -} - -// TestNameSet tests that we are not able to set a property edge for the same -// subject id concurrently. -func TestNameSet(t *testing.T) { - op := &api.Operation{} - op.DropAll = true - require.NoError(t, s.dg.Alter(context.Background(), op)) - - op = &api.Operation{} - op.Schema = `name: string .` - if err := s.dg.Alter(context.Background(), op); err != nil { - log.Fatal(err) - } - - txn1 := s.dg.NewTxn() - mu := &api.Mutation{} - mu.SetJson = []byte(`{"uid": "0x01", "name": "manish"}`) - _, err := txn1.Mutate(context.Background(), mu) - assert.Nil(t, err) - - txn2 := s.dg.NewTxn() - mu = &api.Mutation{} - mu.SetJson = []byte(`{"uid": "0x01", "name": "contributor"}`) - _, err = txn2.Mutate(context.Background(), mu) - assert.Nil(t, err) - - require.NoError(t, txn1.Commit(context.Background())) - require.NotNil(t, txn2.Commit(context.Background())) -} - -// retrieve the uids in the uidMap in the order of ascending keys -func retrieveUids(uidMap map[string]string) []string { - keys := make([]string, 0, len(uidMap)) - for key := range uidMap { - keys = append(keys, key) - } - - sort.Slice(keys, func(i, j int) bool { - num1 := strings.Split(keys[i], ".")[2] - - num2 := strings.Split(keys[j], ".")[2] - n1, err := strconv.Atoi(num1) - x.Check(err) - n2, err := strconv.Atoi(num2) - x.Check(err) - return n1 < n2 - }) - - uids := make([]string, 0, len(uidMap)) - for _, k := range keys { - uids = append(uids, uidMap[k]) - } - return uids -} - -func TestSPStar(t *testing.T) { - op := &api.Operation{} - op.DropAll = true - require.NoError(t, s.dg.Alter(context.Background(), op)) - - op = &api.Operation{} - op.Schema = `friend: [uid] .` - require.NoError(t, s.dg.Alter(context.Background(), op)) - - txn := s.dg.NewTxn() - mu := &api.Mutation{} - mu.SetJson = []byte(`{"name": "Manish", "friend": [{"name": "Jan"}]}`) - assigned, err := txn.Mutate(context.Background(), mu) - require.Equal(t, 2, len(assigned.Uids)) - uid1 := retrieveUids(assigned.Uids)[0] - require.NoError(t, err) - require.Equal(t, 2, len(assigned.Uids)) - require.NoError(t, txn.Commit(context.Background())) - - txn = s.dg.NewTxn() - mu = &api.Mutation{} - dgo.DeleteEdges(mu, uid1, "friend") - assigned, err = txn.Mutate(context.Background(), mu) - require.NoError(t, err) - require.Equal(t, 0, len(assigned.Uids)) - - mu = &api.Mutation{} - mu.SetJson = []byte(fmt.Sprintf(`{"uid": "%s" ,"name": "Manish", "friend": [{"name": "Jan2"}]}`, uid1)) - assigned, err = txn.Mutate(context.Background(), mu) - require.NoError(t, err) - require.Equal(t, 1, len(assigned.Uids)) - uid2 := retrieveUids(assigned.Uids)[0] - - q := fmt.Sprintf(`{ - me(func: uid(%s)) { - uid - friend { - uid - name - } - } - }`, uid1) - - resp, err := txn.Query(context.Background(), q) - require.NoError(t, err) - expectedResp := fmt.Sprintf(`{"me":[{"uid":"%s", "friend": [{"name": "Jan2", "uid":"%s"}]}]}`, uid1, uid2) - require.JSONEq(t, expectedResp, string(resp.Json)) -} - -func TestSPStar2(t *testing.T) { - op := &api.Operation{} - op.DropAll = true - require.NoError(t, s.dg.Alter(context.Background(), op)) - - op = &api.Operation{} - op.Schema = `friend: [uid] .` - require.NoError(t, s.dg.Alter(context.Background(), op)) - - // Add edge - txn := s.dg.NewTxn() - mu := &api.Mutation{} - mu.SetJson = []byte(`{"name": "Manish", "friend": [{"name": "Jan"}]}`) - assigned, err := txn.Mutate(context.Background(), mu) - - require.NoError(t, err) - require.Equal(t, 2, len(assigned.Uids)) - - uids := retrieveUids(assigned.Uids) - uid1 := uids[0] - uid2 := uids[1] - q := fmt.Sprintf(`{ - me(func: uid(%s)) { - uid - friend { - uid - name - } - } - }`, uid1) - - resp, err := txn.Query(context.Background(), q) - require.NoError(t, err) - expectedResp := fmt.Sprintf(`{"me":[{"uid":"%s", "friend": [{"name": "Jan", "uid":"%s"}]}]}`, uid1, uid2) - require.JSONEq(t, expectedResp, string(resp.Json)) - - // Delete S P * - mu = &api.Mutation{} - dgo.DeleteEdges(mu, uid1, "friend") - assigned, err = txn.Mutate(context.Background(), mu) - require.NoError(t, err) - require.Equal(t, 0, len(assigned.Uids)) - - resp, err = txn.Query(context.Background(), q) - require.NoError(t, err) - expectedResp = fmt.Sprintf(`{"me":[{"uid":"%s"}]}`, uid1) - require.JSONEq(t, expectedResp, string(resp.Json)) - - // Add edge - mu = &api.Mutation{} - mu.SetJson = []byte(fmt.Sprintf(`{"uid": "%s" ,"name": "Manish", "friend": [{"name": "Jan2"}]}`, uid1)) - assigned, err = txn.Mutate(context.Background(), mu) - require.NoError(t, err) - require.Equal(t, 1, len(assigned.Uids)) - uid3 := retrieveUids(assigned.Uids)[0] - resp, err = txn.Query(context.Background(), q) - require.NoError(t, err) - expectedResp = fmt.Sprintf(`{"me":[{"uid":"%s", "friend": [{"name": "Jan2", "uid":"%s"}]}]}`, - uid1, uid3) - require.JSONEq(t, expectedResp, string(resp.Json)) - - // Delete S P * - mu = &api.Mutation{} - dgo.DeleteEdges(mu, uid1, "friend") - assigned, err = txn.Mutate(context.Background(), mu) - require.NoError(t, err) - require.Equal(t, 0, len(assigned.Uids)) - - resp, err = txn.Query(context.Background(), q) - require.NoError(t, err) - expectedResp = fmt.Sprintf(`{"me":[{"uid":"%s"}]}`, uid1) - require.JSONEq(t, expectedResp, string(resp.Json)) - - // Add edge - mu = &api.Mutation{} - mu.SetJson = []byte(fmt.Sprintf(`{"uid": "%s" ,"name": "Manish", "friend": [{"name": "Jan3"}]}`, uid1)) - assigned, err = txn.Mutate(context.Background(), mu) - require.NoError(t, err) - require.Equal(t, 1, len(assigned.Uids)) - - uid4 := retrieveUids(assigned.Uids)[0] - resp, err = txn.Query(context.Background(), q) - require.NoError(t, err) - expectedResp = fmt.Sprintf(`{"me":[{"uid":"%s", "friend": [{"name": "Jan3", "uid":"%s"}]}]}`, uid1, uid4) - require.JSONEq(t, expectedResp, string(resp.Json)) -} - -var ( - ctxb = context.Background() - countQuery = ` -query countAnswers($num: int) { - me(func: eq(count(answer), $num)) { - uid - count(answer) - } -} -` -) - -func TestCountIndexConcurrentTxns(t *testing.T) { - dg, err := testutil.DgraphClientWithGroot(testutil.SockAddr) - x.Check(err) - testutil.DropAll(t, dg) - alterSchema(dg, "answer: [uid] @count .") - - // Expected edge count of 0x100: 1 - txn0 := dg.NewTxn() - mu := api.Mutation{SetNquads: []byte("<0x100> <0x200> .")} - _, err = txn0.Mutate(ctxb, &mu) - x.Check(err) - err = txn0.Commit(ctxb) - x.Check(err) - - // The following two mutations are in separate interleaved txns. - txn1 := dg.NewTxn() - mu = api.Mutation{SetNquads: []byte("<0x1> <0x2> .")} - _, err = txn1.Mutate(ctxb, &mu) - x.Check(err) - - txn2 := dg.NewTxn() - mu = api.Mutation{SetNquads: []byte("<0x1> <0x3> .")} - _, err = txn2.Mutate(ctxb, &mu) - x.Check(err) - - err = txn1.Commit(ctxb) - x.Check(err) - err = txn2.Commit(ctxb) - require.Error(t, err, - "the txn2 should be aborted due to concurrent update on the count index of <0x01>") - - // retry the mutation - txn3 := dg.NewTxn() - _, err = txn3.Mutate(ctxb, &mu) - x.Check(err) - err = txn3.Commit(ctxb) - x.Check(err) - - // Verify count queries - txn := dg.NewReadOnlyTxn() - vars := map[string]string{"$num": "1"} - resp, err := txn.QueryWithVars(ctxb, countQuery, vars) - x.Check(err) - js := string(resp.GetJson()) - require.JSONEq(t, - `{"me": [{"count(answer)": 1, "uid": "0x100"}]}`, - js) - txn = dg.NewReadOnlyTxn() - vars = map[string]string{"$num": "2"} - resp, err = txn.QueryWithVars(ctxb, countQuery, vars) - x.Check(err) - js = string(resp.GetJson()) - require.JSONEq(t, - `{"me": [{"count(answer)": 2, "uid": "0x1"}]}`, - js) -} - -func TestCountIndexSerialTxns(t *testing.T) { - dg, err := testutil.DgraphClientWithGroot(testutil.SockAddr) - x.Check(err) - testutil.DropAll(t, dg) - alterSchema(dg, "answer: [uid] @count .") - - // Expected Edge count of 0x100: 1 - txn0 := dg.NewTxn() - mu := api.Mutation{SetNquads: []byte("<0x100> <0x200> .")} - _, err = txn0.Mutate(ctxb, &mu) - require.NoError(t, err) - err = txn0.Commit(ctxb) - require.NoError(t, err) - - // Expected edge count of 0x1: 2 - // This should NOT appear in the query result - // The following two mutations are in serial txns. - txn1 := dg.NewTxn() - mu = api.Mutation{SetNquads: []byte("<0x1> <0x2> .")} - _, err = txn1.Mutate(ctxb, &mu) - require.NoError(t, err) - err = txn1.Commit(ctxb) - require.NoError(t, err) - - txn2 := dg.NewTxn() - mu = api.Mutation{SetNquads: []byte("<0x1> <0x3> .")} - _, err = txn2.Mutate(ctxb, &mu) - require.NoError(t, err) - err = txn2.Commit(ctxb) - require.NoError(t, err) - - // Verify query - txn := dg.NewReadOnlyTxn() - vars := map[string]string{"$num": "1"} - resp, err := txn.QueryWithVars(ctxb, countQuery, vars) - require.NoError(t, err) - js := string(resp.GetJson()) - require.JSONEq(t, - `{"me": [{"count(answer)": 1, "uid": "0x100"}]}`, - js) - txn = dg.NewReadOnlyTxn() - vars = map[string]string{"$num": "2"} - resp, err = txn.QueryWithVars(ctxb, countQuery, vars) - require.NoError(t, err) - js = string(resp.GetJson()) - require.JSONEq(t, - `{"me": [{"count(answer)": 2, "uid": "0x1"}]}`, - js) -} - -func TestCountIndexSameTxn(t *testing.T) { - dg, err := testutil.DgraphClientWithGroot(testutil.SockAddr) - x.Check(err) - testutil.DropAll(t, dg) - alterSchema(dg, "answer: [uid] @count .") - - // Expected Edge count of 0x100: 1 - txn0 := dg.NewTxn() - mu := api.Mutation{SetNquads: []byte("<0x100> <0x200> .")} - _, err = txn0.Mutate(ctxb, &mu) - x.Check(err) - err = txn0.Commit(ctxb) - x.Check(err) - - // Expected edge count of 0x1: 2 - // This should NOT appear in the query result - // The following two mutations are in the same txn. - txn1 := dg.NewTxn() - mu = api.Mutation{SetNquads: []byte("<0x1> <0x2> .")} - _, err = txn1.Mutate(ctxb, &mu) - x.Check(err) - mu = api.Mutation{SetNquads: []byte("<0x1> <0x3> .")} - _, err = txn1.Mutate(ctxb, &mu) - x.Check(err) - err = txn1.Commit(ctxb) - x.Check(err) - - // Verify query - txn := dg.NewReadOnlyTxn() - vars := map[string]string{"$num": "1"} - resp, err := txn.QueryWithVars(ctxb, countQuery, vars) - x.Check(err) - js := string(resp.GetJson()) - require.JSONEq(t, - `{"me": [{"count(answer)": 1, "uid": "0x100"}]}`, - js) - txn = dg.NewReadOnlyTxn() - vars = map[string]string{"$num": "2"} - resp, err = txn.QueryWithVars(ctxb, countQuery, vars) - x.Check(err) - js = string(resp.GetJson()) - require.JSONEq(t, - `{"me": [{"count(answer)": 2, "uid": "0x1"}]}`, - js) -} - -func TestConcurrentQueryMutate(t *testing.T) { - testutil.DropAll(t, s.dg) - alterSchema(s.dg, "name: string .") - - txn := s.dg.NewTxn() - defer txn.Discard(context.Background()) - - // Do one query, so a new timestamp is assigned to the txn. - q := `{me(func: uid(0x01)) { name }}` - _, err := txn.Query(context.Background(), q) - require.NoError(t, err) - - var wg sync.WaitGroup - wg.Add(2) - start := time.Now() - go func() { - defer wg.Done() - for time.Since(start) < 5*time.Second { - mu := &api.Mutation{} - mu.SetJson = []byte(`{"uid": "0x01", "name": "manish"}`) - _, err := txn.Mutate(context.Background(), mu) - assert.Nil(t, err) - } - }() - - go func() { - defer wg.Done() - for time.Since(start) < 5*time.Second { - _, err := txn.Query(context.Background(), q) - require.NoError(t, err) - } - }() - wg.Wait() - t.Logf("Done\n") -} - -func TestTxnDiscardBeforeCommit(t *testing.T) { - testutil.DropAll(t, s.dg) - alterSchema(s.dg, "name: string .") - - txn := s.dg.NewTxn() - mu := &api.Mutation{ - SetNquads: []byte(`_:1 "abc" .`), - } - _, err := txn.Mutate(context.Background(), mu) - require.NoError(t, err, "unable to mutate") - - err = txn.Discard(context.Background()) - // Since client is discarding this transaction server should not throw ErrAborted err. - require.NotEqual(t, err, dgo.ErrAborted) -} - -func alterSchema(dg *dgo.Dgraph, schema string) { - op := api.Operation{Schema: schema} - x.Check(dg.Alter(ctxb, &op)) -} diff --git a/outserv/cmd/alpha/http.go b/outserv/cmd/alpha/http.go index 2375f6098..fae9eb400 100644 --- a/outserv/cmd/alpha/http.go +++ b/outserv/cmd/alpha/http.go @@ -137,6 +137,7 @@ func queryHandler(w http.ResponseWriter, r *http.Request) { if commonHandler(w, r) { return } + glog.Warningln("/query endpoint is DEPRECATED and would be removed in future versions.") isDebugMode, err := parseBool(r, "debug") if err != nil { @@ -274,156 +275,6 @@ func queryHandler(w http.ResponseWriter, r *http.Request) { } } -func mutationHandler(w http.ResponseWriter, r *http.Request) { - if commonHandler(w, r) { - return - } - - commitNow, err := parseBool(r, "commitNow") - if err != nil { - x.SetStatus(w, x.ErrorInvalidRequest, err.Error()) - return - } - startTs, err := parseUint64(r, "startTs") - hash := r.URL.Query().Get("hash") - if err != nil { - x.SetStatus(w, x.ErrorInvalidRequest, err.Error()) - return - } - body := readRequest(w, r) - if body == nil { - return - } - - // start parsing the query - parseStart := time.Now() - - var req *pb.Request - contentType := r.Header.Get("Content-Type") - mediaType, contentTypeParams, err := mime.ParseMediaType(contentType) - if err != nil { - x.SetStatus(w, x.ErrorInvalidRequest, "Invalid Content-Type") - } - if charset, ok := contentTypeParams["charset"]; ok && strings.ToLower(charset) != "utf-8" { - x.SetStatus(w, x.ErrorInvalidRequest, "Unsupported charset. "+ - "Supported charset is UTF-8") - return - } - - switch mediaType { - case "application/json": - ms := make(map[string]*skipJSONUnmarshal) - if err := json.Unmarshal(body, &ms); err != nil { - jsonErr := convertJSONError(string(body), err) - x.SetStatus(w, x.ErrorInvalidRequest, jsonErr.Error()) - return - } - - req = &pb.Request{} - if queryText, ok := ms["query"]; ok && queryText != nil { - req.Query, err = strconv.Unquote(string(queryText.bs)) - if err != nil { - x.SetStatus(w, x.ErrorInvalidRequest, err.Error()) - return - } - } - - // JSON API support both keys 1. mutations 2. set,delete,cond - // We want to maintain the backward compatibility of the API here. - extractMutation := func(jsMap map[string]*skipJSONUnmarshal) (*pb.Mutation, error) { - mu := &pb.Mutation{} - empty := true - if setJSON, ok := jsMap["set"]; ok && setJSON != nil { - empty = false - mu.SetJson = setJSON.bs - } - if delJSON, ok := jsMap["delete"]; ok && delJSON != nil { - empty = false - mu.DeleteJson = delJSON.bs - } - if condText, ok := jsMap["cond"]; ok && condText != nil { - mu.Cond, err = strconv.Unquote(string(condText.bs)) - if err != nil { - return nil, err - } - } - - if empty { - return nil, nil - } - - return mu, nil - } - if mu, err := extractMutation(ms); err != nil { - x.SetStatus(w, x.ErrorInvalidRequest, err.Error()) - return - } else if mu != nil { - req.Mutations = append(req.Mutations, mu) - } - if mus, ok := ms["mutations"]; ok && mus != nil { - var mm []map[string]*skipJSONUnmarshal - if err := json.Unmarshal(mus.bs, &mm); err != nil { - jsonErr := convertJSONError(string(mus.bs), err) - x.SetStatus(w, x.ErrorInvalidRequest, jsonErr.Error()) - return - } - - for _, m := range mm { - if mu, err := extractMutation(m); err != nil { - x.SetStatus(w, x.ErrorInvalidRequest, err.Error()) - return - } else if mu != nil { - req.Mutations = append(req.Mutations, mu) - } - } - } - - default: - x.SetStatus(w, x.ErrorInvalidRequest, "Unsupported Content-Type. "+ - "Supported content types are application/json") - return - } - - // end of query parsing - parseEnd := time.Now() - - req.StartTs = startTs - req.Hash = hash - req.CommitNow = commitNow - - ctx := x.AttachAccessJwt(context.Background(), r) - resp, err := edgraph.Query(ctx, req) - if err != nil { - x.SetStatusWithData(w, x.ErrorInvalidRequest, err.Error()) - return - } - // Add cost to the header. - w.Header().Set(x.DgraphCostHeader, fmt.Sprint(resp.Metrics.NumUids["_total"])) - - resp.Latency.ParsingNs = uint64(parseEnd.Sub(parseStart).Nanoseconds()) - e := query.Extensions{ - Txn: resp.Txn, - Latency: resp.Latency, - } - - response := map[string]interface{}{} - response["extensions"] = e - mp := map[string]interface{}{} - mp["code"] = x.Success - mp["message"] = "Done" - mp["uids"] = resp.Txn.GetUids() - mp["queries"] = json.RawMessage(resp.Json) - response["data"] = mp - - js, err := json.Marshal(response) - if err != nil { - x.SetStatusWithData(w, x.Error, err.Error()) - return - } - - _, _ = x.WriteResponse(w, r, js) -} - func alterHandler(w http.ResponseWriter, r *http.Request) { if commonHandler(w, r) { return diff --git a/outserv/cmd/alpha/run.go b/outserv/cmd/alpha/run.go index 56ef0dc2e..120750982 100644 --- a/outserv/cmd/alpha/run.go +++ b/outserv/cmd/alpha/run.go @@ -595,8 +595,7 @@ func setupServer() { baseMux.HandleFunc("/query", queryHandler) baseMux.HandleFunc("/query/", queryHandler) - baseMux.HandleFunc("/mutate", mutationHandler) - baseMux.HandleFunc("/mutate/", mutationHandler) + // TODO: Remove alter endpoint later. baseMux.HandleFunc("/alter", alterHandler) baseMux.HandleFunc("/health", healthCheck) baseMux.HandleFunc("/state", stateHandler)