Go code which depends on the file system contents like NUMA nodes, CPUs, interfaces associated with NUMA nodes can be tested with multiple ways. One posibility is to use isolate all file open code separately and get the contents and pass it to the actual functions which has the processing logics.

Alternatively, it also possible to mock files using a temproary filesystem only for tesing using spf13/afero project. It provides a wraper for genric io and ioutil packages. But in the GO test files, this wrapper can be altered to a local Memory based filesystem and the required files and content could be written on the tests itself.

Here is an example of the GO file which reads the cpulist from NUMA node.

package main

import (
	"flag"
	"fmt"
	"strings"

	iowrap "github.com/spf13/afero"
)

var (
	FS     iowrap.Fs
	FSUtil *iowrap.Afero
)

func init() {
	FS = iowrap.NewOsFs()
	FSUtil = &iowrap.Afero{Fs: FS}
}

func main() {
	Calc()
}

func Calc() (string, error) {
	content, err := FSUtil.ReadFile("/sys/devices/system/node/node1/cpulist")
	if err != nil {
		fmt.Println("ERROR:", err)
		return "", err
	}
	ret := strings.TrimSuffix(string(content), "\n")
	fmt.Println("Content:", ret)
	return ret, nil
}

The function Calc can be tested by mocking the filesystem to a local memory based filesystem like NewMemMapFs, which will allows us to create files with specific contents as pwer the test needs. This will avoid the need to restructure the code to separate the file read logics. Anf also any error reading file could also be tested to see if valid error messages are provided.

Below snippet is the test file for the above mentioned source file:

package main_test

import (
	. "github.com/krsacme/go-play-ground"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
	iowrap "github.com/spf13/afero"
)

func init() {
	FS = iowrap.NewMemMapFs()
	FSUtil = &iowrap.Afero{Fs: FS}

	FS.MkdirAll("/sys/devices/system/node/node1", 0755)
	iowrap.WriteFile(FS, "/sys/devices/system/node/node1/cpulist", []byte("0-7\n"), 0644)
}

var _ = Describe("Main", func() {

	Describe("calc", func() {
		Context("calc function", func() {
			It("should return numa nodes", func() {
				Expect(Calc()).To(Equal("0-7"))
			})
		})
	})