Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(upgrade): add upgrade tests for systest/plugin #8896

Merged
merged 7 commits into from
Aug 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions dgraphtest/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ type ClusterConfig struct {
portOffset int // exposed port offset for grpc/http port for both alpha/zero
bulkOutDir string
featureFlags []string
customPlugins bool
}

// NewClusterConfig generates a default ClusterConfig
Expand All @@ -134,6 +135,7 @@ func NewClusterConfig() ClusterConfig {
refillInterval: 20 * time.Second,
uidLease: 50,
portOffset: -1,
customPlugins: false,
}
}

Expand Down Expand Up @@ -225,3 +227,9 @@ func (cc ClusterConfig) WithNormalizeCompatibilityMode(mode string) ClusterConfi
cc.featureFlags = append(cc.featureFlags, fmt.Sprintf("normalize-compatibility-mode=%v", mode))
return cc
}

// Enables generation of the custom_plugins in testutil/custom_plugins
func (cc ClusterConfig) WithCustomPlugins() ClusterConfig {
mangalaman93 marked this conversation as resolved.
Show resolved Hide resolved
cc.customPlugins = true
return cc
}
7 changes: 6 additions & 1 deletion dgraphtest/dgraph.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ const (
DefaultUser = "groot"
DefaultPassword = "password"

goBinMountPath = "/gobin"
localVersion = "local"
waitDurBeforeRetry = time.Second
requestTimeout = 120 * time.Second
Expand Down Expand Up @@ -278,6 +279,10 @@ func (a *alpha) cmd(c *LocalCluster) []string {
acmd = append(acmd, fmt.Sprintf("--feature-flags=%v", strings.Join(c.conf.featureFlags, ";")))
}

if c.conf.customPlugins {
acmd = append(acmd, fmt.Sprintf("--custom_tokenizers=%s", c.customTokenizers))
}

return acmd
}

Expand Down Expand Up @@ -385,7 +390,7 @@ func mountBinary(c *LocalCluster) (mount.Mount, error) {
return mount.Mount{
Type: mount.TypeBind,
Source: c.tempBinDir,
Target: "/gobin",
Target: goBinMountPath,
ReadOnly: true,
}, nil
}
6 changes: 6 additions & 0 deletions dgraphtest/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ func (c *LocalCluster) dgraphImage() string {
}

func (c *LocalCluster) setupBinary() error {
if c.conf.customPlugins {
race := false // Explicit var declaration to avoid confusion on the next line
if err := c.GeneratePlugins(race); err != nil {
return err
}
}
if c.conf.version == localVersion {
fromDir := filepath.Join(os.Getenv("GOPATH"), "bin")
return copyBinary(fromDir, c.tempBinDir, c.conf.version)
Expand Down
56 changes: 54 additions & 2 deletions dgraphtest/local_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"os"
"os/exec"
"path/filepath"
"runtime"
"strconv"
"strings"
"time"
Expand Down Expand Up @@ -57,7 +58,9 @@ type LocalCluster struct {
tempBinDir string
tempSecretsDir string
encKeyPath string
lowerThanV21 bool

lowerThanV21 bool
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need this boolean?

customTokenizers string

// resources
dcli *docker.Client
Expand Down Expand Up @@ -384,9 +387,15 @@ func (c *LocalCluster) StopAlpha(id int) error {
func (c *LocalCluster) stopContainer(dc dnode) error {
ctx, cancel := context.WithTimeout(context.Background(), requestTimeout)
defer cancel()
stopTimeout := 30 // in seconds

stopTimeout := 30
mangalaman93 marked this conversation as resolved.
Show resolved Hide resolved
o := container.StopOptions{Timeout: &stopTimeout}
if err := c.dcli.ContainerStop(ctx, dc.cid(), o); err != nil {
// Force kill the container if timeout exceeded
if strings.Contains(err.Error(), "context deadline exceeded") {
_ = c.dcli.ContainerKill(ctx, dc.cid(), "KILL")
return nil
}
return errors.Wrapf(err, "error stopping container [%v]", dc.cname())
}
return nil
Expand Down Expand Up @@ -976,3 +985,46 @@ func runOpennssl(args ...string) error {
}
return nil
}

func (c *LocalCluster) GeneratePlugins(raceEnabled bool) error {
_, curr, _, ok := runtime.Caller(0)
if !ok {
return errors.New("error while getting current file")
}
var soFiles []string
for i, src := range []string{
"../testutil/custom_plugins/anagram/main.go",
"../testutil/custom_plugins/cidr/main.go",
"../testutil/custom_plugins/factor/main.go",
"../testutil/custom_plugins/rune/main.go",
} {
so := c.tempBinDir + "/plugins/" + strconv.Itoa(i) + ".so"
log.Printf("compiling plugin: src=%q so=%q\n", src, so)
opts := []string{"build"}
if raceEnabled {
opts = append(opts, "-race")
}
opts = append(opts, "-buildmode=plugin", "-o", so, src)
os.Setenv("GOOS", "linux")
os.Setenv("GOARCH", "amd64")
cmd := exec.Command("go", opts...)
cmd.Dir = filepath.Dir(curr)
if out, err := cmd.CombinedOutput(); err != nil {
log.Printf("Error: %v\n", err)
log.Printf("Output: %v\n", string(out))
return err
}
absSO, err := filepath.Abs(so)
if err != nil {
log.Printf("Error: %v\n", err)
return err
}
soFiles = append(soFiles, absSO)
}

sofiles := strings.Join(soFiles, ",")
c.customTokenizers = strings.ReplaceAll(sofiles, c.tempBinDir, goBinMountPath)
log.Printf("plugin build completed. Files are: %s\n", sofiles)

return nil
}
53 changes: 53 additions & 0 deletions systest/plugin/integration_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
//go:build integration

/*
* Copyright 2023 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 (
"testing"

"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"

"github.com/dgraph-io/dgraph/dgraphtest"
)

type PluginTestSuite struct {
suite.Suite
dc dgraphtest.Cluster
}

func (psuite *PluginTestSuite) SetupTest() {
psuite.dc = dgraphtest.NewComposeCluster()
}

func (psuite *PluginTestSuite) TearDownTest() {
t := psuite.T()
gcli, cleanup, err := psuite.dc.Client()
mangalaman93 marked this conversation as resolved.
Show resolved Hide resolved
require.NoError(t, err)
defer cleanup()
require.NoError(t, gcli.DropAll())
}

func (psuite *PluginTestSuite) Upgrade() {
// Not implemented for integration tests
}

func TestPluginTestSuite(t *testing.T) {
suite.Run(t, new(PluginTestSuite))
}
106 changes: 53 additions & 53 deletions systest/plugin/plugin_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//go:build integration
//go:build integration || upgrade

/*
* Copyright 2017-2023 Dgraph Labs, Inc. and Contributors
Expand All @@ -19,53 +19,25 @@
package main

import (
"context"
"testing"
"time"
"fmt"

"github.com/stretchr/testify/require"

"github.com/dgraph-io/dgo/v230/protos/api"
"github.com/dgraph-io/dgraph/testutil"
"github.com/dgraph-io/dgraph/dgraphtest"
)

func TestPlugins(t *testing.T) {
if testing.Short() {
t.Skip("skipping test in short mode")
}

type testCase struct {
query string
wantResult string
}

client, err := testutil.DgraphClient(testutil.SockAddr)
require.NoError(t, err)
suite := func(initialSchema string, setJSON string, cases []testCase) {
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()

require.NoError(t, client.Alter(ctx, &api.Operation{
DropAll: true,
}))
require.NoError(t, client.Alter(ctx, &api.Operation{
Schema: initialSchema,
}))

txn := client.NewTxn()
_, err = txn.Mutate(ctx, &api.Mutation{SetJson: []byte(setJSON)})
require.NoError(t, err)
require.NoError(t, txn.Commit(ctx))

for _, test := range cases {
txn := client.NewTxn()
reply, err := txn.Query(ctx, test.query)
require.NoError(t, err)
testutil.CompareJSON(t, test.wantResult, string(reply.GetJson()))
}
}
type testCase struct {
mangalaman93 marked this conversation as resolved.
Show resolved Hide resolved
query string
wantResult string
}

suite(
var testInp = []struct {
initialSchema string
setJSON string
cases []testCase
}{
{
"word: string @index(anagram) .",
`[
{ "word": "airmen" },
Expand Down Expand Up @@ -104,9 +76,8 @@ func TestPlugins(t *testing.T) {
]}`,
},
},
)

suite(
},
{
"word: string @index(anagram) @lang .",
`[
{ "word@en": "airmen", "word@fr": "no match" },
Expand All @@ -122,9 +93,8 @@ func TestPlugins(t *testing.T) {
]}`,
},
},
)

suite(
},
{
"ip: string @index(cidr) .",
`[
{ "ip": "100.55.22.11/32" },
Expand Down Expand Up @@ -173,9 +143,8 @@ func TestPlugins(t *testing.T) {
]}`,
},
},
)

suite(
},
{
"name: string @index(rune) .",
`[
{ "name": "Adam" },
Expand Down Expand Up @@ -247,8 +216,8 @@ func TestPlugins(t *testing.T) {
]}`,
},
},
)
suite(
},
{
"num: int @index(factor) .",
`[
{ "num": 2 },
Expand Down Expand Up @@ -332,5 +301,36 @@ func TestPlugins(t *testing.T) {
]}`,
},
},
)
},
}

func (psuite *PluginTestSuite) TestPlugins() {
for i := 0; i < len(testInp); i++ {
psuite.Run(fmt.Sprintf("test case %d", i+1), func() {
t := psuite.T()
gcli, cleanup, err := psuite.dc.Client()
require.NoError(t, err)
defer cleanup()
require.NoError(t, gcli.DropAll())
require.NoError(t, gcli.SetupSchema(testInp[i].initialSchema))
_, err = gcli.Mutate(&api.Mutation{
SetJson: []byte(testInp[i].setJSON),
CommitNow: true,
})
require.NoError(t, err)

// Upgrade
psuite.Upgrade()

gcli, cleanup, err = psuite.dc.Client()
require.NoError(t, err)
defer cleanup()

for _, test := range testInp[i].cases {
reply, err := gcli.Query(test.query)
require.NoError(t, err)
dgraphtest.CompareJSON(test.wantResult, string(reply.GetJson()))
}
})
}
}
Loading