go-html/bench_test.go
Snider 7efd2ab93a test: add benchmarks, Unicode edge cases, and stress tests
Performance benchmarks across all major APIs:
- BenchmarkRender (depth 1/3/5/7 tree, full page)
- BenchmarkImprint (small/large pipeline)
- BenchmarkCompareVariants (2/3 variants)
- BenchmarkLayout (C, HCF, HLCRF, nested, many children)
- BenchmarkEach (10/100/1000 items)
- BenchmarkResponsive, BenchmarkStripTags
- Codegen: GenerateClass, TagToClassName, GenerateBundle, GenerateRegistration

Edge case tests:
- Unicode: emoji, RTL (Arabic/Hebrew), zero-width chars, mixed scripts
- Deep nesting: 10/20 levels, mixed slot types
- Large Each iterations: 1000/5000 items, nested Each
- Layout variant validation: invalid chars, lowercase, duplicates, empty
- Nil context handling for Render, Imprint, CompareVariants
- Switch no-match, Entitled nil context, empty tag El

Co-Authored-By: Virgil <virgil@lethean.io>
2026-02-20 05:33:15 +00:00

290 lines
6.1 KiB
Go

package html
import (
"fmt"
"testing"
i18n "forge.lthn.ai/core/go-i18n"
)
func init() {
svc, _ := i18n.New()
i18n.SetDefault(svc)
}
// --- BenchmarkRender ---
// buildTree creates an El tree of the given depth with branching factor 3.
func buildTree(depth int) Node {
if depth <= 0 {
return Raw("leaf")
}
children := make([]Node, 3)
for i := range children {
children[i] = buildTree(depth - 1)
}
return El("div", children...)
}
func BenchmarkRender_Depth1(b *testing.B) {
node := buildTree(1)
ctx := NewContext()
b.ResetTimer()
for b.Loop() {
node.Render(ctx)
}
}
func BenchmarkRender_Depth3(b *testing.B) {
node := buildTree(3)
ctx := NewContext()
b.ResetTimer()
for b.Loop() {
node.Render(ctx)
}
}
func BenchmarkRender_Depth5(b *testing.B) {
node := buildTree(5)
ctx := NewContext()
b.ResetTimer()
for b.Loop() {
node.Render(ctx)
}
}
func BenchmarkRender_Depth7(b *testing.B) {
node := buildTree(7)
ctx := NewContext()
b.ResetTimer()
for b.Loop() {
node.Render(ctx)
}
}
func BenchmarkRender_FullPage(b *testing.B) {
page := NewLayout("HCF").
H(El("h1", Text("Dashboard"))).
C(
El("div",
El("p", Text("Welcome")),
Each([]string{"Home", "Settings", "Profile"}, func(item string) Node {
return El("a", Raw(item))
}),
),
).
F(El("small", Text("Footer")))
ctx := NewContext()
b.ResetTimer()
for b.Loop() {
page.Render(ctx)
}
}
// --- BenchmarkImprint ---
func BenchmarkImprint_Small(b *testing.B) {
page := NewLayout("HCF").
H(El("h1", Text("Building project"))).
C(El("p", Text("Files deleted successfully"))).
F(El("small", Text("Completed")))
ctx := NewContext()
b.ResetTimer()
for b.Loop() {
Imprint(page, ctx)
}
}
func BenchmarkImprint_Large(b *testing.B) {
items := make([]string, 20)
for i := range items {
items[i] = fmt.Sprintf("Item %d was created successfully", i)
}
page := NewLayout("HLCRF").
H(El("h1", Text("Building project"))).
L(El("nav", Each(items[:5], func(s string) Node { return El("a", Text(s)) }))).
C(El("div", Each(items, func(s string) Node { return El("p", Text(s)) }))).
R(El("aside", Text("Completed rendering operation"))).
F(El("small", Text("Finished processing all items")))
ctx := NewContext()
b.ResetTimer()
for b.Loop() {
Imprint(page, ctx)
}
}
// --- BenchmarkCompareVariants ---
func BenchmarkCompareVariants_TwoVariants(b *testing.B) {
r := NewResponsive().
Variant("desktop", NewLayout("HLCRF").
H(El("h1", Text("Building project"))).
C(El("p", Text("Files deleted successfully"))).
F(El("small", Text("Completed")))).
Variant("mobile", NewLayout("HCF").
H(El("h1", Text("Building project"))).
C(El("p", Text("Files deleted successfully"))).
F(El("small", Text("Completed"))))
ctx := NewContext()
b.ResetTimer()
for b.Loop() {
CompareVariants(r, ctx)
}
}
func BenchmarkCompareVariants_ThreeVariants(b *testing.B) {
r := NewResponsive().
Variant("desktop", NewLayout("HLCRF").
H(El("h1", Text("Building project"))).
L(El("nav", Text("Navigation links"))).
C(El("p", Text("Files deleted successfully"))).
R(El("aside", Text("Sidebar content"))).
F(El("small", Text("Completed")))).
Variant("tablet", NewLayout("HCF").
H(El("h1", Text("Building project"))).
C(El("p", Text("Files deleted successfully"))).
F(El("small", Text("Completed")))).
Variant("mobile", NewLayout("C").
C(El("p", Text("Files deleted successfully"))))
ctx := NewContext()
b.ResetTimer()
for b.Loop() {
CompareVariants(r, ctx)
}
}
// --- BenchmarkLayout ---
func BenchmarkLayout_ContentOnly(b *testing.B) {
layout := NewLayout("C").C(Raw("content"))
ctx := NewContext()
b.ResetTimer()
for b.Loop() {
layout.Render(ctx)
}
}
func BenchmarkLayout_HCF(b *testing.B) {
layout := NewLayout("HCF").
H(Raw("header")).C(Raw("main")).F(Raw("footer"))
ctx := NewContext()
b.ResetTimer()
for b.Loop() {
layout.Render(ctx)
}
}
func BenchmarkLayout_HLCRF(b *testing.B) {
layout := NewLayout("HLCRF").
H(Raw("header")).L(Raw("left")).C(Raw("main")).R(Raw("right")).F(Raw("footer"))
ctx := NewContext()
b.ResetTimer()
for b.Loop() {
layout.Render(ctx)
}
}
func BenchmarkLayout_Nested(b *testing.B) {
inner := NewLayout("HCF").H(Raw("ih")).C(Raw("ic")).F(Raw("if"))
layout := NewLayout("HLCRF").
H(Raw("header")).L(inner).C(Raw("main")).R(Raw("right")).F(Raw("footer"))
ctx := NewContext()
b.ResetTimer()
for b.Loop() {
layout.Render(ctx)
}
}
func BenchmarkLayout_ManySlotChildren(b *testing.B) {
nodes := make([]Node, 50)
for i := range nodes {
nodes[i] = El("p", Raw(fmt.Sprintf("paragraph %d", i)))
}
layout := NewLayout("HLCRF").
H(Raw("header")).
C(nodes...).
F(Raw("footer"))
ctx := NewContext()
b.ResetTimer()
for b.Loop() {
layout.Render(ctx)
}
}
// --- BenchmarkEach ---
func BenchmarkEach_10(b *testing.B) {
benchEach(b, 10)
}
func BenchmarkEach_100(b *testing.B) {
benchEach(b, 100)
}
func BenchmarkEach_1000(b *testing.B) {
benchEach(b, 1000)
}
func benchEach(b *testing.B, n int) {
b.Helper()
items := make([]int, n)
for i := range items {
items[i] = i
}
node := Each(items, func(i int) Node {
return El("li", Raw(fmt.Sprintf("item-%d", i)))
})
ctx := NewContext()
b.ResetTimer()
for b.Loop() {
node.Render(ctx)
}
}
// --- BenchmarkResponsive ---
func BenchmarkResponsive_ThreeVariants(b *testing.B) {
r := NewResponsive().
Variant("desktop", NewLayout("HLCRF").H(Raw("h")).L(Raw("l")).C(Raw("c")).R(Raw("r")).F(Raw("f"))).
Variant("tablet", NewLayout("HCF").H(Raw("h")).C(Raw("c")).F(Raw("f"))).
Variant("mobile", NewLayout("C").C(Raw("c")))
ctx := NewContext()
b.ResetTimer()
for b.Loop() {
r.Render(ctx)
}
}
// --- BenchmarkStripTags ---
func BenchmarkStripTags_Short(b *testing.B) {
input := `<div>hello</div>`
for b.Loop() {
StripTags(input)
}
}
func BenchmarkStripTags_Long(b *testing.B) {
layout := NewLayout("HLCRF").
H(Raw("header content")).L(Raw("left sidebar")).
C(Raw("main body content with multiple words")).
R(Raw("right sidebar")).F(Raw("footer content"))
input := layout.Render(NewContext())
b.ResetTimer()
for b.Loop() {
StripTags(input)
}
}