Skip to content
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
88 changes: 71 additions & 17 deletions make/test.mk
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,51 @@ TEST_PACKAGES_SHORT = \

TEST_PACKAGES_SHORT_HOST := $(filter $(TEST_PACKAGES_SHORT),$(TEST_PACKAGES_HOST) $(TEST_PACKAGES_SLOW))
TEST_PACKAGES_PRINTER_HOST := $(filter go/printer,$(TEST_PACKAGES_HOST))
TEST_PACKAGES_ALLOCS_HOST := $(filter slices strings,$(TEST_PACKAGES_HOST))
TEST_ALLOCS_SKIP_FLAG := -skip='^(TestBuilderAllocs|TestBuilderGrow|TestGrow)$$'
TEST_PACKAGES_ALLOC_SHA := crypto/sha256 crypto/sha512
TEST_ALLOC_SHA_SKIP_FLAG := -skip='^(TestExtraMethods|TestAllocations|TestAllocatonsWithTypeAsserts)$$'
TEST_PACKAGES_ALLOC_STRCONV := strconv
TEST_ALLOC_STRCONV_SKIP_FLAG := -skip='^(TestCountMallocs|TestAllocationsFromBytes)$$'
TEST_PACKAGES_ALLOC_UNICODE := unicode/utf16 unicode/utf8
TEST_ALLOC_UNICODE_SKIP_FLAG := -skip='^(TestAllocationsDecode|TestRuneCountNonASCIIAllocation)$$'
TEST_PACKAGES_ALLOC_CONTEXT := context
TEST_ALLOC_CONTEXT_SKIP_FLAG := -skip='^TestAllocs$$'
TEST_PACKAGES_ALLOC_MIME := mime
TEST_ALLOC_MIME_SKIP_FLAG := -skip='^TestLookupMallocs$$'
TEST_PACKAGES_ALLOC_TEXTPROTO := net/textproto
TEST_ALLOC_TEXTPROTO_SKIP_FLAG := -skip='^TestCommonHeaders$$'
TEST_PACKAGES_ALLOC_REFLECT := reflect
TEST_ALLOC_REFLECT_SKIP_FLAG := -skip='^(TestMapIterSet|TestDeepEqualAllocs)$$'
TEST_PACKAGES_ALLOC_BYTES := bytes
TEST_ALLOC_BYTES_SKIP_FLAG := -skip='^(TestNewBufferShallow|TestEqual|TestIndex|TestLastIndex|TestReplace)$$'
TEST_PACKAGES_ALLOC_SLICES := slices
TEST_ALLOC_SLICES_SKIP_FLAG := -skip='^(TestGrow|TestInsert|TestConcat)$$'
TEST_PACKAGES_ALLOC_STRINGS := strings
TEST_ALLOC_STRINGS_SKIP_FLAG := -skip='^(TestBuilderAllocs|TestBuilderGrow|TestBuilderGrowSizeclasses|TestIndexRune|TestReplace)$$'
TEST_PACKAGES_ALLOCS := \
$(TEST_PACKAGES_ALLOC_SHA) \
$(TEST_PACKAGES_ALLOC_STRCONV) \
$(TEST_PACKAGES_ALLOC_UNICODE) \
$(TEST_PACKAGES_ALLOC_CONTEXT) \
$(TEST_PACKAGES_ALLOC_MIME) \
$(TEST_PACKAGES_ALLOC_TEXTPROTO) \
$(TEST_PACKAGES_ALLOC_REFLECT) \
$(TEST_PACKAGES_ALLOC_BYTES) \
$(TEST_PACKAGES_ALLOC_SLICES) \
$(TEST_PACKAGES_ALLOC_STRINGS) \
$(nil)

