Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
21b5aea
test: add import compliance tests
JonathanOppenheimer Nov 21, 2025
7e33965
test: tweak violation wording
JonathanOppenheimer Nov 21, 2025
404acd5
test: add violation to show failure example
JonathanOppenheimer Nov 21, 2025
dec282e
test: remove violation
JonathanOppenheimer Nov 21, 2025
234a039
test: only enforce on vms/evm directory
JonathanOppenheimer Nov 21, 2025
9a39d6b
test: clarify boundaries
JonathanOppenheimer Nov 22, 2025
5017e1e
test: rename test
JonathanOppenheimer Nov 22, 2025
e490151
test: clarify comments
JonathanOppenheimer Nov 22, 2025
f411817
chore: lint
JonathanOppenheimer Nov 22, 2025
84fbb35
test: add license violation test
JonathanOppenheimer Nov 22, 2025
498915c
test: inline once used type
JonathanOppenheimer Nov 22, 2025
f4fbfac
tests: rename libevm test
JonathanOppenheimer Nov 22, 2025
69e8354
chore: fix typo
JonathanOppenheimer Nov 22, 2025
be5228a
test: remove licensing test (excessive)
JonathanOppenheimer Nov 24, 2025
d607b78
Merge branch 'master' into JonathanOppenheimer/import-testing
JonathanOppenheimer Nov 24, 2025
99ed2ce
test: check both evm code locations
JonathanOppenheimer Nov 24, 2025
e9cc48b
test: move import tests to evm directory
JonathanOppenheimer Nov 24, 2025
cbcd663
test: reconsider boundary tests
JonathanOppenheimer Nov 24, 2025
f482da4
Update vms/evm/imports_test.go
JonathanOppenheimer Dec 1, 2025
c4b31fc
test: use Arran's rewritten test
JonathanOppenheimer Dec 1, 2025
7d513d4
fix: add .go
JonathanOppenheimer Dec 1, 2025
40e5904
Merge branch 'master' into JonathanOppenheimer/import-testing
JonathanOppenheimer Dec 1, 2025
b6541d1
chore: lint
JonathanOppenheimer Dec 1, 2025
70f33bc
chore: move comment
JonathanOppenheimer Dec 1, 2025
57f083c
docs: document functions
JonathanOppenheimer Dec 1, 2025
63a88d9
Update vms/evm/imports_test.go
JonathanOppenheimer Dec 2, 2025
249e7cd
Update vms/evm/imports_test.go
JonathanOppenheimer Dec 2, 2025
fee0356
Update vms/evm/imports_test.go
JonathanOppenheimer Dec 2, 2025
d24963b
test: use absolute file paths
JonathanOppenheimer Dec 2, 2025
7578a3f
Merge branch 'master' into JonathanOppenheimer/import-testing
JonathanOppenheimer Dec 9, 2025
892dc3b
test: remove outdated / unneeded import tests
JonathanOppenheimer Dec 12, 2025
247e2d7
Merge branch 'master' into JonathanOppenheimer/import-testing
JonathanOppenheimer Dec 16, 2025
6f76cfa
test: enforce way graft/evm import direction
JonathanOppenheimer Dec 16, 2025
74c3da1
Update vms/evm/imports_test.go
JonathanOppenheimer Dec 16, 2025
a180d44
fix: maru feedback
JonathanOppenheimer Dec 16, 2025
e3d87f0
fix: austin feedback
JonathanOppenheimer Dec 16, 2025
d4164ec
fix: cleanup boolean logic
JonathanOppenheimer Dec 16, 2025
f252545
Merge branch 'master' into JonathanOppenheimer/import-testing
JonathanOppenheimer Dec 16, 2025
0a94664
Merge remote-tracking branch 'origin/master' into JonathanOppenheimer…
JonathanOppenheimer Dec 17, 2025
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
146 changes: 0 additions & 146 deletions graft/coreth/plugin/evm/imports_test.go

This file was deleted.

46 changes: 0 additions & 46 deletions graft/coreth/scripts/eth-allowed-packages.txt

This file was deleted.

120 changes: 120 additions & 0 deletions vms/evm/imports_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// Copyright (C) 2019-2025, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package evm

