Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/spec_store.rb
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ def process_specs(specs_string, from_adapter: false)

hashed_sdk_key_used = specs_json[:hashed_sdk_key_used]
unless hashed_sdk_key_used.nil? or hashed_sdk_key_used == Statsig::HashUtils.djb2(@secret_key)
err_boundary.log_exception(Statsig::InvalidSDKKeyResponse.new)
@error_boundary.log_exception(Statsig::InvalidSDKKeyResponse.new)
return {reason: "PARSE_RESPONSE_ERROR"}
end

Expand Down
69 changes: 69 additions & 0 deletions test/test_spec_store_error_boundary_usage.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
require_relative 'test_helper'
require 'minitest'
require 'minitest/autorun'
require 'statsig'
require 'webmock/minitest'

class TestSpecStoreErrorBoundaryUsage < BaseTest
suite :TestSpecStoreErrorBoundaryUsage

def setup
super
WebMock.enable!
@diagnostics = Statsig::Diagnostics.new
@sdk_configs = Statsig::SDKConfigs.new
@error_boundary = Statsig::ErrorBoundary.new('secret-key', false)
@options = StatsigOptions.new
@network = Statsig::Network.new('secret-key', @options)
@logger = Statsig::StatsigLogger.new(@network, @options, @error_boundary, @sdk_configs)
end

def teardown
super
WebMock.reset!
WebMock.disable!
end

def test_process_specs_logs_to_error_boundary_on_invalid_key
# This test ensures that when an invalid SDK key is detected in the response,
# the error is correctly logged to the error boundary.
# Before the fix, this would have raised a NoMethodError because it tried to call
# @err_boundary instead of @error_boundary.

invalid_response = {
feature_gates: {},
dynamic_configs: {},
layer_configs: {},
has_updates: true,
time: 123,
hashed_sdk_key_used: 'invalid-key-hash'
}.to_json

stub_request(:post, 'https://statsigapi.net/v1/sdk_exception').to_return(status: 200)
stub_request(:post, 'https://statsigapi.net/v1/get_id_lists').to_return(status: 200, body: '{}')
stub_download_config_specs.to_return(status: 200, body: invalid_response)

# SpecStore.new calls download_config_specs -> process_specs
# We need to ensure that hashed_sdk_key_used in the response is NOT equal to djb2(@secret_key)
# djb2('secret-key') is '110609353'

store = Statsig::SpecStore.new(
@network,
@options,
nil,
@diagnostics,
@error_boundary,
@logger,
'secret-key',
@sdk_configs
)

# Verify that the exception was logged to the error boundary endpoint
# The first call to log_exception for InvalidSDKKeyResponse will trigger the network request.
# Subsequent calls with the same exception class will be ignored by ErrorBoundary unless force: true.
assert_requested(:post, 'https://statsigapi.net/v1/sdk_exception', times: 1) do |req|
body = JSON.parse(req.body)
assert_equal('Statsig::InvalidSDKKeyResponse', body['exception'])
end
end
end