define run-tinygo-alloc-tests
$(if $(filter $(TEST_PACKAGES_ALLOC_SHA),$(1)),$(3) $(TINYGO) test $(2) $(TEST_ALLOC_SHA_SKIP_FLAG) $(filter $(TEST_PACKAGES_ALLOC_SHA),$(1)))
$(if $(filter $(TEST_PACKAGES_ALLOC_STRCONV),$(1)),$(3) $(TINYGO) test $(2) $(TEST_ALLOC_STRCONV_SKIP_FLAG) $(filter $(TEST_PACKAGES_ALLOC_STRCONV),$(1)))
$(if $(filter $(TEST_PACKAGES_ALLOC_UNICODE),$(1)),$(3) $(TINYGO) test $(2) $(TEST_ALLOC_UNICODE_SKIP_FLAG) $(filter $(TEST_PACKAGES_ALLOC_UNICODE),$(1)))
$(if $(filter $(TEST_PACKAGES_ALLOC_CONTEXT),$(1)),$(3) $(TINYGO) test $(2) $(TEST_ALLOC_CONTEXT_SKIP_FLAG) $(filter $(TEST_PACKAGES_ALLOC_CONTEXT),$(1)))
$(if $(filter $(TEST_PACKAGES_ALLOC_MIME),$(1)),$(3) $(TINYGO) test $(2) $(TEST_ALLOC_MIME_SKIP_FLAG) $(filter $(TEST_PACKAGES_ALLOC_MIME),$(1)))
$(if $(filter $(TEST_PACKAGES_ALLOC_TEXTPROTO),$(1)),$(3) $(TINYGO) test $(2) $(TEST_ALLOC_TEXTPROTO_SKIP_FLAG) $(filter $(TEST_PACKAGES_ALLOC_TEXTPROTO),$(1)))
$(if $(filter $(TEST_PACKAGES_ALLOC_REFLECT),$(1)),$(3) $(TINYGO) test $(2) $(TEST_ALLOC_REFLECT_SKIP_FLAG) $(filter $(TEST_PACKAGES_ALLOC_REFLECT),$(1)))
$(if $(filter $(TEST_PACKAGES_ALLOC_BYTES),$(1)),$(3) $(TINYGO) test $(2) $(TEST_ALLOC_BYTES_SKIP_FLAG) $(filter $(TEST_PACKAGES_ALLOC_BYTES),$(1)))
$(if $(filter $(TEST_PACKAGES_ALLOC_SLICES),$(1)),$(3) $(TINYGO) test $(2) $(TEST_ALLOC_SLICES_SKIP_FLAG) $(filter $(TEST_PACKAGES_ALLOC_SLICES),$(1)))
$(if $(filter $(TEST_PACKAGES_ALLOC_STRINGS),$(1)),$(3) $(TINYGO) test $(2) $(TEST_ALLOC_STRINGS_SKIP_FLAG) $(filter $(TEST_PACKAGES_ALLOC_STRINGS),$(1)))
endef
TEST_PACKAGES_NETIP_HOST := $(filter net/netip,$(TEST_PACKAGES_HOST))

