On Fri, Apr 10, 2020 at 3:37 PM 'K Richard Pixley' via golang-nuts
<golang-nuts@googlegroups.com> wrote:
>
> I have some code.  It uses ioutil.ReadDir which returns a possible error.
>
> My testing is at 99% code coverage because I can't figure out a way to
> set up a situation in which os.Open succeeds on a directory, but
> ioutil.ReadDir fails.
>
> I can get to 100% code coverage if I throw away the err rather than
> testing for it and reporting it but that seems a bit... well...
> disingenuous.  I've looked down the calls to the kernel call
> getdirentries but the only errno I can see being relevant to a go
> program is EIO and I can't think of a way to force that to happen on a
> real file system.
>
> I can imagine a fake file system created specifically for this purpose,
> but that seems an awfully long way around the barn.
>
> How can I get to 100% code coverage?  Or should I just give up on
> finding a way to cover that last, single line of error handling code?

I'm not proud.  Here is an example program for which os.Open(dirname)
succeeds but ioutil.ReadDir(dirname) fails.  You may have to adjust
pathMax and nameMax for your system.  Whether you actually want to use
this technique is left to you.

Ian

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CAOyqgcVgKj1oBq6wj_bpS4zN6kZduVjAfP1NxTcnvpskPSx9NA%40mail.gmail.com.
package main

import (
	"fmt"
	"log"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

const pathMax = 4096
const nameMax = 256

func main() {
	tmpdir, err := ioutil.TempDir("", "readdir")
	if err != nil {
		log.Fatal(err)
	}
	defer os.RemoveAll(tmpdir)
	dirname := tmpdir
	for n := len(tmpdir); n + 10 < pathMax; n += nameMax {
		next := nameMax - 1
		if limit := pathMax - n - 10; limit < next {
			next = limit
		}
		subdir := strings.Repeat("d", next)
		dirname = filepath.Join(dirname, subdir)
		if err := os.Mkdir(dirname, 0o755); err != nil {
			log.Fatal(err)
		}
	}
	if err := os.Chdir(dirname); err != nil {
		log.Fatal(err)
	}
	f, err := os.Create("thisPathNameIsTooLong")
	if err != nil {
		log.Fatal(err)
	}
	if err := f.Close(); err != nil {
		log.Fatal(err)
	}
	if err := os.Chdir(tmpdir); err != nil {
		log.Fatal(err)
	}
	d, err := os.Open(dirname)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("os.Open(%q) succeeded\n", dirname)
	d.Close()
	if infos, err := ioutil.ReadDir(dirname); err != nil {
		fmt.Printf("ioutil.ReadDir(%q) failed: %v\n", dirname, err)
	} else {
		fmt.Printf("ioutil.ReadDir(%q) returned\n", dirname)
		for _, info := range infos {
			fmt.Printf(" %s\n", info.Name())
		}
	}
}

Reply via email to