Explorar el Código

Updated config tests. Added delimiters around sample config in README to help with programmatically processing it.

Adam Pritchard hace 11 años
padre
commit
a7db54a393
Se han modificado 2 ficheros con 96 adiciones y 104 borrados
  1. 2 0
      README.md
  2. 94 104
      psiphon/config_test.go

+ 2 - 0
README.md

@@ -24,6 +24,7 @@ Setup
 * This project builds and runs on recent versions of Windows, Linux, and Mac OS X.
 * Run `./psiphon-tunnel-core --config psiphon.config` where the config file looks like this:
 
+<!--BEGIN-SAMPLE-CONFIG-->
     ```
     {
         "PropagationChannelId" : "<placeholder>",
@@ -43,6 +44,7 @@ Setup
         "UpstreamHttpProxyAddress" : ""
     }
     ```
+<!--END-SAMPLE-CONFIG-->
 
 * Replace each `<placeholder>` with a value from your Psiphon network. The Psiphon server-side stack is open source and can be found in our  [Psiphon 3 repository](https://bitbucket.org/psiphon/psiphon-circumvention-system). If you would like to use the Psiphon Inc. network, contact <developer-support@psiphon.ca>.
 * The project builds and runs on Android. See the [AndroidLibrary README](AndroidLibrary/README.md) for more information about building the Go component, and the [AndroidApp README](AndroidApp/README.md) for a sample Android app that uses it.

+ 94 - 104
psiphon/config_test.go

@@ -19,145 +19,135 @@
 
 package psiphon
 
-/*
-NOTE: This test suite is probably overkill for such a simple file. It also
-probably shouldn't be doing error type checking, and especially not checking
-for particular JSON package errors. This is our first test file and mostly
-intended to be something to learn from and derive other test sets.
-*/
-
 import (
-	"os"
-	"path/filepath"
+	"encoding/json"
+	"io/ioutil"
+	"strings"
 	"testing"
 
 	"github.com/stretchr/testify/suite"
 )
 
 const (
-	_TEST_DIR = "./testfiles"
+	_README              = "../README.md"
+	_README_CONFIG_BEGIN = "<!--BEGIN-SAMPLE-CONFIG-->"
+	_README_CONFIG_END   = "<!--END-SAMPLE-CONFIG-->"
 )
 
 type ConfigTestSuite struct {
 	suite.Suite
+	confStubBlob      []byte
+	requiredFields    []string
+	nonRequiredFields []string
 }
 
-func (suite *ConfigTestSuite) SetupTest() {
-	os.Mkdir(_TEST_DIR, 0777)
-}
-
-func (suite *ConfigTestSuite) TearDownTest() {
-	os.RemoveAll(_TEST_DIR)
+func (suite *ConfigTestSuite) SetupSuite() {
+	readmeBlob, _ := ioutil.ReadFile(_README)
+	readmeString := string(readmeBlob)
+	readmeString = readmeString[strings.Index(readmeString, _README_CONFIG_BEGIN)+len(_README_CONFIG_BEGIN) : strings.Index(readmeString, _README_CONFIG_END)]
+	readmeString = strings.TrimSpace(readmeString)
+	readmeString = strings.Trim(readmeString, "`")
+
+	suite.confStubBlob = []byte(readmeString)
+
+	var obj map[string]interface{}
+	json.Unmarshal(suite.confStubBlob, &obj)
+	for k, v := range obj {
+		if v == "<placeholder>" {
+			suite.requiredFields = append(suite.requiredFields, k)
+		} else {
+			suite.nonRequiredFields = append(suite.nonRequiredFields, k)
+		}
+	}
 }
 
 func TestConfigTestSuite(t *testing.T) {
 	suite.Run(t, new(ConfigTestSuite))
 }
 
-func writeConfigFile(filename string, contents string) {
-	configFile, _ := os.Create(filename)
-	configFile.WriteString(contents)
-	configFile.Close()
-}
-
-// Tests bad config file path
-func (suite *ConfigTestSuite) Test_LoadConfig_BadPath() {
-	_, err := LoadConfig("BAADPATH")
-	suite.NotNil(err, "error should be set")
-}
-
-// Tests good config file path
-func (suite *ConfigTestSuite) Test_LoadConfig_GoodPath() {
-	filename := filepath.Join(_TEST_DIR, "good.json")
-	writeConfigFile(filename, `{"PropagationChannelId": "xyz", "SponsorId": "xyz", "RemoteServerListUrl": "xyz", "RemoteServerListSignaturePublicKey": "xyz"}`)
-
-	// Use absolute path
-	abspath, _ := filepath.Abs(filename)
-	_, err := LoadConfig(abspath)
-	suite.Nil(err, "error should not be set")
-
-	// Use relative path
-	suite.False(filepath.IsAbs(filename))
-	_, err = LoadConfig(filename)
-	suite.Nil(err, "error should not be set")
+// Tests good config
+func (suite *ConfigTestSuite) Test_LoadConfig_BasicGood() {
+	_, err := LoadConfig(suite.confStubBlob)
+	suite.Nil(err, "a basic config should succeed")
 }
 
 // Tests non-JSON file contents
 func (suite *ConfigTestSuite) Test_LoadConfig_BadFileContents() {
-	filename := filepath.Join(_TEST_DIR, "junk.json")
-	writeConfigFile(filename, "**ohhi**")
-	_, err := LoadConfig(filename)
-	suite.NotNil(err, "error should be set")
+	_, err := LoadConfig([]byte(`this is not JSON`))
+	suite.NotNil(err, "bytes that are not JSON at all should give an error")
 }
 
 // Tests config file with JSON contents that don't match our structure
 func (suite *ConfigTestSuite) Test_LoadConfig_BadJson() {
-	filename := filepath.Join(_TEST_DIR, "other.json")
-
-	// Has none of our fields
-	writeConfigFile(filename, `{"f1": 11, "f2": "two"}`)
-	_, err := LoadConfig(filename)
-	suite.NotNil(err, "error should be set")
-
-	// Has one of our required fields, but wrong type
-	writeConfigFile(filename, `{"PropagationChannelId": 11, "f2": "two"}`)
-	_, err = LoadConfig(filename)
-	suite.NotNil(err, "error should be set")
-
-	// Has one of our required fields, but null
-	writeConfigFile(filename, `{"PropagationChannelId": null, "f2": "two"}`)
-	_, err = LoadConfig(filename)
-	suite.NotNil(err, "error should be set")
-
-	// Has one of our required fields, but empty string
-	writeConfigFile(filename, `{"PropagationChannelId": "", "f2": "two"}`)
-	_, err = LoadConfig(filename)
-	suite.NotNil(err, "error should be set")
-
-	// Has all of our required fields, but no optional fields
-	writeConfigFile(filename, `{"PropagationChannelId": "xyz", "SponsorId": "xyz", "RemoteServerListUrl": "xyz", "RemoteServerListSignaturePublicKey": "xyz"}`)
-	config, err := LoadConfig(filename)
-	suite.Nil(err, "should be no error")
-	suite.Equal("xyz", config.PropagationChannelId)
+	var testObj map[string]interface{}
+	var testObjJSON []byte
+
+	// JSON with none of our fields
+	_, err := LoadConfig([]byte(`{"f1": 11, "f2": "two"}`))
+	suite.NotNil(err, "JSON with none of our fields should fail")
+
+	// Missing a required field
+	json.Unmarshal(suite.confStubBlob, &testObj)
+	delete(testObj, suite.requiredFields[0])
+	testObjJSON, _ = json.Marshal(testObj)
+	_, err = LoadConfig(testObjJSON)
+	suite.NotNil(err, "JSON with one of our required fields missing should fail")
+
+	// Bad type for required field
+	json.Unmarshal(suite.confStubBlob, &testObj)
+	testObj[suite.requiredFields[0]] = false // basically guessing a wrong type
+	testObjJSON, _ = json.Marshal(testObj)
+	_, err = LoadConfig(testObjJSON)
+	suite.NotNil(err, "JSON with one of our required fields with the wrong type should fail")
+
+	// One of our required fields is null
+	json.Unmarshal(suite.confStubBlob, &testObj)
+	testObj[suite.requiredFields[0]] = nil
+	testObjJSON, _ = json.Marshal(testObj)
+	_, err = LoadConfig(testObjJSON)
+	suite.NotNil(err, "JSON with one of our required fields set to null should fail")
+
+	// One of our required fields is an empty string
+	json.Unmarshal(suite.confStubBlob, &testObj)
+	testObj[suite.requiredFields[0]] = ""
+	testObjJSON, _ = json.Marshal(testObj)
+	_, err = LoadConfig(testObjJSON)
+	suite.NotNil(err, "JSON with one of our required fields set to an empty string should fail")
 
 	// Has incorrect type for optional field
-	writeConfigFile(filename, `{"ClientVersion": "string, not int", "PropagationChannelId": "xyz", "SponsorId": "xyz", "RemoteServerListUrl": "xyz", "RemoteServerListSignaturePublicKey": "xyz"}`)
-	_, err = LoadConfig(filename)
-	suite.NotNil(err, "error should be set")
-
-	// Has null for optional field
-	writeConfigFile(filename, `{"ClientVersion": null, "PropagationChannelId": "xyz", "SponsorId": "xyz", "RemoteServerListUrl": "xyz", "RemoteServerListSignaturePublicKey": "xyz"}`)
-	config, err = LoadConfig(filename)
-	suite.Nil(err, "should be no error")
-	suite.Equal(0, config.ClientVersion)
+	json.Unmarshal(suite.confStubBlob, &testObj)
+	testObj[suite.nonRequiredFields[0]] = false // basically guessing a wrong type
+	testObjJSON, _ = json.Marshal(testObj)
+	_, err = LoadConfig(testObjJSON)
+	suite.NotNil(err, "JSON with one of our optional fields with the wrong type should fail")
 }
 
 // Tests config file with JSON contents that don't match our structure
 func (suite *ConfigTestSuite) Test_LoadConfig_GoodJson() {
-	filename := filepath.Join(_TEST_DIR, "good.json")
+	var testObj map[string]interface{}
+	var testObjJSON []byte
+
+	// TODO: Test that the config actually gets the values we expect?
 
 	// Has all of our required fields, but no optional fields
-	writeConfigFile(filename, `{"PropagationChannelId": "pci", "SponsorId": "si", "RemoteServerListUrl": "rslu", "RemoteServerListSignaturePublicKey": "rslspk"}`)
-	config, err := LoadConfig(filename)
-	suite.Nil(err, "should be no error")
-	suite.Equal("pci", config.PropagationChannelId)
-	suite.Equal("si", config.SponsorId)
-	suite.Equal("rslu", config.RemoteServerListUrl)
-	suite.Equal("rslspk", config.RemoteServerListSignaturePublicKey)
+	json.Unmarshal(suite.confStubBlob, &testObj)
+	for i := range suite.nonRequiredFields {
+		delete(testObj, suite.nonRequiredFields[i])
+	}
+	testObjJSON, _ = json.Marshal(testObj)
+	_, err := LoadConfig(testObjJSON)
+	suite.Nil(err, "JSON with good values for our required fields but no optional fields should succeed")
 
 	// Has all of our required fields, and all optional fields
-	writeConfigFile(filename, `{"PropagationChannelId": "pci", "SponsorId": "si", "RemoteServerListUrl": "rslu", "RemoteServerListSignaturePublicKey": "rslspk", "LogFilename": "lf", "ClientVersion": 12, "ClientPlatform": "cp", "TunnelWholeDevice": 34, "EgressRegion": "er", "LocalSocksProxyPort": 56, "LocalHttpProxyPort": 78}`)
-	config, err = LoadConfig(filename)
-	suite.Nil(err, "should be no error")
-	suite.Equal("pci", config.PropagationChannelId)
-	suite.Equal("si", config.SponsorId)
-	suite.Equal("rslu", config.RemoteServerListUrl)
-	suite.Equal("rslspk", config.RemoteServerListSignaturePublicKey)
-	suite.Equal("lf", config.LogFilename)
-	suite.Equal(12, config.ClientVersion)
-	suite.Equal("cp", config.ClientPlatform)
-	suite.Equal(34, config.TunnelWholeDevice)
-	suite.Equal("er", config.EgressRegion)
-	suite.Equal(56, config.LocalSocksProxyPort)
-	suite.Equal(78, config.LocalHttpProxyPort)
+	_, err = LoadConfig(suite.confStubBlob)
+	suite.Nil(err, "JSON with all good values for required and optional fields should succeed")
+
+	// Has null for optional fields
+	json.Unmarshal(suite.confStubBlob, &testObj)
+	for i := range suite.nonRequiredFields {
+		testObj[suite.nonRequiredFields[i]] = nil
+	}
+	testObjJSON, _ = json.Marshal(testObj)
+	_, err = LoadConfig(testObjJSON)
+	suite.Nil(err, "JSON with null for optional values should succeed")
 }