Skip to content
Closed
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,5 @@ x/log_test/*.enc
*.buf
.osgrep
.worktrees/
AGENTS.md
CLAUDE.md
12 changes: 10 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@
```bash
git clone https://github.com/dgraph-io/dgraph.git
cd ./dgraph
make install
make setup # auto-install tool dependencies (gotestsum, ack, etc.)
make install # build and install the dgraph binary
```

This will put the source code in a Git repo under `$GOPATH/src/github.com/dgraph-io/dgraph` and
Expand Down Expand Up @@ -144,16 +145,23 @@ directory, providing control and flexibility beyond the standard Go testing fram
The simplest way to run tests is via Make:

```bash
# Run all tests
# First-time setup: install tool dependencies
make setup

# Run default tests (~30 min): unit, systest, core suites + integration2
make test

# Run every test in the repo
make test-full

# Run specific test types
make test-unit # Unit tests only (no Docker)
make test-integration2 # Integration2 tests via dgraphtest
make test-upgrade # Upgrade tests

# Use variables for more control
make test TAGS=integration2 PKG=systest/vector
make test SUITE=all # All t/ runner suites
make test TIMEOUT=90m # Override per-package timeout (default: 30m)
```

Expand Down
84 changes: 67 additions & 17 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,20 @@ ifeq ($(GOPATH),)
$(error GOPATH is not set. Please set it explicitly, e.g. export GOPATH=$$HOME/go)
endif

# On non-Linux systems, use a separate directory for Linux binaries
# On non-Linux systems, use a separate directory for Linux binaries and
# a cross-compiler so that CGO is available (required for plugin support).
ifeq ($(GOHOSTOS),linux)
export LINUX_GOBIN ?= $(GOPATH)/bin
LINUX_CC ?= gcc
else
export LINUX_GOBIN ?= $(GOPATH)/linux_$(GOHOSTARCH)
ifeq ($(GOHOSTARCH),arm64)
LINUX_CC ?= aarch64-unknown-linux-gnu-gcc
else ifeq ($(GOHOSTARCH),amd64)
LINUX_CC ?= x86_64-unknown-linux-gnu-gcc
else
LINUX_CC ?= gcc
endif
endif

######################
Expand Down Expand Up @@ -60,7 +69,7 @@ install: ## Install dgraph binary
ifneq ($(GOHOSTOS),linux)
@mkdir -p $(LINUX_GOBIN)
@echo "Installing dgraph (linux/$(GOHOSTARCH))..."
@GOOS=linux GOARCH=$(GOHOSTARCH) $(MAKE) -C dgraph dgraph
@GOOS=linux GOARCH=$(GOHOSTARCH) CGO_ENABLED=1 CC=$(LINUX_CC) $(MAKE) -C dgraph BUILD_TAGS= EXTLDFLAGS=-fuse-ld=bfd dgraph
@mv dgraph/dgraph $(LINUX_GOBIN)/dgraph
@echo "Installed dgraph (linux/$(GOHOSTARCH)) to $(LINUX_GOBIN)/dgraph"
endif
Expand All @@ -78,8 +87,16 @@ dgraph-installed:
$(MAKE) install; \
fi

.PHONY: deps
deps: ## Check test dependencies (pass AUTO_INSTALL=true to auto-install missing ones)
$(MAKE) -C t deps

.PHONY: setup
setup: ## Install all test dependencies automatically
$(MAKE) deps AUTO_INSTALL=true

.PHONY: test
test: dgraph-installed local-image ## Run tests (see 'make help' for options)
test: dgraph-installed local-image ## Run tests (default: unit,systest,core + integration2)
ifdef TAGS
@echo "Running tests with tags: $(TAGS)"
go test -v --tags="$(TAGS)" \
Expand All @@ -97,62 +114,87 @@ else
done
endif
else
@echo "Running test suite: $(or $(SUITE),all)"
$(MAKE) -C t test args="--suite=$(or $(SUITE),all) $(if $(PKG),--pkg=\"$(PKG)\") $(if $(TEST),--test=\"$(TEST)\") $(if $(TIMEOUT),--timeout=$(TIMEOUT))"
ifdef SUITE
@echo "Running test suite: $(SUITE)"
$(MAKE) -C t test args="--suite=$(SUITE) $(if $(PKG),--pkg=\"$(PKG)\") $(if $(TEST),--test=\"$(TEST)\") $(if $(TIMEOUT),--timeout=$(TIMEOUT))"
else
@echo "Running test suites: unit, systest, core"
$(MAKE) -C t test args="--suite=unit,systest,core $(if $(PKG),--pkg=\"$(PKG)\") $(if $(TEST),--test=\"$(TEST)\") $(if $(TIMEOUT),--timeout=$(TIMEOUT))"
@echo "Running integration2 tests..."
go test -v --tags="integration2" \
$(if $(TEST),--run="$(TEST)") \
$(if $(PKG),./$(PKG)/...,./...)
endif
endif

.PHONY: test-all
test-all: ## All test suites via t/ runner (i.e. 'make test SUITE=all')
@SUITE=all $(MAKE) test
.PHONY: test-suite
test-suite: ## Run t/ runner suite (default: all). Ex: make test-suite SUITE=unit
@SUITE=$(or $(SUITE),all) $(MAKE) test

.PHONY: test-unit
test-unit: ## Unit tests, no Docker (i.e. 'make test SUITE=unit')
test-unit: ## Unit tests (i.e. 'make test SUITE=unit')
$(if $(filter command line,$(origin SUITE)),$(error SUITE= cannot be passed to test-unit; use 'make test SUITE=...' instead))
@SUITE=unit $(MAKE) test

.PHONY: test-core
test-core: ## Core tests (i.e. 'make test SUITE=core')
$(if $(filter command line,$(origin SUITE)),$(error SUITE= cannot be passed to test-core; use 'make test SUITE=...' instead))
@SUITE=core $(MAKE) test

.PHONY: test-integration
test-integration: ## Integration tests (i.e. 'make test TAGS=integration')
@TAGS=integration $(MAKE) test

.PHONY: test-integration2
test-integration2: ## Integration2 tests via dgraphtest (i.e. 'make test TAGS=integration2')
$(if $(filter command line,$(origin TAGS)),$(error TAGS= cannot be passed to test-integration2; use 'make test TAGS=...' instead))
@TAGS=integration2 $(MAKE) test

.PHONY: test-upgrade
test-upgrade: ## Upgrade tests (i.e. 'make test TAGS=upgrade')
$(if $(filter command line,$(origin TAGS)),$(error TAGS= cannot be passed to test-upgrade; use 'make test TAGS=...' instead))
@TAGS=upgrade $(MAKE) test

.PHONY: test-systest
test-systest: ## System integration tests (i.e. 'make test SUITE=systest')
$(if $(filter command line,$(origin SUITE)),$(error SUITE= cannot be passed to test-systest; use 'make test SUITE=...' instead))
@SUITE=systest $(MAKE) test

.PHONY: test-vector
test-vector: ## Vector search tests (i.e. 'make test SUITE=vector')
$(if $(filter command line,$(origin SUITE)),$(error SUITE= cannot be passed to test-vector; use 'make test SUITE=...' instead))
@SUITE=vector $(MAKE) test

.PHONY: test-fuzz
test-fuzz: ## Fuzz tests, auto-discovers packages (i.e. 'make test FUZZ=1')
test-fuzz: ## Fuzz tests (i.e. 'make test FUZZ=1')
$(if $(filter command line,$(origin FUZZ)),$(error FUZZ= cannot be passed to test-fuzz; use 'make test FUZZ=...' instead))
@FUZZ=1 $(MAKE) test

.PHONY: test-ldbc
test-ldbc: ## LDBC benchmark tests (i.e. 'make test SUITE=ldbc')
$(if $(filter command line,$(origin SUITE)),$(error SUITE= cannot be passed to test-ldbc; use 'make test SUITE=...' instead))
@SUITE=ldbc $(MAKE) test

.PHONY: test-load
test-load: ## Heavy load tests (i.e. 'make test SUITE=load')
$(if $(filter command line,$(origin SUITE)),$(error SUITE= cannot be passed to test-load; use 'make test SUITE=...' instead))
@SUITE=load $(MAKE) test

.PHONY: test-full
test-full: ## Every test: all suites + integration2 + upgrade + fuzz
$(MAKE) test-suite
$(MAKE) test-integration2
$(MAKE) test-upgrade
$(MAKE) test-fuzz

.PHONY: test-benchmark
test-benchmark: ## Go benchmarks (i.e. 'go test -bench')
go test -bench=. -benchmem $(if $(PKG),./$(PKG)/...,./...)

.PHONY: local-image
local-image: ## Build local Docker image (dgraph/dgraph:local)
@echo building local docker image
@GOOS=linux GOARCH=amd64 $(MAKE) dgraph
ifneq ($(GOHOSTOS),linux)
@GOOS=linux GOARCH=$(GOHOSTARCH) CGO_ENABLED=1 CC=$(LINUX_CC) $(MAKE) BUILD_TAGS= EXTLDFLAGS=-fuse-ld=bfd dgraph
else
@GOOS=linux GOARCH=$(GOHOSTARCH) $(MAKE) dgraph
endif
@mkdir -p linux
@mv ./dgraph/dgraph ./linux/dgraph
@docker build -f contrib/Dockerfile -t dgraph/dgraph:local .
Expand All @@ -161,6 +203,13 @@ local-image: ## Build local Docker image (dgraph/dgraph:local)
.PHONY: image-local
image-local: local-image ## Alias for local-image

.PHONY: clean
clean: ## Clean build artifacts
$(MAKE) -C dgraph clean
$(MAKE) -C compose clean
@rm -rf linux
@go clean -testcache

.PHONY: docker-image
docker-image: dgraph ## Build Docker image (dgraph/dgraph:$VERSION)
@mkdir -p linux
Expand Down Expand Up @@ -201,7 +250,7 @@ help: ## Show available targets and variables
awk 'BEGIN {FS = ":.*?## "}; {printf " %-20s %s\n", $$1, $$2}'
@echo ""
@echo "Variables that can be passed to 'test':"
@echo " SUITE Select t/ runner suite (e.g., make test SUITE=systest)"
@echo " SUITE Select t/ runner suite (default: unit,systest,core + integration2)"
@echo " TAGS Go build tags - bypasses t/ runner (e.g., make test TAGS=integration2)"
@echo " PKG Limit to specific package (e.g., make test PKG=systest/export)"
@echo " TEST Run specific test function (e.g., make test TEST=TestGQLSchema)"
Expand All @@ -216,8 +265,9 @@ help: ## Show available targets and variables
@printf " Available TAGS values: "
@grep -roh "//go:build [a-z0-9]*" --include="*_test.go" . 2>/dev/null | \
awk '{print $$2}' | \
grep -E '^(integration|integration2|upgrade)$$' | \
grep -E '^(integration2|upgrade)$$' | \
sort -u | tr '\n' ' ' && echo ""
@echo " Note: 'integration' tests require the t/ runner (use SUITE=, not TAGS=)"
@echo ""
@echo "Examples:"
@echo " make test TAGS=integration2 PKG=systest/vector # integration2 tests for vector"
Expand Down
44 changes: 26 additions & 18 deletions TESTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,20 +128,24 @@ The codebase is organized into several key packages:

Before running tests, ensure you have the following installed and configured.

> **TL;DR:** On a fresh checkout, just run `make install` followed by `make test`. The build system
> automatically handles OS detection, builds the correct binaries, and validates dependencies.
> **TL;DR:** On a fresh checkout, run `make setup` to auto-install tool dependencies, then
> `make install` followed by `make test`. The build system automatically handles OS detection,
> builds the correct binaries, and validates dependencies.

### Automatic Dependency Checking

The test framework includes scripts that check for required dependencies and can optionally
auto-install them:

```bash
# Check all dependencies (run from t/ directory)
cd t && make check
# Auto-install all missing tool dependencies (recommended for first-time setup)
make setup

# Auto-install missing dependencies
AUTO_INSTALL=true make check
# Check dependencies without installing (reports what's missing)
make deps

# Same as 'make deps' but auto-installs anything missing
make deps AUTO_INSTALL=true
```

The check scripts validate:
Expand All @@ -154,9 +158,8 @@ The check scripts validate:

### Required Tools

> **Note:** You don't need to install these manually. Running `AUTO_INSTALL=true make check` from
> the `t/` directory (or `AUTO_INSTALL=true make test` from the repo root) automatically installs
> missing dependencies. The commands below are listed for reference.
> **Note:** You don't need to install these manually. Running `make setup` from the repo root
> automatically installs missing dependencies. The commands below are listed for reference.

#### 1. Go (1.21+)

Expand Down Expand Up @@ -222,8 +225,8 @@ dgraph version
The build system now handles most setup automatically. On both Linux and macOS:

```bash
# Install dependencies (optional - auto-installs if missing)
cd t && AUTO_INSTALL=true make check && cd ..
# Auto-install tool dependencies (gotestsum, ack, etc.)
make setup

# Build dgraph binary (automatically handles Linux binary on macOS)
make install
Expand Down Expand Up @@ -304,21 +307,23 @@ If both pass, you're ready to run all test types!
The simplest way to run tests:

```bash
# Run all tests (default)
# Run default tests (~30 min): unit, systest, core suites + integration2
make test

# Run every test in the repo (all suites + all tag-based tests + fuzz)
make test-full

# Common shortcuts (run 'make help' for full list)
make test-all # All test suites via t/ runner (i.e. 'make test SUITE=all')
make test-unit # Unit tests, no Docker (i.e. 'make test SUITE=unit')
make test-suite # All t/ runner suites (default), or: make test-suite SUITE=unit
make test-unit # Unit tests (i.e. 'make test SUITE=unit')
make test-core # Core tests (i.e. 'make test SUITE=core')
make test-systest # System integration tests (i.e. 'make test SUITE=systest')
make test-vector # Vector search tests (i.e. 'make test SUITE=vector')
make test-ldbc # LDBC benchmark tests (i.e. 'make test SUITE=ldbc')
make test-load # Heavy load tests (i.e. 'make test SUITE=load')
make test-integration # Integration tests (i.e. 'make test TAGS=integration')
make test-integration2 # Integration2 tests via dgraphtest (i.e. 'make test TAGS=integration2')
make test-upgrade # Upgrade tests (i.e. 'make test TAGS=upgrade')
make test-fuzz # Fuzz tests, auto-discovers packages (i.e. 'make test FUZZ=1')
make test-fuzz # Fuzz tests (i.e. 'make test FUZZ=1')
make test-benchmark # Go benchmarks (i.e. 'go test -bench')
```

Expand All @@ -339,7 +344,8 @@ For more control, pass variables to `make test`:
| `FUZZ` | Enable fuzz testing | `make test FUZZ=1` |
| `FUZZTIME` | Fuzz duration per package | `make test FUZZ=1 FUZZTIME=60s` |

**Precedence:** `TAGS` > `FUZZ` > `SUITE` (first match wins)
**Precedence:** `TAGS` > `FUZZ` > `SUITE` > default (first match wins). When no variable is set,
`make test` runs suites `unit,systest,core` plus `integration2`.

### Examples

Expand Down Expand Up @@ -1288,14 +1294,16 @@ The following items from the original wishlist have been implemented:

- **✅ Unified test interface:** A single `make test` entry point that accepts arguments to run any
test type (unit, integration, integration2, upgrade, fuzz) with environment variables for control.
The default (`make test` with no args) runs `unit,systest,core` suites plus `integration2` for a
fast feedback loop (~30 min). Use `make test-full` to run all tests.

- **✅ Example commands that "just work":** The following now work as expected:

```bash
make test SUITE=systest
make test FUZZ=1 PKG=dql
make test TAGS=upgrade PKG=acl
make test TAGS=integration PKG=systest/plugin
make test-suite SUITE=systest PKG=systest/plugin
```

### Remaining Ideas
Expand Down
3 changes: 2 additions & 1 deletion dgraph/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ gitBranch = github.com/dgraph-io/dgraph/v25/x.gitBranch
lastCommitSHA = github.com/dgraph-io/dgraph/v25/x.lastCommitSHA
lastCommitTime = github.com/dgraph-io/dgraph/v25/x.lastCommitTime

BUILD_FLAGS ?= -ldflags '-X ${lastCommitSHA}=${BUILD} -X "${lastCommitTime}=${BUILD_DATE}" -X "${dgraphVersion}=${BUILD_VERSION}" -X "${dgraphCodename}=${BUILD_CODENAME}" -X ${gitBranch}=${BUILD_BRANCH}'
EXTLDFLAGS ?=
BUILD_FLAGS ?= -ldflags '-X ${lastCommitSHA}=${BUILD} -X "${lastCommitTime}=${BUILD_DATE}" -X "${dgraphVersion}=${BUILD_VERSION}" -X "${dgraphCodename}=${BUILD_CODENAME}" -X ${gitBranch}=${BUILD_BRANCH}$(if $(EXTLDFLAGS), -extldflags "$(EXTLDFLAGS)")'

# Insert build tags if specified
ifneq ($(strip $(BUILD_TAGS)),)
Expand Down
30 changes: 27 additions & 3 deletions dgraphtest/local_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -1322,11 +1322,19 @@ func (c *LocalCluster) GeneratePlugins(raceEnabled bool) error {
if raceEnabled {
opts = append(opts, "-race")
}
opts = append(opts, "-buildmode=plugin", "-o", so, src)
os.Setenv("GOOS", "linux")
os.Setenv("GOARCH", "amd64")
opts = append(opts, "-buildmode=plugin")
if runtime.GOOS != "linux" {
// Use the BFD linker; the default gold linker is not shipped
// with most cross-compiler toolchains.
opts = append(opts, "-ldflags", "-extldflags -fuse-ld=bfd")
}
opts = append(opts, "-o", so, src)
cmd := exec.Command("go", opts...)
cmd.Dir = filepath.Dir(curr)
cmd.Env = append(os.Environ(), "GOOS=linux", "GOARCH="+runtime.GOARCH)
if runtime.GOOS != "linux" {
cmd.Env = append(cmd.Env, "CGO_ENABLED=1", "CC="+linuxCrossCC())
}
if out, err := cmd.CombinedOutput(); err != nil {
log.Printf("Error: %v\n", err)
log.Printf("Output: %v\n", string(out))
Expand All @@ -1347,6 +1355,22 @@ func (c *LocalCluster) GeneratePlugins(raceEnabled bool) error {
return nil
}

// linuxCrossCC returns the C cross-compiler for targeting Linux from the current host.
// Respects the LINUX_CC environment variable if set.
func linuxCrossCC() string {
if cc := os.Getenv("LINUX_CC"); cc != "" {
return cc
}
switch runtime.GOARCH {
case "arm64":
return "aarch64-unknown-linux-gnu-gcc"
case "amd64":
return "x86_64-unknown-linux-gnu-gcc"
default:
return "gcc"
}
}

func (c *LocalCluster) GetAlphaGrpcPublicPort(id int) (string, error) {
return publicPort(c.dcli, c.alphas[id], alphaGrpcPort)
}
Expand Down
Loading
Loading