Home | History | Annotate | Download | only in token
      1 // Copyright 2011 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package token
      6 
      7 import (
      8 	"bytes"
      9 	"encoding/gob"
     10 	"fmt"
     11 	"testing"
     12 )
     13 
     14 // equal returns nil if p and q describe the same file set;
     15 // otherwise it returns an error describing the discrepancy.
     16 func equal(p, q *FileSet) error {
     17 	if p == q {
     18 		// avoid deadlock if p == q
     19 		return nil
     20 	}
     21 
     22 	// not strictly needed for the test
     23 	p.mutex.Lock()
     24 	q.mutex.Lock()
     25 	defer q.mutex.Unlock()
     26 	defer p.mutex.Unlock()
     27 
     28 	if p.base != q.base {
     29 		return fmt.Errorf("different bases: %d != %d", p.base, q.base)
     30 	}
     31 
     32 	if len(p.files) != len(q.files) {
     33 		return fmt.Errorf("different number of files: %d != %d", len(p.files), len(q.files))
     34 	}
     35 
     36 	for i, f := range p.files {
     37 		g := q.files[i]
     38 		if f.set != p {
     39 			return fmt.Errorf("wrong fileset for %q", f.name)
     40 		}
     41 		if g.set != q {
     42 			return fmt.Errorf("wrong fileset for %q", g.name)
     43 		}
     44 		if f.name != g.name {
     45 			return fmt.Errorf("different filenames: %q != %q", f.name, g.name)
     46 		}
     47 		if f.base != g.base {
     48 			return fmt.Errorf("different base for %q: %d != %d", f.name, f.base, g.base)
     49 		}
     50 		if f.size != g.size {
     51 			return fmt.Errorf("different size for %q: %d != %d", f.name, f.size, g.size)
     52 		}
     53 		for j, l := range f.lines {
     54 			m := g.lines[j]
     55 			if l != m {
     56 				return fmt.Errorf("different offsets for %q", f.name)
     57 			}
     58 		}
     59 		for j, l := range f.infos {
     60 			m := g.infos[j]
     61 			if l.Offset != m.Offset || l.Filename != m.Filename || l.Line != m.Line {
     62 				return fmt.Errorf("different infos for %q", f.name)
     63 			}
     64 		}
     65 	}
     66 
     67 	// we don't care about .last - it's just a cache
     68 	return nil
     69 }
     70 
     71 func checkSerialize(t *testing.T, p *FileSet) {
     72 	var buf bytes.Buffer
     73 	encode := func(x interface{}) error {
     74 		return gob.NewEncoder(&buf).Encode(x)
     75 	}
     76 	if err := p.Write(encode); err != nil {
     77 		t.Errorf("writing fileset failed: %s", err)
     78 		return
     79 	}
     80 	q := NewFileSet()
     81 	decode := func(x interface{}) error {
     82 		return gob.NewDecoder(&buf).Decode(x)
     83 	}
     84 	if err := q.Read(decode); err != nil {
     85 		t.Errorf("reading fileset failed: %s", err)
     86 		return
     87 	}
     88 	if err := equal(p, q); err != nil {
     89 		t.Errorf("filesets not identical: %s", err)
     90 	}
     91 }
     92 
     93 func TestSerialization(t *testing.T) {
     94 	p := NewFileSet()
     95 	checkSerialize(t, p)
     96 	// add some files
     97 	for i := 0; i < 10; i++ {
     98 		f := p.AddFile(fmt.Sprintf("file%d", i), p.Base()+i, i*100)
     99 		checkSerialize(t, p)
    100 		// add some lines and alternative file infos
    101 		line := 1000
    102 		for offs := 0; offs < f.Size(); offs += 40 + i {
    103 			f.AddLine(offs)
    104 			if offs%7 == 0 {
    105 				f.AddLineInfo(offs, fmt.Sprintf("file%d", offs), line)
    106 				line += 33
    107 			}
    108 		}
    109 		checkSerialize(t, p)
    110 	}
    111 }
    112