# 7.3 Unit Test

初始化的 UT 可以参考 IR Tree, 因为初始化工作本身就需要基于 IR Tree. 我们查看一下如下代码的处理结果：

```go
package p

const version = 1.16

func main() {
    if version <= 1.15 {
        println("Inside Body")
    } else {
        println("Inside Else")
    }
}
```

此处的 `if body` 应该从 IR Tree 中清除掉。为了方便，这里我们将所有的测试代码拷贝到测试文件 `cmd/compile/internal/noder/deadcode_test.go`, 完整内容如下：

```go
package noder

import (
    "bufio"
    "cmd/compile/internal/amd64"
    "cmd/compile/internal/base"
    "cmd/compile/internal/deadcode"
    "cmd/compile/internal/escape"
    "cmd/compile/internal/inline"
    "cmd/compile/internal/ir"
    "cmd/compile/internal/reflectdata"
    "cmd/compile/internal/ssa"
    "cmd/compile/internal/ssagen"
    "cmd/compile/internal/syntax"
    "cmd/compile/internal/typecheck"
    "cmd/compile/internal/types"
    "cmd/compile/internal/types2"
    "cmd/internal/obj"
    "cmd/internal/objabi"
    "cmd/internal/src"
    "fmt"
    "os"
    "strings"
    "testing"
)

func parseSrc(path, src string) (*syntax.File, error) {
    var mode syntax.Mode
    mode = syntax.AllowGenerics | syntax.CheckBranches
    errh := func(error) {} // dummy error handler so that parsing continues in presence of errors
    return syntax.Parse(syntax.NewFileBase(path), strings.NewReader(src), errh, nil, mode)
}

func defaultImporter() *gcimports {
    return &gcimports{
        packages: map[string]*types2.Package{},
    }
}

func init() {
    amd64.Init(&ssagen.Arch)

    base.Ctxt = obj.Linknew(ssagen.Arch.LinkArch)
    base.Ctxt.DiagFunc = base.Errorf
    base.Ctxt.DiagFlush = base.FlushErrors
    base.Ctxt.Bso = bufio.NewWriter(os.Stdout)

    base.Ctxt.UseBASEntries = base.Ctxt.Headtype != objabi.Hdarwin

    types.LocalPkg = types.NewPkg("", "")
    types.LocalPkg.Prefix = "\"\""

    types.LocalPkg.Height = types.MaxPkgHeight

    types.BuiltinPkg = types.NewPkg("go.builtin", "") // TODO(gri) name this package go.builtin?
    types.BuiltinPkg.Prefix = "go.builtin"            // not go%2ebuiltin

    // pseudo-package, accessed by import "unsafe"
    ir.Pkgs.Unsafe = types.NewPkg("unsafe", "unsafe")

    ir.Pkgs.Runtime = types.NewPkg("go.runtime", "runtime")
    ir.Pkgs.Runtime.Prefix = "runtime"

    // pseudo-packages used in symbol tables
    ir.Pkgs.Itab = types.NewPkg("go.itab", "go.itab")
    ir.Pkgs.Itab.Prefix = "go.itab" // not go%2eitab

    // pseudo-package used for methods with anonymous receivers
    ir.Pkgs.Go = types.NewPkg("go", "")

    base.DebugSSA = ssa.PhaseOption

    ssagen.Arch.LinkArch.Init(base.Ctxt)
    ir.EscFmt = escape.Fmt
    ir.IsIntrinsicCall = ssagen.IsIntrinsicCall
    inline.SSADumpInline = ssagen.DumpInline
    ssagen.InitEnv()
    ssagen.InitTables()

    types.PtrSize = ssagen.Arch.LinkArch.PtrSize
    types.RegSize = ssagen.Arch.LinkArch.RegSize
    types.MaxWidth = ssagen.Arch.MAXWIDTH

    typecheck.Target = new(ir.Package)

    typecheck.NeedITab = func(t, iface *types.Type) { reflectdata.ITabAddr(t, iface) }
    typecheck.NeedRuntimeType = reflectdata.NeedRuntimeType // TODO(rsc): TypeSym for lock?

    base.AutogeneratedPos = base.Ctxt.PosTable.XPos(src.MakePos(src.NewFileBase("<autogenerated>", "<autogenerated>"), 1, 0))

    typecheck.InitUniverse()
}

func dumpIrTree(nodes []ir.Node) {
    for _, n := range nodes {
        s := fmt.Sprintf("\nafter noder2 %v", n)
        ir.Dump(s, n)
    }
}

func TestIrTree(t *testing.T) {
    code := `
