aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/embed
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2020-12-23 09:57:37 -0800
committerIan Lance Taylor <iant@golang.org>2020-12-30 15:13:24 -0800
commitcfcbb4227fb20191e04eb8d7766ae6202f526afd (patch)
treee2effea96f6f204451779f044415c2385e45042b /libgo/go/embed
parent0696141107d61483f38482b941549959a0d7f613 (diff)
downloadgcc-cfcbb4227fb20191e04eb8d7766ae6202f526afd.zip
gcc-cfcbb4227fb20191e04eb8d7766ae6202f526afd.tar.gz
gcc-cfcbb4227fb20191e04eb8d7766ae6202f526afd.tar.bz2
libgo: update to Go1.16beta1 release
This does not yet include support for the //go:embed directive added in this release. * Makefile.am (check-runtime): Don't create check-runtime-dir. (mostlyclean-local): Don't remove check-runtime-dir. (check-go-tool, check-vet): Copy in go.mod and modules.txt. (check-cgo-test, check-carchive-test): Add go.mod file. * Makefile.in: Regenerate. Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/280172
Diffstat (limited to 'libgo/go/embed')
-rw-r--r--libgo/go/embed/embed.go406
-rw-r--r--libgo/go/embed/internal/embedtest/concurrency.txt1
-rw-r--r--libgo/go/embed/internal/embedtest/embed_test.go124
-rw-r--r--libgo/go/embed/internal/embedtest/embedx_test.go106
-rw-r--r--libgo/go/embed/internal/embedtest/testdata/.hidden/.more/tip.txt1
-rw-r--r--libgo/go/embed/internal/embedtest/testdata/.hidden/_more/tip.txt1
-rw-r--r--libgo/go/embed/internal/embedtest/testdata/.hidden/fortune.txt2
-rw-r--r--libgo/go/embed/internal/embedtest/testdata/.hidden/more/tip.txt1
-rw-r--r--libgo/go/embed/internal/embedtest/testdata/_hidden/fortune.txt2
-rw-r--r--libgo/go/embed/internal/embedtest/testdata/ascii.txt25
-rw-r--r--libgo/go/embed/internal/embedtest/testdata/glass.txt1
-rw-r--r--libgo/go/embed/internal/embedtest/testdata/hello.txt1
-rw-r--r--libgo/go/embed/internal/embedtest/testdata/i/i18n.txt1
-rw-r--r--libgo/go/embed/internal/embedtest/testdata/i/j/k/k8s.txt1
-rw-r--r--libgo/go/embed/internal/embedtest/testdata/ken.txt1
15 files changed, 674 insertions, 0 deletions
diff --git a/libgo/go/embed/embed.go b/libgo/go/embed/embed.go
new file mode 100644
index 0000000..29e0adf
--- /dev/null
+++ b/libgo/go/embed/embed.go
@@ -0,0 +1,406 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package embed provides access to files embedded in the running Go program.
+//
+// Go source files that import "embed" can use the //go:embed directive
+// to initialize a variable of type string, []byte, or FS with the contents of
+// files read from the package directory or subdirectories at compile time.
+//
+// For example, here are three ways to embed a file named hello.txt
+// and then print its contents at run time:
+//
+// import "embed"
+//
+// //go:embed hello.txt
+// var s string
+// print(s)
+//
+// //go:embed hello.txt
+// var b []byte
+// print(string(b))
+//
+// //go:embed hello.txt
+// var f embed.FS
+// data, _ := f.ReadFile("hello.txt")
+// print(string(data))
+//
+// Directives
+//
+// A //go:embed directive above a variable declaration specifies which files to embed,
+// using one or more path.Match patterns.
+//
+// The directive must immediately precede a line containing the declaration of a single variable.
+// Only blank lines and ‘//’ line comments are permitted between the directive and the declaration.
+//
+// The variable must be of type string, []byte, or FS exactly. Named types or type aliases
+// derived from those types are not allowed.
+//
+// For example:
+//
+// package server
+//
+// import "embed"
+//
+// // content holds our static web server content.
+// //go:embed image/* template/*
+// //go:embed html/index.html
+// var content embed.FS
+//
+// The Go build system will recognize the directives and arrange for the declared variable
+// (in the example above, content) to be populated with the matching files from the file system.
+//
+// The //go:embed directive accepts multiple space-separated patterns for brevity,
+// but it can also be repeated, to avoid very long lines when there are many patterns.
+// The patterns are interpreted relative to the package directory containing the source file.
+// The path separator is a forward slash, even on Windows systems.
+// To allow for naming files with spaces in their names, patterns can be written
+// as Go double-quoted or back-quoted string literals.
+//
+// If a pattern names a directory, all files in the subtree rooted at that directory are
+// embedded (recursively), except that files with names beginning with ‘.’ or ‘_’
+// are excluded. So the variable in the above example is almost equivalent to:
+//
+// // content is our static web server content.
+// //go:embed image template html/index.html
+// var content embed.FS
+//
+// The difference is that ‘image/*’ embeds ‘image/.tempfile’ while ‘image’ does not.
+//
+// The //go:embed directive can be used with both exported and unexported variables,
+// depending on whether the package wants to make the data available to other packages.
+// Similarly, it can be used with both global and function-local variables,
+// depending on what is more convenient in context.
+//
+// Patterns must not match files outside the package's module, such as ‘.git/*’ or symbolic links.
+// Matches for empty directories are ignored. After that, each pattern in a //go:embed line
+// must match at least one file or non-empty directory.
+//
+// Patterns must not contain ‘.’ or ‘..’ path elements nor begin with a leading slash.
+// To match everything in the current directory, use ‘*’ instead of ‘.’.
+//
+// If any patterns are invalid or have invalid matches, the build will fail.
+//
+// Strings and Bytes
+//
+// The //go:embed line for a variable of type string or []byte can have only a single pattern,
+// and that pattern can match only a single file. The string or []byte is initialized with
+// the contents of that file.
+//
+// The //go:embed directive requires importing "embed", even when using a string or []byte.
+// In source files that don't refer to embed.FS, use a blank import (import _ "embed").
+//
+// File Systems
+//
+// For embedding a single file, a variable of type string or []byte is often best.
+// The FS type enables embedding a tree of files, such as a directory of static
+// web server content, as in the example above.
+//
+// FS implements the io/fs package's FS interface, so it can be used with any package that
+// understands file systems, including net/http, text/template, and html/template.
+//
+// For example, given the content variable in the example above, we can write:
+//
+// http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.FS(content))))
+//
+// template.ParseFS(content, "*.tmpl")
+//
+// Tools
+//
+// To support tools that analyze Go packages, the patterns found in //go:embed lines
+// are available in “go list” output. See the EmbedPatterns, TestEmbedPatterns,
+// and XTestEmbedPatterns fields in the “go help list” output.
+//
+package embed
+
+import (
+ "errors"
+ "io"
+ "io/fs"
+ "time"
+)
+
+// An FS is a read-only collection of files, usually initialized with a //go:embed directive.
+// When declared without a //go:embed directive, an FS is an empty file system.
+//
+// An FS is a read-only value, so it is safe to use from multiple goroutines
+// simultaneously and also safe to assign values of type FS to each other.
+//
+// FS implements fs.FS, so it can be used with any package that understands
+// file system interfaces, including net/http, text/template, and html/template.
+//
+// See the package documentation for more details about initializing an FS.
+type FS struct {
+ // The compiler knows the layout of this struct.
+ // See cmd/compile/internal/gc's initEmbed.
+ //
+ // The files list is sorted by name but not by simple string comparison.
+ // Instead, each file's name takes the form "dir/elem" or "dir/elem/".
+ // The optional trailing slash indicates that the file is itself a directory.
+ // The files list is sorted first by dir (if dir is missing, it is taken to be ".")
+ // and then by base, so this list of files:
+ //
+ // p
+ // q/
+ // q/r
+ // q/s/
+ // q/s/t
+ // q/s/u
+ // q/v
+ // w
+ //
+ // is actually sorted as:
+ //
+ // p # dir=. elem=p
+ // q/ # dir=. elem=q
+ // w/ # dir=. elem=w
+ // q/r # dir=q elem=r
+ // q/s/ # dir=q elem=s
+ // q/v # dir=q elem=v
+ // q/s/t # dir=q/s elem=t
+ // q/s/u # dir=q/s elem=u
+ //
+ // This order brings directory contents together in contiguous sections
+ // of the list, allowing a directory read to use binary search to find
+ // the relevant sequence of entries.
+ files *[]file
+}
+
+// split splits the name into dir and elem as described in the
+// comment in the FS struct above. isDir reports whether the
+// final trailing slash was present, indicating that name is a directory.
+func split(name string) (dir, elem string, isDir bool) {
+ if name[len(name)-1] == '/' {
+ isDir = true
+ name = name[:len(name)-1]
+ }
+ i := len(name) - 1
+ for i >= 0 && name[i] != '/' {
+ i--
+ }
+ if i < 0 {
+ return ".", name, isDir
+ }
+ return name[:i], name[i+1:], isDir
+}
+
+// trimSlash trims a trailing slash from name, if present,
+// returning the possibly shortened name.
+func trimSlash(name string) string {
+ if len(name) > 0 && name[len(name)-1] == '/' {
+ return name[:len(name)-1]
+ }
+ return name
+}
+
+var (
+ _ fs.ReadDirFS = FS{}
+ _ fs.ReadFileFS = FS{}
+)
+
+// A file is a single file in the FS.
+// It implements fs.FileInfo and fs.DirEntry.
+type file struct {
+ // The compiler knows the layout of this struct.
+ // See cmd/compile/internal/gc's initEmbed.
+ name string
+ data string
+ hash [16]byte // truncated SHA256 hash
+}
+
+var (
+ _ fs.FileInfo = (*file)(nil)
+ _ fs.DirEntry = (*file)(nil)
+)
+
+func (f *file) Name() string { _, elem, _ := split(f.name); return elem }
+func (f *file) Size() int64 { return int64(len(f.data)) }
+func (f *file) ModTime() time.Time { return time.Time{} }
+func (f *file) IsDir() bool { _, _, isDir := split(f.name); return isDir }
+func (f *file) Sys() interface{} { return nil }
+func (f *file) Type() fs.FileMode { return f.Mode().Type() }
+func (f *file) Info() (fs.FileInfo, error) { return f, nil }
+
+func (f *file) Mode() fs.FileMode {
+ if f.IsDir() {
+ return fs.ModeDir | 0555
+ }
+ return 0444
+}
+
+// dotFile is a file for the root directory,
+// which is omitted from the files list in a FS.
+var dotFile = &file{name: "./"}
+
+// lookup returns the named file, or nil if it is not present.
+func (f FS) lookup(name string) *file {
+ if !fs.ValidPath(name) {
+ // The compiler should never emit a file with an invalid name,
+ // so this check is not strictly necessary (if name is invalid,
+ // we shouldn't find a match below), but it's a good backstop anyway.
+ return nil
+ }
+ if name == "." {
+ return dotFile
+ }
+
+ // Binary search to find where name would be in the list,
+ // and then check if name is at that position.
+ dir, elem, _ := split(name)
+ files := *f.files
+ i := sortSearch(len(files), func(i int) bool {
+ idir, ielem, _ := split(files[i].name)
+ return idir > dir || idir == dir && ielem >= elem
+ })
+ if i < len(files) && trimSlash(files[i].name) == name {
+ return &files[i]
+ }
+ return nil
+}
+
+// readDir returns the list of files corresponding to the directory dir.
+func (f FS) readDir(dir string) []file {
+ // Binary search to find where dir starts and ends in the list
+ // and then return that slice of the list.
+ files := *f.files
+ i := sortSearch(len(files), func(i int) bool {
+ idir, _, _ := split(files[i].name)
+ return idir >= dir
+ })
+ j := sortSearch(len(files), func(j int) bool {
+ jdir, _, _ := split(files[j].name)
+ return jdir > dir
+ })
+ return files[i:j]
+}
+
+// Open opens the named file for reading and returns it as an fs.File.
+func (f FS) Open(name string) (fs.File, error) {
+ file := f.lookup(name)
+ if file == nil {
+ return nil, &fs.PathError{Op: "open", Path: name, Err: fs.ErrNotExist}
+ }
+ if file.IsDir() {
+ return &openDir{file, f.readDir(name), 0}, nil
+ }
+ return &openFile{file, 0}, nil
+}
+
+// ReadDir reads and returns the entire named directory.
+func (f FS) ReadDir(name string) ([]fs.DirEntry, error) {
+ file, err := f.Open(name)
+ if err != nil {
+ return nil, err
+ }
+ dir, ok := file.(*openDir)
+ if !ok {
+ return nil, &fs.PathError{Op: "read", Path: name, Err: errors.New("not a directory")}
+ }
+ list := make([]fs.DirEntry, len(dir.files))
+ for i := range list {
+ list[i] = &dir.files[i]
+ }
+ return list, nil
+}
+
+// ReadFile reads and returns the content of the named file.
+func (f FS) ReadFile(name string) ([]byte, error) {
+ file, err := f.Open(name)
+ if err != nil {
+ return nil, err
+ }
+ ofile, ok := file.(*openFile)
+ if !ok {
+ return nil, &fs.PathError{Op: "read", Path: name, Err: errors.New("is a directory")}
+ }
+ return []byte(ofile.f.data), nil
+}
+
+// An openFile is a regular file open for reading.
+type openFile struct {
+ f *file // the file itself
+ offset int64 // current read offset
+}
+
+func (f *openFile) Close() error { return nil }
+func (f *openFile) Stat() (fs.FileInfo, error) { return f.f, nil }
+
+func (f *openFile) Read(b []byte) (int, error) {
+ if f.offset >= int64(len(f.f.data)) {
+ return 0, io.EOF
+ }
+ if f.offset < 0 {
+ return 0, &fs.PathError{Op: "read", Path: f.f.name, Err: fs.ErrInvalid}
+ }
+ n := copy(b, f.f.data[f.offset:])
+ f.offset += int64(n)
+ return n, nil
+}
+
+func (f *openFile) Seek(offset int64, whence int) (int64, error) {
+ switch whence {
+ case 0:
+ // offset += 0
+ case 1:
+ offset += f.offset
+ case 2:
+ offset += int64(len(f.f.data))
+ }
+ if offset < 0 || offset > int64(len(f.f.data)) {
+ return 0, &fs.PathError{Op: "seek", Path: f.f.name, Err: fs.ErrInvalid}
+ }
+ f.offset = offset
+ return offset, nil
+}
+
+// An openDir is a directory open for reading.
+type openDir struct {
+ f *file // the directory file itself
+ files []file // the directory contents
+ offset int // the read offset, an index into the files slice
+}
+
+func (d *openDir) Close() error { return nil }
+func (d *openDir) Stat() (fs.FileInfo, error) { return d.f, nil }
+
+func (d *openDir) Read([]byte) (int, error) {
+ return 0, &fs.PathError{Op: "read", Path: d.f.name, Err: errors.New("is a directory")}
+}
+
+func (d *openDir) ReadDir(count int) ([]fs.DirEntry, error) {
+ n := len(d.files) - d.offset
+ if count > 0 && n > count {
+ n = count
+ }
+ if n == 0 {
+ if count <= 0 {
+ return nil, nil
+ }
+ return nil, io.EOF
+ }
+ list := make([]fs.DirEntry, n)
+ for i := range list {
+ list[i] = &d.files[d.offset+i]
+ }
+ d.offset += n
+ return list, nil
+}
+
+// sortSearch is like sort.Search, avoiding an import.
+func sortSearch(n int, f func(int) bool) int {
+ // Define f(-1) == false and f(n) == true.
+ // Invariant: f(i-1) == false, f(j) == true.
+ i, j := 0, n
+ for i < j {
+ h := int(uint(i+j) >> 1) // avoid overflow when computing h
+ // i ≤ h < j
+ if !f(h) {
+ i = h + 1 // preserves f(i-1) == false
+ } else {
+ j = h // preserves f(j) == true
+ }
+ }
+ // i == j, f(i-1) == false, and f(j) (= f(i)) == true => answer is i.
+ return i
+}
diff --git a/libgo/go/embed/internal/embedtest/concurrency.txt b/libgo/go/embed/internal/embedtest/concurrency.txt
new file mode 100644
index 0000000..0814741
--- /dev/null
+++ b/libgo/go/embed/internal/embedtest/concurrency.txt
@@ -0,0 +1 @@
+Concurrency is not parallelism.
diff --git a/libgo/go/embed/internal/embedtest/embed_test.go b/libgo/go/embed/internal/embedtest/embed_test.go
new file mode 100644
index 0000000..c6a7bea
--- /dev/null
+++ b/libgo/go/embed/internal/embedtest/embed_test.go
@@ -0,0 +1,124 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package embedtest
+
+import (
+ "embed"
+ "reflect"
+ "testing"
+ "testing/fstest"
+)
+
+//go:embed testdata/h*.txt
+//go:embed c*.txt testdata/g*.txt
+var global embed.FS
+
+//go:embed c*txt
+var concurrency string
+
+//go:embed testdata/g*.txt
+var glass []byte
+
+func testFiles(t *testing.T, f embed.FS, name, data string) {
+ t.Helper()
+ d, err := f.ReadFile(name)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if string(d) != data {
+ t.Errorf("read %v = %q, want %q", name, d, data)
+ }
+}
+
+func testString(t *testing.T, s, name, data string) {
+ t.Helper()
+ if s != data {
+ t.Errorf("%v = %q, want %q", name, s, data)
+ }
+}
+
+func testDir(t *testing.T, f embed.FS, name string, expect ...string) {
+ t.Helper()
+ dirs, err := f.ReadDir(name)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ var names []string
+ for _, d := range dirs {
+ name := d.Name()
+ if d.IsDir() {
+ name += "/"
+ }
+ names = append(names, name)
+ }
+ if !reflect.DeepEqual(names, expect) {
+ t.Errorf("readdir %v = %v, want %v", name, names, expect)
+ }
+}
+
+func TestGlobal(t *testing.T) {
+ testFiles(t, global, "concurrency.txt", "Concurrency is not parallelism.\n")
+ testFiles(t, global, "testdata/hello.txt", "hello, world\n")
+ testFiles(t, global, "testdata/glass.txt", "I can eat glass and it doesn't hurt me.\n")
+
+ if err := fstest.TestFS(global, "concurrency.txt", "testdata/hello.txt"); err != nil {
+ t.Fatal(err)
+ }
+
+ testString(t, concurrency, "concurrency", "Concurrency is not parallelism.\n")
+ testString(t, string(glass), "glass", "I can eat glass and it doesn't hurt me.\n")
+}
+
+func TestLocal(t *testing.T) {
+ //go:embed testdata/k*.txt
+ var local embed.FS
+ testFiles(t, local, "testdata/ken.txt", "If a program is too slow, it must have a loop.\n")
+
+ //go:embed testdata/k*.txt
+ var s string
+ testString(t, s, "local variable s", "If a program is too slow, it must have a loop.\n")
+
+ //go:embed testdata/h*.txt
+ var b []byte
+ testString(t, string(b), "local variable b", "hello, world\n")
+}
+
+func TestDir(t *testing.T) {
+ //go:embed testdata
+ var all embed.FS
+
+ testFiles(t, all, "testdata/hello.txt", "hello, world\n")
+ testFiles(t, all, "testdata/i/i18n.txt", "internationalization\n")
+ testFiles(t, all, "testdata/i/j/k/k8s.txt", "kubernetes\n")
+ testFiles(t, all, "testdata/ken.txt", "If a program is too slow, it must have a loop.\n")
+
+ testDir(t, all, ".", "testdata/")
+ testDir(t, all, "testdata/i", "i18n.txt", "j/")
+ testDir(t, all, "testdata/i/j", "k/")
+ testDir(t, all, "testdata/i/j/k", "k8s.txt")
+}
+
+func TestHidden(t *testing.T) {
+ //go:embed testdata
+ var dir embed.FS
+
+ //go:embed testdata/*
+ var star embed.FS
+
+ t.Logf("//go:embed testdata")
+
+ testDir(t, dir, "testdata",
+ "ascii.txt", "glass.txt", "hello.txt", "i/", "ken.txt")
+
+ t.Logf("//go:embed testdata/*")
+
+ testDir(t, star, "testdata",
+ ".hidden/", "_hidden/", "ascii.txt", "glass.txt", "hello.txt", "i/", "ken.txt")
+
+ testDir(t, star, "testdata/.hidden",
+ "fortune.txt", "more/") // but not .more or _more
+}
diff --git a/libgo/go/embed/internal/embedtest/embedx_test.go b/libgo/go/embed/internal/embedtest/embedx_test.go
new file mode 100644
index 0000000..20d5a28
--- /dev/null
+++ b/libgo/go/embed/internal/embedtest/embedx_test.go
@@ -0,0 +1,106 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package embedtest_test
+
+import (
+ "embed"
+ "os"
+ "testing"
+)
+
+var (
+ global2 = global
+ concurrency2 = concurrency
+ glass2 = glass
+ sbig2 = sbig
+ bbig2 = bbig
+)
+
+//go:embed testdata/*.txt
+var global embed.FS
+
+//go:embed c*txt
+var concurrency string
+
+//go:embed testdata/g*.txt
+var glass []byte
+
+//go:embed testdata/ascii.txt
+var sbig string
+
+//go:embed testdata/ascii.txt
+var bbig []byte
+
+func testFiles(t *testing.T, f embed.FS, name, data string) {
+ t.Helper()
+ d, err := f.ReadFile(name)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if string(d) != data {
+ t.Errorf("read %v = %q, want %q", name, d, data)
+ }
+}
+
+func testString(t *testing.T, s, name, data string) {
+ t.Helper()
+ if s != data {
+ t.Errorf("%v = %q, want %q", name, s, data)
+ }
+}
+
+func TestXGlobal(t *testing.T) {
+ testFiles(t, global, "testdata/hello.txt", "hello, world\n")
+ testString(t, concurrency, "concurrency", "Concurrency is not parallelism.\n")
+ testString(t, string(glass), "glass", "I can eat glass and it doesn't hurt me.\n")
+ testString(t, concurrency2, "concurrency2", "Concurrency is not parallelism.\n")
+ testString(t, string(glass2), "glass2", "I can eat glass and it doesn't hurt me.\n")
+
+ big, err := os.ReadFile("testdata/ascii.txt")
+ if err != nil {
+ t.Fatal(err)
+ }
+ testString(t, sbig, "sbig", string(big))
+ testString(t, sbig2, "sbig2", string(big))
+ testString(t, string(bbig), "bbig", string(big))
+ testString(t, string(bbig2), "bbig", string(big))
+
+ if t.Failed() {
+ return
+ }
+
+ // Could check &glass[0] == &glass2[0] but also want to make sure write does not fault
+ // (data must not be in read-only memory).
+ old := glass[0]
+ glass[0]++
+ if glass2[0] != glass[0] {
+ t.Fatalf("glass and glass2 do not share storage")
+ }
+ glass[0] = old
+
+ // Could check &bbig[0] == &bbig2[0] but also want to make sure write does not fault
+ // (data must not be in read-only memory).
+ old = bbig[0]
+ bbig[0]++
+ if bbig2[0] != bbig[0] {
+ t.Fatalf("bbig and bbig2 do not share storage")
+ }
+ bbig[0] = old
+}
+
+func TestXLocal(t *testing.T) {
+ //go:embed testdata/*o.txt
+ var local embed.FS
+ testFiles(t, local, "testdata/hello.txt", "hello, world\n")
+
+ //go:embed testdata/k*.txt
+ var s string
+ testString(t, s, "local variable s", "If a program is too slow, it must have a loop.\n")
+
+ //go:embed testdata/h*.txt
+ var b []byte
+ testString(t, string(b), "local variable b", "hello, world\n")
+}
diff --git a/libgo/go/embed/internal/embedtest/testdata/.hidden/.more/tip.txt b/libgo/go/embed/internal/embedtest/testdata/.hidden/.more/tip.txt
new file mode 100644
index 0000000..71b9c69
--- /dev/null
+++ b/libgo/go/embed/internal/embedtest/testdata/.hidden/.more/tip.txt
@@ -0,0 +1 @@
+#define struct union /* Great space saver */
diff --git a/libgo/go/embed/internal/embedtest/testdata/.hidden/_more/tip.txt b/libgo/go/embed/internal/embedtest/testdata/.hidden/_more/tip.txt
new file mode 100644
index 0000000..71b9c69
--- /dev/null
+++ b/libgo/go/embed/internal/embedtest/testdata/.hidden/_more/tip.txt
@@ -0,0 +1 @@
+#define struct union /* Great space saver */
diff --git a/libgo/go/embed/internal/embedtest/testdata/.hidden/fortune.txt b/libgo/go/embed/internal/embedtest/testdata/.hidden/fortune.txt
new file mode 100644
index 0000000..31f2013
--- /dev/null
+++ b/libgo/go/embed/internal/embedtest/testdata/.hidden/fortune.txt
@@ -0,0 +1,2 @@
+WARNING: terminal is not fully functional
+ - (press RETURN)
diff --git a/libgo/go/embed/internal/embedtest/testdata/.hidden/more/tip.txt b/libgo/go/embed/internal/embedtest/testdata/.hidden/more/tip.txt
new file mode 100644
index 0000000..71b9c69
--- /dev/null
+++ b/libgo/go/embed/internal/embedtest/testdata/.hidden/more/tip.txt
@@ -0,0 +1 @@
+#define struct union /* Great space saver */
diff --git a/libgo/go/embed/internal/embedtest/testdata/_hidden/fortune.txt b/libgo/go/embed/internal/embedtest/testdata/_hidden/fortune.txt
new file mode 100644
index 0000000..31f2013
--- /dev/null
+++ b/libgo/go/embed/internal/embedtest/testdata/_hidden/fortune.txt
@@ -0,0 +1,2 @@
+WARNING: terminal is not fully functional
+ - (press RETURN)
diff --git a/libgo/go/embed/internal/embedtest/testdata/ascii.txt b/libgo/go/embed/internal/embedtest/testdata/ascii.txt
new file mode 100644
index 0000000..0cfebf6
--- /dev/null
+++ b/libgo/go/embed/internal/embedtest/testdata/ascii.txt
@@ -0,0 +1,25 @@
+ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmn
+!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmno
+"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnop
+#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopq
+$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqr
+%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrs
+&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrst
+'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstu
+()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuv
+)*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvw
+*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwx
++,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxy
+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz
+-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{
+./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|
+/0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}
+0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}
+123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !
+23456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"
+3456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#
+456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$
+56789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%
+6789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&
+789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'
+89:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|} !"#$%&'(
diff --git a/libgo/go/embed/internal/embedtest/testdata/glass.txt b/libgo/go/embed/internal/embedtest/testdata/glass.txt
new file mode 100644
index 0000000..8350baf
--- /dev/null
+++ b/libgo/go/embed/internal/embedtest/testdata/glass.txt
@@ -0,0 +1 @@
+I can eat glass and it doesn't hurt me.
diff --git a/libgo/go/embed/internal/embedtest/testdata/hello.txt b/libgo/go/embed/internal/embedtest/testdata/hello.txt
new file mode 100644
index 0000000..4b5fa63
--- /dev/null
+++ b/libgo/go/embed/internal/embedtest/testdata/hello.txt
@@ -0,0 +1 @@
+hello, world
diff --git a/libgo/go/embed/internal/embedtest/testdata/i/i18n.txt b/libgo/go/embed/internal/embedtest/testdata/i/i18n.txt
new file mode 100644
index 0000000..5ee27c6
--- /dev/null
+++ b/libgo/go/embed/internal/embedtest/testdata/i/i18n.txt
@@ -0,0 +1 @@
+internationalization
diff --git a/libgo/go/embed/internal/embedtest/testdata/i/j/k/k8s.txt b/libgo/go/embed/internal/embedtest/testdata/i/j/k/k8s.txt
new file mode 100644
index 0000000..807e21b
--- /dev/null
+++ b/libgo/go/embed/internal/embedtest/testdata/i/j/k/k8s.txt
@@ -0,0 +1 @@
+kubernetes
diff --git a/libgo/go/embed/internal/embedtest/testdata/ken.txt b/libgo/go/embed/internal/embedtest/testdata/ken.txt
new file mode 100644
index 0000000..bb25981
--- /dev/null
+++ b/libgo/go/embed/internal/embedtest/testdata/ken.txt
@@ -0,0 +1 @@
+If a program is too slow, it must have a loop.