-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
366 additions
and
50 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#!/bin/bash | ||
|
||
. ~/.nvm/nvm.sh | ||
mkdir -p $FSC_PATH | ||
pushd $FSC_PATH && git init && git fetch --depth=1 https://$CI_USER_TOKEN@github.com/optimizely/fullstack-sdk-compatibility-suite ${FSC_BRANCH:-master} && git checkout FETCH_HEAD | ||
ln -s features/support/datafiles/ public | ||
pushd services/datafile && nvm install && nvm use && npm install && popd | ||
node services/datafile/ &> /dev/null & | ||
popd |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/**************************************************************************** | ||
* Copyright 2019, Optimizely, Inc. and contributors * | ||
* * | ||
* Licensed under the Apache License, Version 2.0 (the "License"); * | ||
* you may not use this file except in compliance with the License. * | ||
* You may obtain a copy of the License at * | ||
* * | ||
* http://www.apache.org/licenses/LICENSE-2.0 * | ||
* * | ||
* Unless required by applicable law or agreed to in writing, software * | ||
* distributed under the License is distributed on an "AS IS" BASIS, * | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * | ||
* See the License for the specific language governing permissions and * | ||
* limitations under the License. * | ||
***************************************************************************/ | ||
|
||
package models | ||
|
||
// DataFileManagerConfiguration represents a datafile manager configuration | ||
type DataFileManagerConfiguration struct { | ||
SDKKey string `yaml:"sdk_key"` | ||
Mode string `yaml:"mode,omitempty"` | ||
Revision *int `yaml:"revision,omitempty"` | ||
DatafileCondition string `yaml:"datafile_condition,omitempty"` | ||
UpdateInterval *int `yaml:"update_interval,omitempty"` | ||
Timeout *int `yaml:"timeout,omitempty"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
/**************************************************************************** | ||
* Copyright 2019, Optimizely, Inc. and contributors * | ||
* * | ||
* Licensed under the Apache License, Version 2.0 (the "License"); * | ||
* you may not use this file except in compliance with the License. * | ||
* You may obtain a copy of the License at * | ||
* * | ||
* http://www.apache.org/licenses/LICENSE-2.0 * | ||
* * | ||
* Unless required by applicable law or agreed to in writing, software * | ||
* distributed under the License is distributed on an "AS IS" BASIS, * | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * | ||
* See the License for the specific language governing permissions and * | ||
* limitations under the License. * | ||
***************************************************************************/ | ||
|
||
package optlyplugins | ||
|
||
import ( | ||
"sync" | ||
"time" | ||
|
||
"github.com/optimizely/go-sdk/pkg" | ||
"github.com/optimizely/go-sdk/pkg/notification" | ||
"github.com/optimizely/go-sdk/tests/integration/models" | ||
) | ||
|
||
// DefaultInitializationTimeout defines default timeout for datafile sync | ||
const DefaultInitializationTimeout = time.Duration(3000) * time.Millisecond | ||
|
||
// TestProjectConfigManager represents a ProjectConfigManager with custom implementations | ||
type TestProjectConfigManager struct { | ||
pkg.ProjectConfigManager | ||
listenersCalled []notification.ProjectConfigUpdateNotification | ||
} | ||
|
||
// GetListenerCallbacks - Creates and returns listener callback array | ||
func (c *TestProjectConfigManager) GetListenerCallbacks(apiOptions models.APIOptions) (listeners []func(notification notification.ProjectConfigUpdateNotification)) { | ||
|
||
projectConfigUpdateCallback := func(notification notification.ProjectConfigUpdateNotification) { | ||
c.listenersCalled = append(c.listenersCalled, notification) | ||
} | ||
|
||
for listenerType, count := range apiOptions.Listeners { | ||
for i := 1; i <= count; i++ { | ||
switch listenerType { | ||
case "Config-update": | ||
listeners = append(listeners, projectConfigUpdateCallback) | ||
break | ||
default: | ||
break | ||
} | ||
} | ||
} | ||
return listeners | ||
} | ||
|
||
// Verify - Verifies configuration tests | ||
func (c *TestProjectConfigManager) Verify(configuration models.DataFileManagerConfiguration) { | ||
timeout := DefaultInitializationTimeout | ||
if configuration.Timeout != nil { | ||
timeout = time.Duration(*(configuration.Timeout)) * time.Millisecond | ||
} | ||
|
||
verify := func(wg *sync.WaitGroup) { | ||
start := time.Now() | ||
switch configuration.Mode { | ||
case "wait_for_on_ready": | ||
for { | ||
t := time.Now() | ||
elapsed := t.Sub(start) | ||
if elapsed >= timeout { | ||
break | ||
} | ||
// Check if projectconfig is ready | ||
_, err := c.GetConfig() | ||
if err == nil { | ||
break | ||
} | ||
} | ||
break | ||
case "wait_for_config_update": | ||
revision := 0 | ||
if configuration.Revision != nil { | ||
revision = *(configuration.Revision) | ||
} | ||
for { | ||
t := time.Now() | ||
elapsed := t.Sub(start) | ||
if elapsed >= timeout { | ||
break | ||
} | ||
if revision > 0 { | ||
// This means we want the manager to poll until we get to a specific revision | ||
if revision == len(c.listenersCalled) { | ||
break | ||
} | ||
} else if len(c.listenersCalled) == 1 { | ||
// For cases where we are just waiting for config listener | ||
break | ||
} | ||
} | ||
break | ||
default: | ||
break | ||
} | ||
wg.Done() | ||
} | ||
|
||
var wg sync.WaitGroup | ||
wg.Add(1) | ||
go verify(&wg) | ||
wg.Wait() | ||
} | ||
|
||
// GetListenersCalled - Returns listeners called | ||
func (c *TestProjectConfigManager) GetListenersCalled() []notification.ProjectConfigUpdateNotification { | ||
listenerCalled := c.listenersCalled | ||
// Since for every scenario, a new sdk instance is created, emptying listenersCalled is required for scenario's | ||
// where multiple requests are executed but no session is to be maintained among them. | ||
// @TODO: Make it optional once event-batching(sessioned) tests are implemented. | ||
c.listenersCalled = nil | ||
return listenerCalled | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
/**************************************************************************** | ||
* Copyright 2019, Optimizely, Inc. and contributors * | ||
* * | ||
* Licensed under the Apache License, Version 2.0 (the "License"); * | ||
* you may not use this file except in compliance with the License. * | ||
* You may obtain a copy of the License at * | ||
* * | ||
* http://www.apache.org/licenses/LICENSE-2.0 * | ||
* * | ||
* Unless required by applicable law or agreed to in writing, software * | ||
* distributed under the License is distributed on an "AS IS" BASIS, * | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * | ||
* See the License for the specific language governing permissions and * | ||
* limitations under the License. * | ||
***************************************************************************/ | ||
|
||
package optlyplugins | ||
|
||
import ( | ||
"io/ioutil" | ||
"log" | ||
"os" | ||
"path" | ||
"path/filepath" | ||
"time" | ||
|
||
"github.com/optimizely/go-sdk/pkg/config" | ||
"github.com/optimizely/go-sdk/pkg/utils" | ||
"github.com/optimizely/go-sdk/tests/integration/models" | ||
) | ||
|
||
const localDatafileURLTemplate = "http://localhost:3001/datafiles/%s.json?request_id=" | ||
|
||
// SyncConfig doesn't request for new datafile if we provide a valid datafile | ||
// this requires us to keep defaultPollingInterval low so that the request | ||
// initiated from Start method is executed quickly | ||
const defaultPollingInterval = time.Duration(1000) * time.Millisecond | ||
|
||
// CreatePollingConfigManager creates a pollingConfigManager with given configuration | ||
func CreatePollingConfigManager(options models.APIOptions) *TestProjectConfigManager { | ||
var pollingConfigManagerOptions []config.OptionFunc | ||
|
||
// Setting up initial datafile | ||
if options.DatafileName != "" { | ||
datafile, err := GetDatafile(options.DatafileName) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
pollingConfigManagerOptions = append(pollingConfigManagerOptions, config.WithInitialDatafile(datafile)) | ||
} | ||
// Setting up polling interval | ||
pollingTimeInterval := defaultPollingInterval | ||
if options.DFMConfiguration.UpdateInterval != nil { | ||
pollingTimeInterval = time.Duration((*options.DFMConfiguration.UpdateInterval)) * time.Millisecond | ||
} | ||
pollingConfigManagerOptions = append(pollingConfigManagerOptions, config.WithPollingInterval(pollingTimeInterval)) | ||
sdkKey := GetSDKKey(options.DFMConfiguration) | ||
urlString := localDatafileURLTemplate + options.ScenarioID | ||
pollingConfigManagerOptions = append(pollingConfigManagerOptions, config.WithDatafileURLTemplate(urlString)) | ||
|
||
testProjectConfigManagerInstance := &TestProjectConfigManager{} | ||
pollingConfigManagerOptions = append(pollingConfigManagerOptions, config.WithNotificationHandlers(testProjectConfigManagerInstance.GetListenerCallbacks(options)...)) | ||
|
||
configManager := config.NewPollingProjectConfigManager( | ||
sdkKey, | ||
pollingConfigManagerOptions..., | ||
) | ||
testProjectConfigManagerInstance.ProjectConfigManager = configManager | ||
// Since we are using TestProjectConfigManager over ProjectConfigManager, factory will | ||
// not call the start method for ProjectConfigManager, so we have to do it manually | ||
exeCtx := utils.NewCancelableExecutionCtx() | ||
configManager.Start(sdkKey, exeCtx) | ||
// Verify datafile configuration tests | ||
testProjectConfigManagerInstance.Verify(options.DFMConfiguration) | ||
|
||
return testProjectConfigManagerInstance | ||
} | ||
|
||
// GetDatafile returns datafile,error for the provided datafileName | ||
func GetDatafile(datafileName string) ([]byte, error) { | ||
datafileDir := os.Getenv("DATAFILES_DIR") | ||
return ioutil.ReadFile(filepath.Clean(path.Join(datafileDir, datafileName))) | ||
} | ||
|
||
// GetSDKKey returns SDKKey for configuration | ||
func GetSDKKey(configuration models.DataFileManagerConfiguration) (sdkKey string) { | ||
sdkKey = configuration.SDKKey | ||
if configuration.DatafileCondition != "" { | ||
sdkKey += "_" + configuration.DatafileCondition | ||
} | ||
return sdkKey | ||
} |
Oops, something went wrong.