package p

const version = 1.16

func main() {
if version <= 1.15 {
println("Inside Body")
} else {
println("Inside Else")
}
}
`
    f, err := parseSrc("generic_testTypecheckConst", code)

    if err != nil {
        panic(err)
    }

    var conf types2.Config
    conf.Trace = false
    conf.Importer = defaultImporter()
    conf.Error = func(err error) {
        fmt.Printf("Typecheck Error: %v\n", err)
    }

    info := types2.Info{
        Types:      make(map[syntax.Expr]types2.TypeAndValue),
        Defs:       make(map[*syntax.Name]types2.Object),
        Uses:       make(map[*syntax.Name]types2.Object),
        Selections: make(map[*syntax.SelectorExpr]*types2.Selection),
        Implicits:  make(map[syntax.Node]types2.Object),
        Scopes:     make(map[syntax.Node]*types2.Scope),
        Inferred:   make(map[syntax.Expr]types2.Inferred),
    }

    pkg, err := conf.Check("<no package>", []*syntax.File{f}, &info)
    if err != nil {
        panic(err)
    }

    var m posMap
    g := irgen{
        target: typecheck.Target,
        self:   pkg,
        info:   &info,
        posMap: m,
        objs:   make(map[types2.Object]*ir.Name),
        typs:   make(map[types2.Type]*types.Type),
    }

    p := &noder{
        err:         make(chan syntax.Error),
        trackScopes: base.Flag.Dwarf,
        file:        f,
    }
    g.generate([]*noder{p})

    println("Before Deadcode:")
    dumpIrTree(typecheck.Target.Decls)

    for _, n := range typecheck.Target.Decls {
        if n.Op() == ir.ODCLFUNC {
            deadcode.Func(n.(*ir.Func))
        }
    }

    println("After Deadcode:")
    dumpIrTree(typecheck.Target.Decls)
}
```

如果只看 `main` 函数的 `body` 的话，前后的 IR Tree 对比如下：

&#x20;清理无效代码前：

> ```
> .   DCLFUNC-body
> .   .   IF # deadcode:27
> .   .   IF-Cond
> .   .   .   LITERAL-false tc(1) bool # deadcode:27
> .   .   IF-Body
> .   .   .   PRINTN tc(1) Use:3 # deadcode:28
> .   .   .   PRINTN-Args
> .   .   .   .   LITERAL-“Inside Body” tc(1) string # deadcode:28
> .   .   IF-Else
> .   .   .   PRINTN tc(1) Use:3 # deadcode:30
> .   .   .   PRINTN-Args
> .   .   .   .   LITERAL-“Inside Else” tc(1) string # deadcode:30
> ```

清理无效代码后：

> ```
> .   DCLFUNC-body
> .   .   IF # deadcode:27
> .   .   IF-Cond
> .   .   .   LITERAL-false tc(1) bool # deadcode:27
> .   .   IF-Else
> .   .   .   PRINTN tc(1) Use:3 # deadcode:30
> .   .   .   PRINTN-Args
> .   .   .   .   LITERAL-“Inside Else” tc(1) string # deadcode:30
> ```

后者已经没有了 `IF-Body` 这个节点。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://gocompiler.shizhz.me/7.-golang-bian-yi-qi-qing-chu-wu-xiao-dai-ma/7.3-unit-test.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
