github.com/olivere/camlistore@v0.0.0-20140121221811-1b7ac2da0199/pkg/serverconfig/serverconfig_test.go (about)

     1  /*
     2  Copyright 2012 Google Inc.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8       http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package serverconfig_test
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/json"
    22  	"errors"
    23  	"flag"
    24  	"fmt"
    25  	"io"
    26  	"io/ioutil"
    27  	"os"
    28  	"path/filepath"
    29  	"sort"
    30  	"strings"
    31  	"testing"
    32  
    33  	"camlistore.org/pkg/jsonconfig"
    34  	"camlistore.org/pkg/serverconfig"
    35  	"camlistore.org/pkg/test"
    36  )
    37  
    38  var updateGolden = flag.Bool("update_golden", false, "Update golden *.want files")
    39  
    40  const (
    41  	// relativeRing points to a real secret ring, but serverconfig
    42  	// rewrites it to be an absolute path.  We then canonicalize
    43  	// it to secringPlaceholder in the golden files.
    44  	relativeRing       = "../jsonsign/testdata/test-secring.gpg"
    45  	secringPlaceholder = "/path/to/secring"
    46  )
    47  
    48  func init() {
    49  	// Avoid Linux vs. OS X differences in tests.
    50  	serverconfig.SetTempDirFunc(func() string { return "/tmp" })
    51  	serverconfig.SetNoMkdir(true)
    52  }
    53  
    54  func sortedKeys(m map[string]interface{}) (keys []string) {
    55  	for k := range m {
    56  		keys = append(keys, k)
    57  	}
    58  	sort.Strings(keys)
    59  	return
    60  }
    61  
    62  func prettyPrint(t *testing.T, w io.Writer, i interface{}, indent int) {
    63  	out, err := json.MarshalIndent(i, "", "  ")
    64  	if err != nil {
    65  		t.Fatal(err)
    66  	}
    67  	w.Write(out)
    68  }
    69  
    70  func TestConfigs(t *testing.T) {
    71  	dir, err := os.Open("testdata")
    72  	if err != nil {
    73  		t.Fatal(err)
    74  	}
    75  	names, err := dir.Readdirnames(-1)
    76  	if err != nil {
    77  		t.Fatal(err)
    78  	}
    79  	for _, name := range names {
    80  		if strings.HasSuffix(name, ".json") {
    81  			if strings.HasSuffix(name, "-want.json") {
    82  				continue
    83  			}
    84  			testConfig(filepath.Join("testdata", name), t)
    85  		}
    86  	}
    87  }
    88  
    89  type namedReadSeeker struct {
    90  	name string
    91  	io.ReadSeeker
    92  }
    93  
    94  func (n namedReadSeeker) Name() string { return n.name }
    95  func (n namedReadSeeker) Close() error { return nil }
    96  
    97  func configParser() *jsonconfig.ConfigParser {
    98  	// Make a custom jsonconfig ConfigParser whose reader rewrites "/path/to/secring" to the absolute
    99  	// path of the jsonconfig test-secring.gpg file.
   100  	secRing, err := filepath.Abs("../jsonsign/testdata/test-secring.gpg")
   101  	if err != nil {
   102  		panic(err)
   103  	}
   104  	return &jsonconfig.ConfigParser{
   105  		Open: func(path string) (jsonconfig.File, error) {
   106  			slurpBytes, err := ioutil.ReadFile(path)
   107  			if err != nil {
   108  				return nil, err
   109  			}
   110  			slurp := strings.Replace(string(slurpBytes), secringPlaceholder, secRing, 1)
   111  			return namedReadSeeker{path, strings.NewReader(slurp)}, nil
   112  		},
   113  	}
   114  }
   115  
   116  func testConfig(name string, t *testing.T) {
   117  	obj, err := configParser().ReadFile(name)
   118  	if err != nil {
   119  		t.Fatal(err)
   120  	}
   121  	wantedError := func() error {
   122  		slurp, err := ioutil.ReadFile(strings.Replace(name, ".json", ".err", 1))
   123  		if os.IsNotExist(err) {
   124  			return nil
   125  		}
   126  		if err != nil {
   127  			t.Fatalf("Error reading .err file: %v", err)
   128  		}
   129  		return errors.New(string(slurp))
   130  	}
   131  	lowLevelConf, err := serverconfig.GenLowLevelConfig(&serverconfig.Config{Obj: obj})
   132  	if g, w := strings.TrimSpace(fmt.Sprint(err)), strings.TrimSpace(fmt.Sprint(wantedError())); g != w {
   133  		t.Fatalf("test %s: got GenLowLevelConfig error %q; want %q", name, g, w)
   134  	}
   135  	if err != nil {
   136  		return
   137  	}
   138  
   139  	wantFile := strings.Replace(name, ".json", "-want.json", 1)
   140  	wantConf, err := configParser().ReadFile(wantFile)
   141  	if err != nil {
   142  		t.Fatalf("test %s: ReadFile: %v", name, err)
   143  	}
   144  	var got, want bytes.Buffer
   145  	prettyPrint(t, &got, lowLevelConf.Obj, 0)
   146  	prettyPrint(t, &want, wantConf, 0)
   147  	if got.String() != want.String() {
   148  		if *updateGolden {
   149  			contents, err := json.MarshalIndent(lowLevelConf.Obj, "", "\t")
   150  			if err != nil {
   151  				t.Fatal(err)
   152  			}
   153  			contents = canonicalizeGolden(t, contents)
   154  			if err := ioutil.WriteFile(wantFile, contents, 0644); err != nil {
   155  				t.Fatal(err)
   156  			}
   157  		}
   158  		t.Errorf("test %s configurations differ.\nGot:\n%s\nWant:\n%s\nDiff (got -> want), %s:\n%s",
   159  			name, &got, &want, name, test.Diff(got.Bytes(), want.Bytes()))
   160  	}
   161  }
   162  
   163  func canonicalizeGolden(t *testing.T, v []byte) []byte {
   164  	localPath, err := filepath.Abs("../jsonsign/testdata/test-secring.gpg")
   165  	if err != nil {
   166  		t.Fatal(err)
   167  	}
   168  	v = bytes.Replace(v, []byte(localPath), []byte(secringPlaceholder), 1)
   169  	if !bytes.HasSuffix(v, []byte("\n")) {
   170  		v = append(v, '\n')
   171  	}
   172  	return v
   173  }