зеркало из https://github.com/golang/tools.git
godoc: update Index.{Write,Reader}, add tests
R=golang-dev, adg CC=golang-dev https://golang.org/cl/24490043
This commit is contained in:
Родитель
f339918a70
Коммит
515bcdc536
100
godoc/index.go
100
godoc/index.go
|
@ -880,11 +880,22 @@ func NewIndex(c *Corpus, dirnames <-chan string, fulltextIndex bool, throttle fl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ErrFileIndexVersion = errors.New("file index version out of date")
|
||||||
|
|
||||||
|
const fileIndexVersion = 2
|
||||||
|
|
||||||
|
// fileIndex is the subset of Index that's gob-encoded for use by
|
||||||
|
// Index.Write and Index.Read.
|
||||||
type fileIndex struct {
|
type fileIndex struct {
|
||||||
Words map[string]*LookupResult
|
Version int
|
||||||
Alts map[string]*AltWords
|
Words map[string]*LookupResult
|
||||||
Snippets []*Snippet
|
Alts map[string]*AltWords
|
||||||
Fulltext bool
|
Snippets []*Snippet
|
||||||
|
Fulltext bool
|
||||||
|
Stats Statistics
|
||||||
|
ImportCount map[string]int
|
||||||
|
PackagePath map[string]map[string]bool
|
||||||
|
Exports map[string]map[string]SpotKind
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *fileIndex) Write(w io.Writer) error {
|
func (x *fileIndex) Write(w io.Writer) error {
|
||||||
|
@ -895,63 +906,79 @@ func (x *fileIndex) Read(r io.Reader) error {
|
||||||
return gob.NewDecoder(r).Decode(x)
|
return gob.NewDecoder(r).Decode(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write writes the index x to w.
|
// WriteTo writes the index x to w.
|
||||||
func (x *Index) Write(w io.Writer) error {
|
func (x *Index) WriteTo(w io.Writer) (n int64, err error) {
|
||||||
|
w = countingWriter{&n, w}
|
||||||
fulltext := false
|
fulltext := false
|
||||||
if x.suffixes != nil {
|
if x.suffixes != nil {
|
||||||
fulltext = true
|
fulltext = true
|
||||||
}
|
}
|
||||||
fx := fileIndex{
|
fx := fileIndex{
|
||||||
x.words,
|
Version: fileIndexVersion,
|
||||||
x.alts,
|
Words: x.words,
|
||||||
x.snippets,
|
Alts: x.alts,
|
||||||
fulltext,
|
Snippets: x.snippets,
|
||||||
|
Fulltext: fulltext,
|
||||||
|
Stats: x.stats,
|
||||||
|
ImportCount: x.importCount,
|
||||||
|
PackagePath: x.packagePath,
|
||||||
|
Exports: x.exports,
|
||||||
}
|
}
|
||||||
if err := fx.Write(w); err != nil {
|
if err := fx.Write(w); err != nil {
|
||||||
return err
|
return 0, err
|
||||||
}
|
}
|
||||||
if fulltext {
|
if fulltext {
|
||||||
encode := func(x interface{}) error {
|
encode := func(x interface{}) error {
|
||||||
return gob.NewEncoder(w).Encode(x)
|
return gob.NewEncoder(w).Encode(x)
|
||||||
}
|
}
|
||||||
if err := x.fset.Write(encode); err != nil {
|
if err := x.fset.Write(encode); err != nil {
|
||||||
return err
|
return 0, err
|
||||||
}
|
}
|
||||||
if err := x.suffixes.Write(w); err != nil {
|
if err := x.suffixes.Write(w); err != nil {
|
||||||
return err
|
return 0, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return n, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read reads the index from r into x; x must not be nil.
|
// Read reads the index from r into x; x must not be nil.
|
||||||
// If r does not also implement io.ByteReader, it will be wrapped in a bufio.Reader.
|
// If r does not also implement io.ByteReader, it will be wrapped in a bufio.Reader.
|
||||||
func (x *Index) Read(r io.Reader) error {
|
// If the index is from an old version, the error is ErrFileIndexVersion.
|
||||||
|
func (x *Index) ReadFrom(r io.Reader) (n int64, err error) {
|
||||||
// We use the ability to read bytes as a plausible surrogate for buffering.
|
// We use the ability to read bytes as a plausible surrogate for buffering.
|
||||||
if _, ok := r.(io.ByteReader); !ok {
|
if _, ok := r.(io.ByteReader); !ok {
|
||||||
r = bufio.NewReader(r)
|
r = bufio.NewReader(r)
|
||||||
}
|
}
|
||||||
|
r = countingReader{&n, r.(byteReader)}
|
||||||
var fx fileIndex
|
var fx fileIndex
|
||||||
if err := fx.Read(r); err != nil {
|
if err := fx.Read(r); err != nil {
|
||||||
return err
|
return n, err
|
||||||
|
}
|
||||||
|
if fx.Version != fileIndexVersion {
|
||||||
|
return 0, ErrFileIndexVersion
|
||||||
}
|
}
|
||||||
x.words = fx.Words
|
x.words = fx.Words
|
||||||
x.alts = fx.Alts
|
x.alts = fx.Alts
|
||||||
x.snippets = fx.Snippets
|
x.snippets = fx.Snippets
|
||||||
|
x.stats = fx.Stats
|
||||||
|
x.importCount = fx.ImportCount
|
||||||
|
x.packagePath = fx.PackagePath
|
||||||
|
x.exports = fx.Exports
|
||||||
|
|
||||||
if fx.Fulltext {
|
if fx.Fulltext {
|
||||||
x.fset = token.NewFileSet()
|
x.fset = token.NewFileSet()
|
||||||
decode := func(x interface{}) error {
|
decode := func(x interface{}) error {
|
||||||
return gob.NewDecoder(r).Decode(x)
|
return gob.NewDecoder(r).Decode(x)
|
||||||
}
|
}
|
||||||
if err := x.fset.Read(decode); err != nil {
|
if err := x.fset.Read(decode); err != nil {
|
||||||
return err
|
return n, err
|
||||||
}
|
}
|
||||||
x.suffixes = new(suffixarray.Index)
|
x.suffixes = new(suffixarray.Index)
|
||||||
if err := x.suffixes.Read(r); err != nil {
|
if err := x.suffixes.Read(r); err != nil {
|
||||||
return err
|
return n, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return n, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stats returns index statistics.
|
// Stats returns index statistics.
|
||||||
|
@ -1204,7 +1231,7 @@ func (c *Corpus) readIndex(filenames string) error {
|
||||||
files = append(files, f)
|
files = append(files, f)
|
||||||
}
|
}
|
||||||
x := new(Index)
|
x := new(Index)
|
||||||
if err := x.Read(io.MultiReader(files...)); err != nil {
|
if _, err := x.ReadFrom(io.MultiReader(files...)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
c.searchIndex.Set(x)
|
c.searchIndex.Set(x)
|
||||||
|
@ -1269,3 +1296,36 @@ func (c *Corpus) RunIndexer() {
|
||||||
time.Sleep(delay)
|
time.Sleep(delay)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type countingWriter struct {
|
||||||
|
n *int64
|
||||||
|
w io.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c countingWriter) Write(p []byte) (n int, err error) {
|
||||||
|
n, err = c.w.Write(p)
|
||||||
|
*c.n += int64(n)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
type byteReader interface {
|
||||||
|
io.Reader
|
||||||
|
io.ByteReader
|
||||||
|
}
|
||||||
|
|
||||||
|
type countingReader struct {
|
||||||
|
n *int64
|
||||||
|
r byteReader
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c countingReader) Read(p []byte) (n int, err error) {
|
||||||
|
n, err = c.r.Read(p)
|
||||||
|
*c.n += int64(n)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c countingReader) ReadByte() (b byte, err error) {
|
||||||
|
b, err = c.r.ReadByte()
|
||||||
|
*c.n += 1
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
package godoc
|
package godoc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -12,7 +13,7 @@ import (
|
||||||
"code.google.com/p/go.tools/godoc/vfs/mapfs"
|
"code.google.com/p/go.tools/godoc/vfs/mapfs"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestIndex(t *testing.T) {
|
func newCorpus(t *testing.T) *Corpus {
|
||||||
c := NewCorpus(mapfs.New(map[string]string{
|
c := NewCorpus(mapfs.New(map[string]string{
|
||||||
"src/pkg/foo/foo.go": `// Package foo is an example.
|
"src/pkg/foo/foo.go": `// Package foo is an example.
|
||||||
package foo
|
package foo
|
||||||
|
@ -46,13 +47,46 @@ func Skip() {}
|
||||||
if err := c.Init(); err != nil {
|
if err := c.Init(); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIndex(t *testing.T) {
|
||||||
|
c := newCorpus(t)
|
||||||
c.UpdateIndex()
|
c.UpdateIndex()
|
||||||
ix, _ := c.CurrentIndex()
|
ix, _ := c.CurrentIndex()
|
||||||
if ix == nil {
|
if ix == nil {
|
||||||
t.Fatal("no index")
|
t.Fatal("no index")
|
||||||
}
|
}
|
||||||
t.Logf("Got: %#v", ix)
|
t.Logf("Got: %#v", ix)
|
||||||
|
testIndex(t, ix)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIndexWriteRead(t *testing.T) {
|
||||||
|
c := newCorpus(t)
|
||||||
|
c.UpdateIndex()
|
||||||
|
ix, _ := c.CurrentIndex()
|
||||||
|
if ix == nil {
|
||||||
|
t.Fatal("no index")
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
nw, err := ix.WriteTo(&buf)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Index.WriteTo: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ix2 := new(Index)
|
||||||
|
nr, err := ix2.ReadFrom(&buf)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Index.ReadFrom: %v", err)
|
||||||
|
}
|
||||||
|
if nr != nw {
|
||||||
|
t.Errorf("Wrote %d bytes to index but read %d", nw, nr)
|
||||||
|
}
|
||||||
|
testIndex(t, ix2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testIndex(t *testing.T, ix *Index) {
|
||||||
wantStats := Statistics{Bytes: 256, Files: 3, Lines: 16, Words: 6, Spots: 9}
|
wantStats := Statistics{Bytes: 256, Files: 3, Lines: 16, Words: 6, Spots: 9}
|
||||||
if !reflect.DeepEqual(ix.Stats(), wantStats) {
|
if !reflect.DeepEqual(ix.Stats(), wantStats) {
|
||||||
t.Errorf("Stats = %#v; want %#v", ix.Stats(), wantStats)
|
t.Errorf("Stats = %#v; want %#v", ix.Stats(), wantStats)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче