Просмотр исходного кода

Add Open/CloseDataStore calls required for stand-alone GetTactics

Rod Hynes 5 лет назад
Родитель
Сommit
354a3afac4
3 измененных файлов с 122 добавлено и 5 удалено
  1. 0 5
      psiphon/controller_test.go
  2. 20 0
      psiphon/dataStore.go
  3. 102 0
      psiphon/tactics_test.go

+ 0 - 5
psiphon/controller_test.go

@@ -566,11 +566,6 @@ func controllerRun(t *testing.T, runConfig *controllerRunConfig) {
 		t.Fatalf("error committing configuration file: %s", err)
 	}
 
-	// Enable tactics requests. This will passively exercise the code
-	// paths. server_test runs a more comprehensive test that checks
-	// that the tactics request succeeds.
-	config.NetworkID = "NETWORK1"
-
 	err = OpenDataStore(config)
 	if err != nil {
 		t.Fatalf("error initializing datastore: %s", err)

+ 20 - 0
psiphon/dataStore.go

@@ -600,6 +600,16 @@ func (iterator *ServerEntryIterator) reset(isInitialRound bool) error {
 		return nil
 	}
 
+	// Support stand-alone GetTactics operation. See TacticsStorer for more
+	// details.
+	if iterator.isTacticsServerEntryIterator {
+		err := OpenDataStore(iterator.config)
+		if err != nil {
+			return errors.Trace(err)
+		}
+		defer CloseDataStore()
+	}
+
 	// BoltDB implementation note:
 	// We don't keep a transaction open for the duration of the iterator
 	// because this would expose the following semantics to consumer code:
@@ -740,6 +750,16 @@ func (iterator *ServerEntryIterator) Next() (*protocol.ServerEntry, error) {
 		return nil, nil
 	}
 
+	// Support stand-alone GetTactics operation. See TacticsStorer for more
+	// details.
+	if iterator.isTacticsServerEntryIterator {
+		err := OpenDataStore(iterator.config)
+		if err != nil {
+			return nil, errors.Trace(err)
+		}
+		defer CloseDataStore()
+	}
+
 	// There are no region/protocol indexes for the server entries bucket.
 	// Loop until we have the next server entry that matches the iterator
 	// filter requirements.

+ 102 - 0
psiphon/tactics_test.go

@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2020, Psiphon Inc.
+ * All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package psiphon
+
+import (
+	"context"
+	"encoding/json"
+	"io/ioutil"
+	"os"
+	"sync/atomic"
+	"testing"
+	"time"
+)
+
+func TestStandAloneGetTactics(t *testing.T) {
+
+	testDataDirName, err := ioutil.TempDir("", "psiphon-tactics-test")
+	if err != nil {
+		t.Fatalf("TempDir failed: %s\n", err)
+	}
+	defer os.RemoveAll(testDataDirName)
+
+	configJSON, err := ioutil.ReadFile("controller_test.config")
+	if err != nil {
+		// Skip, don't fail, if config file is not present
+		t.Skipf("error loading configuration file: %s", err)
+	}
+
+	var modifyConfig map[string]interface{}
+	json.Unmarshal(configJSON, &modifyConfig)
+	modifyConfig["DataRootDirectory"] = testDataDirName
+
+	configJSON, _ = json.Marshal(modifyConfig)
+
+	config, err := LoadConfig(configJSON)
+	if err != nil {
+		t.Fatalf("error processing configuration file: %s", err)
+	}
+
+	err = config.Commit(false)
+	if err != nil {
+		t.Fatalf("error committing configuration file: %s", err)
+	}
+
+	gotTactics := int32(0)
+
+	SetNoticeWriter(NewNoticeReceiver(
+		func(notice []byte) {
+			noticeType, _, err := GetNotice(notice)
+			if err != nil {
+				return
+			}
+			switch noticeType {
+			case "RequestedTactics":
+				atomic.StoreInt32(&gotTactics, 1)
+			}
+		}))
+
+	ctx, cancelFunc := context.WithTimeout(context.Background(), 30*time.Second)
+	defer cancelFunc()
+
+	err = OpenDataStore(config)
+	if err != nil {
+		t.Fatalf("error committing initializing datastore: %s", err)
+	}
+
+	untunneledDialConfig := &DialConfig{
+		UpstreamProxyURL: config.UpstreamProxyURL,
+	}
+
+	err = FetchCommonRemoteServerList(ctx, config, 0, nil, untunneledDialConfig)
+	if err != nil {
+		t.Fatalf("error cfetching remote server list: %s", err)
+	}
+
+	// Close the datastore to exercise the OpenDatastore/CloseDatastore
+	// operations in GetTactics.
+	CloseDataStore()
+
+	GetTactics(ctx, config)
+
+	if atomic.LoadInt32(&gotTactics) != 1 {
+		t.Fatalf("failed to get tactics")
+	}
+}