import (
"fmt"
"go/parser"
"go/token"
"io/fs"
"path/filepath"
"strings"
"testing"

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

const (
corethImport = "github.com/ava-labs/avalanchego/graft/coreth"
subnetEVMImport = "github.com/ava-labs/avalanchego/graft/subnet-evm"
)

// TestImportViolations ensures proper import rules:
// - graft/coreth can be imported anywhere EXCEPT vms/evm (but vms/evm/emulate is an exception)
// - graft/subnet-evm can only be imported within graft/subnet-evm itself and vms/evm/emulate
// - graft/evm can NOT import from graft/coreth or graft/subnet-evm
//
// The rationale for these rules are as follows:
//
// coreth can be imported in AvalancheGo, because it was already imported by Avalanche prior to
// grafting
//
// coreth can NOT be imported in the vms/evm package, because the goal is that vms/evm should
// only contain the 'clean' properly uplifted code, that meets AvalancheGo quality standards.
//
// subnet-evm can NOT be imported anywhere in AvalancheGo besides graft/subnet-evm itself,
// because it must not become a direct dependency of AvalancheGo or mix directly with coreth.
//
// graft/evm is the shared code that both coreth and subnet-evm will depend on, so it must not
// import from either of them to avoid a circular dependency.
//
// both coreth and subnet-evm can be imported in the vms/evm/emulate package, because it
// allows consumers to use both coreth and subnet-evm registration at the same time.
//
// TODO(jonathanoppenheimer): remove the graft functionality once the graft package is removed.
func TestImportViolations(t *testing.T) {
const root = "../.."
repoRoot, err := filepath.Abs(root)
require.NoError(t, err)

graftDir := filepath.Join(repoRoot, "graft")
graftEVMDir := filepath.Join(graftDir, "evm")
graftSubnetEVMDir := filepath.Join(graftDir, "subnet-evm")
vmsEVMDir := filepath.Join(repoRoot, "vms", "evm")
emulateDir := filepath.Join(vmsEVMDir, "emulate")

var violations []string

err = filepath.Walk(root, func(file string, _ fs.FileInfo, err error) error {
if err != nil {
return err
}
if strings.ToLower(filepath.Ext(file)) != ".go" {
return nil
}

absFile, err := filepath.Abs(file)
if err != nil {
return err
}

node, err := parser.ParseFile(token.NewFileSet(), file, nil, parser.ImportsOnly)
if err != nil {
return fmt.Errorf("parser.ParseFile(..., %q, ...): %w", file, err)
}

inGraftEVM := strings.HasPrefix(absFile, graftEVMDir)
inGraftSubnetEVM := strings.HasPrefix(absFile, graftSubnetEVMDir)
inEmulate := strings.HasPrefix(absFile, emulateDir)
inVMsEVM := strings.HasPrefix(absFile, vmsEVMDir)

for _, spec := range node.Imports {
if spec.Path == nil {
continue
}
importPath := strings.Trim(spec.Path.Value, `"`)

importsCoreth := isImportIn(importPath, corethImport)
importsSubnetEVM := isImportIn(importPath, subnetEVMImport)

hasViolation := (importsCoreth && inVMsEVM && !inEmulate || // vm/evm can't import coreth
importsSubnetEVM && !inGraftSubnetEVM && !inEmulate || // vm/evm can't import subnet-evm
(importsCoreth || importsSubnetEVM) && inGraftEVM) // graft/evm can't import coreth or subnet-evm
if hasViolation {
violations = append(violations, fmt.Sprintf("File %q imports %q", file, importPath))
}
}
return nil
})

require.NoErrorf(t, err, "filepath.Walk(%q)", root)
require.Empty(t, violations, "import violations found")
}

func isImportIn(importPath, targetedImport string) bool {
if importPath == targetedImport {
return true
}

// importPath must be at least len(targetedImport) + 1 to be a subpackage
// (e.g., "github.com/foo/x" is len("github.com/foo") + 2, minimum subpackage length)
if len(importPath) < len(targetedImport)+1 {
return false
}

// Check if importPath is a subpackage by ensuring it has the targetedImport prefix
// AND the next character is '/'. This is to prevent false positives where one
// package name is a prefix of another like "github.com/foo" vs "github.com/foobar".
return strings.HasPrefix(importPath, targetedImport) && importPath[len(targetedImport)] == '/'
}