# Test known-working standard library packages.
Expand All @@ -230,18 +273,16 @@ tinygo-test:
@# TestExtraMethods: used by many crypto packages and uses reflect.Type.Method which is not implemented.
@# TestUnmarshalNestingLimit{Slice,Struct}: encoding/asn1 nesting limit added in
@# https://github.com/golang/go/commit/6a6d115f9a7422b2fa081ba6f567eefb4a099462
$(TINYGO) test $(TEST_ADDITIONAL_FLAGS) $(TEST_SKIP_FLAG) $(filter-out encoding/xml $(TEST_PACKAGES_SHORT) $(TEST_PACKAGES_PRINTER_HOST) $(TEST_PACKAGES_ALLOCS_HOST) $(TEST_PACKAGES_NETIP_HOST),$(TEST_PACKAGES_HOST) $(TEST_PACKAGES_SLOW))
$(TINYGO) test $(TEST_ADDITIONAL_FLAGS) $(TEST_SKIP_FLAG) $(filter-out encoding/xml $(TEST_PACKAGES_SHORT) $(TEST_PACKAGES_PRINTER_HOST) $(TEST_PACKAGES_ALLOCS) $(TEST_PACKAGES_NETIP_HOST),$(TEST_PACKAGES_HOST) $(TEST_PACKAGES_SLOW))
ifneq ($(TEST_PACKAGES_SHORT_HOST),)
$(TINYGO) test $(TEST_ADDITIONAL_FLAGS) $(TEST_SKIP_FLAG) -short $(TEST_PACKAGES_SHORT_HOST)
endif
ifneq ($(TEST_PACKAGES_PRINTER_HOST),)
$(TINYGO) test $(TEST_ADDITIONAL_FLAGS) -stack-size=1MB $(TEST_PACKAGES_PRINTER_HOST)
endif
ifneq ($(TEST_PACKAGES_ALLOCS_HOST),)
$(TINYGO) test $(TEST_ADDITIONAL_FLAGS) $(TEST_ALLOCS_SKIP_FLAG) $(TEST_PACKAGES_ALLOCS_HOST)
endif
$(call run-tinygo-alloc-tests,$(TEST_PACKAGES_HOST) $(TEST_PACKAGES_SLOW),$(TEST_ADDITIONAL_FLAGS))
ifneq ($(TEST_PACKAGES_NETIP_HOST),)
$(TINYGO) test $(TEST_ADDITIONAL_FLAGS) -skip='^TestAddrStringAllocs$$' $(TEST_PACKAGES_NETIP_HOST)
$(TINYGO) test $(TEST_ADDITIONAL_FLAGS) -skip='^TestAddrStringAllocs$$|^TestNoAllocs$$/^(Addr.IsGlobalUnicast|Addr.IsInterfaceLocalMulticast|Addr.IsLinkLocalMulticast|Addr.IsLinkLocalUnicast|Addr.IsPrivate)$$' $(TEST_PACKAGES_NETIP_HOST)
endif
$(TINYGO) test $(TEST_ADDITIONAL_FLAGS) -skip='^(TestReflectFuncOf|TestChannelMovedOutOfBubble|TestTimerFromInsideBubble|TestWaitGroupMovedIntoBubble|TestWaitGroupMovedOutOfBubble|TestWaitGroupMovedBetweenBubblesWithNonZeroCount)$$' internal/synctest
$(TINYGO) test $(TEST_ADDITIONAL_FLAGS) -skip='^(TestFatal|TestError|TestVerboseError|TestSkip|TestVerboseSkip|TestHelper|TestHTTPTransport100Continue)$$' testing/synctest
Expand All @@ -256,9 +297,13 @@ ifeq ($(TEST_IOFS),true)
$(TINYGO) test -stack-size=6MB io/fs
endif
tinygo-test-fast:
$(TINYGO) test $(TEST_SKIP_FLAG) $(filter-out $(TEST_PACKAGES_ALLOCS_HOST),$(TEST_PACKAGES_HOST))
ifneq ($(TEST_PACKAGES_ALLOCS_HOST),)
$(TINYGO) test $(TEST_ALLOCS_SKIP_FLAG) $(TEST_PACKAGES_ALLOCS_HOST)
$(TINYGO) test $(TEST_SKIP_FLAG) $(filter-out encoding/xml $(TEST_PACKAGES_PRINTER_HOST) $(TEST_PACKAGES_ALLOCS),$(TEST_PACKAGES_HOST))
ifneq ($(TEST_PACKAGES_PRINTER_HOST),)
$(TINYGO) test -stack-size=1MB $(TEST_PACKAGES_PRINTER_HOST)
endif
$(call run-tinygo-alloc-tests,$(TEST_PACKAGES_HOST))
ifeq ($(TEST_ENCODING_XML),true)
$(TINYGO) test $(TEST_SKIP_FLAG) -short -stack-size=16MB encoding/xml
endif
tinygo-bench:
$(TINYGO) test -bench . $(TEST_PACKAGES_HOST) $(TEST_PACKAGES_SLOW)
Expand All @@ -267,18 +312,24 @@ tinygo-bench-fast:

# Same thing, except for wasi rather than the current platform.
tinygo-test-wasm:
$(TINYGO) test -target wasm $(TEST_SKIP_FLAG) $(TEST_PACKAGES_WASM)
$(TINYGO) test -target wasm $(TEST_SKIP_FLAG) $(filter-out $(TEST_PACKAGES_ALLOCS),$(TEST_PACKAGES_WASM))
$(call run-tinygo-alloc-tests,$(TEST_PACKAGES_WASM),-target wasm)
tinygo-test-wasi:
$(TINYGO) test -target wasip1 $(TEST_SKIP_FLAG) $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW) ./tests/runtime_wasi
$(TINYGO) test -target wasip1 $(TEST_SKIP_FLAG) $(filter-out $(TEST_PACKAGES_ALLOCS),$(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW)) ./tests/runtime_wasi
$(call run-tinygo-alloc-tests,$(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW),-target wasip1)
tinygo-test-wasip1:
GOOS=wasip1 GOARCH=wasm $(TINYGO) test $(TEST_SKIP_FLAG) $(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW) ./tests/runtime_wasi
GOOS=wasip1 GOARCH=wasm $(TINYGO) test $(TEST_SKIP_FLAG) $(filter-out $(TEST_PACKAGES_ALLOCS),$(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW)) ./tests/runtime_wasi
$(call run-tinygo-alloc-tests,$(TEST_PACKAGES_FAST) $(TEST_PACKAGES_SLOW),,GOOS=wasip1 GOARCH=wasm)
tinygo-test-wasip1-fast:
$(TINYGO) test -target=wasip1 $(TEST_SKIP_FLAG) $(TEST_PACKAGES_FAST_WASI) ./tests/runtime_wasi
$(TINYGO) test -target=wasip1 $(TEST_SKIP_FLAG) $(filter-out $(TEST_PACKAGES_ALLOCS),$(TEST_PACKAGES_FAST_WASI)) ./tests/runtime_wasi
$(call run-tinygo-alloc-tests,$(TEST_PACKAGES_FAST_WASI),-target=wasip1)

tinygo-test-wasip2-slow:
$(TINYGO) test -target=wasip2 $(TEST_SKIP_FLAG) $(TEST_PACKAGES_SLOW)
$(TINYGO) test -target=wasip2 $(TEST_SKIP_FLAG) $(filter-out $(TEST_PACKAGES_ALLOCS),$(TEST_PACKAGES_SLOW))
$(call run-tinygo-alloc-tests,$(TEST_PACKAGES_SLOW),-target=wasip2)
tinygo-test-wasip2-fast:
$(TINYGO) test -target=wasip2 $(TEST_SKIP_FLAG) $(TEST_PACKAGES_FAST_WASIP2) ./tests/runtime_wasi
$(TINYGO) test -target=wasip2 $(TEST_SKIP_FLAG) $(filter-out $(TEST_PACKAGES_ALLOCS),$(TEST_PACKAGES_FAST_WASIP2)) ./tests/runtime_wasi
$(call run-tinygo-alloc-tests,$(TEST_PACKAGES_FAST_WASIP2),-target=wasip2)

tinygo-test-wasip2-sum-slow:
TINYGO=$(TINYGO) \
Expand All @@ -304,7 +355,10 @@ tinygo-bench-wasip2-fast:

# Run tests on riscv-qemu since that one provides a large amount of memory.
tinygo-test-baremetal:
$(TINYGO) test -target riscv-qemu $(TEST_SKIP_FLAG) $(TEST_PACKAGES_BAREMETAL)
$(TINYGO) test -target riscv-qemu $(TEST_SKIP_FLAG) $(filter-out $(TEST_PACKAGES_ALLOCS),$(TEST_PACKAGES_BAREMETAL))
$(if $(filter $(TEST_PACKAGES_ALLOC_STRCONV),$(TEST_PACKAGES_BAREMETAL)),$(TINYGO) test -target riscv-qemu -skip='TestCountMallocs|TestAllocationsFromBytes' $(filter $(TEST_PACKAGES_ALLOC_STRCONV),$(TEST_PACKAGES_BAREMETAL)))
$(if $(filter $(TEST_PACKAGES_ALLOC_UNICODE),$(TEST_PACKAGES_BAREMETAL)),$(TINYGO) test -target riscv-qemu -skip='TestAllocationsDecode|TestRuneCountNonASCIIAllocation' $(filter $(TEST_PACKAGES_ALLOC_UNICODE),$(TEST_PACKAGES_BAREMETAL)))
$(if $(filter $(TEST_PACKAGES_ALLOC_REFLECT),$(TEST_PACKAGES_BAREMETAL)),$(TINYGO) test -target riscv-qemu -skip='TestMapIterSet|TestDeepEqualAllocs' $(filter $(TEST_PACKAGES_ALLOC_REFLECT),$(TEST_PACKAGES_BAREMETAL)))

# Test external packages in a large corpus.
test-corpus:
Expand Down
7 changes: 7 additions & 0 deletions src/runtime/gc_blocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -912,6 +912,13 @@ func ReadMemStats(m *MemStats) {
gcLock.Unlock()
}

func mallocs() uint64 {
gcLock.Lock()
mallocs := gcMallocs
gcLock.Unlock()
return mallocs
}

// count4LUT is a lookup table used to count set bits in a 4-bit mask.
// TODO: replace with popcnt when available
var count4LUT = [16]uint8{
Expand Down
13 changes: 12 additions & 1 deletion src/runtime/gc_boehm.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ const (
boehmNormalKind = 1
)

var gcLock task.PMutex
var (
gcLock task.PMutex
gcMallocs uint64
)

func initHeap() {
libgc_init()
Expand Down Expand Up @@ -74,6 +77,7 @@ func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer {
}

gcLock.Lock()
gcMallocs++

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

are we allowed to use an atomic here; istm that there are two calls, add(1) to increment, and return add(0) to get the current mallocs count.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

oh, but its a double word :( ok, lock it is

var ptr unsafe.Pointer
var needsZero bool
switch layout {
Expand Down Expand Up @@ -200,6 +204,13 @@ func ReadMemStats(m *MemStats) {
gcLock.Unlock()
}

func mallocs() uint64 {
gcLock.Lock()
mallocs := gcMallocs
gcLock.Unlock()
return mallocs
}

func setHeapEnd(newHeapEnd uintptr) {
runtimeFatal("gc: did not expect setHeapEnd call")
}
Expand Down
6 changes: 6 additions & 0 deletions src/runtime/gc_custom.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ func SetFinalizer(obj interface{}, finalizer interface{})
// ReadMemStats populates m with memory statistics.
func ReadMemStats(ms *MemStats)

func mallocs() uint64 {
var stats MemStats
ReadMemStats(&stats)
return stats.Mallocs
}

func setHeapEnd(newHeapEnd uintptr) {
// Heap is in custom GC so ignore for when called from wasm initialization.
}
7 changes: 7 additions & 0 deletions src/runtime/gc_leaking.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,13 @@ func ReadMemStats(m *MemStats) {
gcLock.Unlock()
}

func mallocs() uint64 {
gcLock.Lock()
mallocs := gcMallocs
gcLock.Unlock()
return mallocs
}

func GC() {
// No-op.
}
Expand Down
4 changes: 4 additions & 0 deletions src/runtime/gc_none.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ func GC() {
// Unimplemented.
}

func mallocs() uint64 {
return 0
}

func markRoots(start, end uintptr) {
runtimeFatal("unreachable: markRoots")
}
Expand Down
23 changes: 23 additions & 0 deletions src/testing/allocs_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package testing_test

import "testing"

var (
allocations [101]*byte
allocation int
)

func TestAllocsPerRun(t *testing.T) {
allocs := testing.AllocsPerRun(100, func() {
allocations[allocation] = new(byte)
allocation++
})
if allocs != 1 {
t.Errorf("got %v allocations, want 1", allocs)
}
for i := 1; i < len(allocations); i++ {
if allocations[i] == allocations[i-1] {
t.Fatalf("allocations %d and %d have the same address", i-1, i)
}
}
}
13 changes: 10 additions & 3 deletions src/testing/testing.go
Original file line number Diff line number Diff line change
Expand Up @@ -977,16 +977,23 @@ func (t *T) report() {
// AllocsPerRun returns the average number of allocations during calls to f.
// Although the return value has type float64, it will always be an integral
// value.
//
// Not implemented.
func AllocsPerRun(runs int, f func()) (avg float64) {
f()

mallocs := 0 - runtimeMallocs()

for range runs {
f()
}
return 0

mallocs += runtimeMallocs()

return float64(mallocs / uint64(runs))
}

//go:linkname runtimeMallocs runtime.mallocs
func runtimeMallocs() uint64

type InternalExample struct {
Name string
F func()
Expand Down
Loading