Skip to content
Merged
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
1 change: 1 addition & 0 deletions splitio/common/impressionlistener/dtos.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ type ImpressionForListener struct {
Label string `json:"label"`
BucketingKey string `json:"bucketingKey,omitempty"`
Pt int64 `json:"pt,omitempty"`
Properties string `json:"properties,omitempty"`
}

// ImpressionsForListener struct for payload
Expand Down
212 changes: 190 additions & 22 deletions splitio/common/impressionlistener/listener_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,61 +8,228 @@ import (
"testing"

"github.com/splitio/go-split-commons/v9/dtos"
"github.com/stretchr/testify/assert"
)

func TestImpressionListener(t *testing.T) {

reqsDone := make(chan struct{}, 1)
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func() { reqsDone <- struct{}{} }()
if r.URL.Path != "/someUrl" && r.Method != "POST" {
t.Error("Invalid request. Should be POST to /someUrl")
}
// Verify request method and path
assert.False(t, r.URL.Path != "/someUrl" && r.Method != "POST", "Invalid request. Should be POST to /someUrl")

// Read and parse request body
body, err := ioutil.ReadAll(r.Body)
r.Body.Close()
assert.False(t, err != nil, "Error reading body")
if err != nil {
t.Error("Error reading body")
return
}

var all impressionListenerPostBody
err = json.Unmarshal(body, &all)
assert.False(t, err != nil, "Error parsing json: %v", err)
if err != nil {
t.Errorf("Error parsing json: %s", err)
return
}

if all.SdkVersion != "go-1.1.1" || all.MachineIP != "1.2.3.4" || all.MachineName != "ip-1-2-3-4" {
t.Error("invalid metadata")
}
// Verify metadata
assert.False(t, all.SdkVersion != "go-1.1.1" || all.MachineIP != "1.2.3.4" || all.MachineName != "ip-1-2-3-4", "invalid metadata")

// Verify impressions
imps := all.Impressions
if len(imps) != 2 {
t.Error("invalid number of impression groups received")
return
}
assert.Equal(t, 2, len(imps), "Should have 2 impression groups")

// Verify first impression group (t1)
assert.Equal(t, "t1", imps[0].TestName, "First group should be t1")
assert.Equal(t, 2, len(imps[0].KeyImpressions), "t1 should have 2 impressions")

// Verify first impression of t1
assert.Equal(t, "k1", imps[0].KeyImpressions[0].KeyName, "t1 first impression should have correct key name")
assert.Equal(t, "on", imps[0].KeyImpressions[0].Treatment, "t1 first impression should have correct treatment")
assert.Equal(t, int64(1), imps[0].KeyImpressions[0].Time, "t1 first impression should have correct time")
assert.Equal(t, int64(2), imps[0].KeyImpressions[0].ChangeNumber, "t1 first impression should have correct change number")
assert.Equal(t, "l1", imps[0].KeyImpressions[0].Label, "t1 first impression should have correct label")
assert.Equal(t, "b1", imps[0].KeyImpressions[0].BucketingKey, "t1 first impression should have correct bucketing key")
assert.Equal(t, int64(1), imps[0].KeyImpressions[0].Pt, "t1 first impression should have correct pt")

// Verify second impression of t1
assert.Equal(t, "k2", imps[0].KeyImpressions[1].KeyName, "t1 second impression should have correct key name")
assert.Equal(t, "on", imps[0].KeyImpressions[1].Treatment, "t1 second impression should have correct treatment")
assert.Equal(t, int64(1), imps[0].KeyImpressions[1].Time, "t1 second impression should have correct time")
assert.Equal(t, int64(2), imps[0].KeyImpressions[1].ChangeNumber, "t1 second impression should have correct change number")
assert.Equal(t, "l1", imps[0].KeyImpressions[1].Label, "t1 second impression should have correct label")
assert.Equal(t, "b1", imps[0].KeyImpressions[1].BucketingKey, "t1 second impression should have correct bucketing key")
assert.Equal(t, int64(1), imps[0].KeyImpressions[1].Pt, "t1 second impression should have correct pt")

// Verify second impression group (t2)
assert.Equal(t, "t2", imps[1].TestName, "Second group should be t2")
assert.Equal(t, 2, len(imps[1].KeyImpressions), "t2 should have 2 impressions")

// Verify first impression of t2
assert.Equal(t, "k1", imps[1].KeyImpressions[0].KeyName, "t2 first impression should have correct key name")
assert.Equal(t, "off", imps[1].KeyImpressions[0].Treatment, "t2 first impression should have correct treatment")
assert.Equal(t, int64(2), imps[1].KeyImpressions[0].Time, "t2 first impression should have correct time")
assert.Equal(t, int64(3), imps[1].KeyImpressions[0].ChangeNumber, "t2 first impression should have correct change number")
assert.Equal(t, "l2", imps[1].KeyImpressions[0].Label, "t2 first impression should have correct label")
assert.Equal(t, "b2", imps[1].KeyImpressions[0].BucketingKey, "t2 first impression should have correct bucketing key")
assert.Equal(t, int64(2), imps[1].KeyImpressions[0].Pt, "t2 first impression should have correct pt")

// Verify second impression of t2
assert.Equal(t, "k2", imps[1].KeyImpressions[1].KeyName, "t2 second impression should have correct key name")
assert.Equal(t, "off", imps[1].KeyImpressions[1].Treatment, "t2 second impression should have correct treatment")
assert.Equal(t, int64(2), imps[1].KeyImpressions[1].Time, "t2 second impression should have correct time")
assert.Equal(t, int64(3), imps[1].KeyImpressions[1].ChangeNumber, "t2 second impression should have correct change number")
assert.Equal(t, "l2", imps[1].KeyImpressions[1].Label, "t2 second impression should have correct label")
assert.Equal(t, "b2", imps[1].KeyImpressions[1].BucketingKey, "t2 second impression should have correct bucketing key")
assert.Equal(t, int64(3), imps[1].KeyImpressions[1].Pt, "t2 second impression should have correct pt")
}))
defer ts.Close()

listener, err := NewImpressionBulkListener(ts.URL, 10, nil)
assert.False(t, err != nil, "error cannot be nil: %v", err)

err = listener.Start()
assert.False(t, err != nil, "start() should not fail. Got: %v", err)
defer listener.Stop(true)

listener.Submit([]ImpressionsForListener{
ImpressionsForListener{
TestName: "t1",
KeyImpressions: []ImpressionForListener{
ImpressionForListener{
KeyName: "k1",
Treatment: "on",
Time: 1,
ChangeNumber: 2,
Label: "l1",
BucketingKey: "b1",
Pt: 1,
},
ImpressionForListener{
KeyName: "k2",
Treatment: "on",
Time: 1,
ChangeNumber: 2,
Label: "l1",
BucketingKey: "b1",
Pt: 1,
},
},
},
ImpressionsForListener{
TestName: "t2",
KeyImpressions: []ImpressionForListener{
ImpressionForListener{
KeyName: "k1",
Treatment: "off",
Time: 2,
ChangeNumber: 3,
Label: "l2",
BucketingKey: "b2",
Pt: 2,
},
ImpressionForListener{
KeyName: "k2",
Treatment: "off",
Time: 2,
ChangeNumber: 3,
Label: "l2",
BucketingKey: "b2",
Pt: 3,
},
},
},
}, &dtos.Metadata{SDKVersion: "go-1.1.1", MachineIP: "1.2.3.4", MachineName: "ip-1-2-3-4"})

<-reqsDone
}

func TestImpressionListenerWithProperties(t *testing.T) {

if imps[0].TestName != "t1" || len(imps[0].KeyImpressions) != 2 {
t.Errorf("invalid ipmressions for t1")
reqsDone := make(chan struct{}, 1)
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func() { reqsDone <- struct{}{} }()
// Verify request method and path
assert.False(t, r.URL.Path != "/someUrl" && r.Method != "POST", "Invalid request. Should be POST to /someUrl")

// Read and parse request body
body, err := ioutil.ReadAll(r.Body)
r.Body.Close()
assert.False(t, err != nil, "Error reading body")
if err != nil {
return
}

if imps[1].TestName != "t2" || len(imps[1].KeyImpressions) != 2 {
t.Errorf("invalid ipmressions for t2")
var all impressionListenerPostBody
err = json.Unmarshal(body, &all)
assert.False(t, err != nil, "Error parsing json: %v", err)
if err != nil {
return
}

// Verify metadata
assert.False(t, all.SdkVersion != "go-1.1.1" || all.MachineIP != "1.2.3.4" || all.MachineName != "ip-1-2-3-4", "invalid metadata")

// Verify impressions
imps := all.Impressions
assert.Equal(t, 2, len(imps), "Should have 2 impression groups")

// Verify first impression group (t1)
assert.Equal(t, "t1", imps[0].TestName, "First group should be t1")
assert.Equal(t, 2, len(imps[0].KeyImpressions), "t1 should have 2 impressions")

// Verify first impression of t1
assert.Equal(t, "k1", imps[0].KeyImpressions[0].KeyName, "t1 first impression should have correct key name")
assert.Equal(t, "on", imps[0].KeyImpressions[0].Treatment, "t1 first impression should have correct treatment")
assert.Equal(t, int64(1), imps[0].KeyImpressions[0].Time, "t1 first impression should have correct time")
assert.Equal(t, int64(2), imps[0].KeyImpressions[0].ChangeNumber, "t1 first impression should have correct change number")
assert.Equal(t, "l1", imps[0].KeyImpressions[0].Label, "t1 first impression should have correct label")
assert.Equal(t, "b1", imps[0].KeyImpressions[0].BucketingKey, "t1 first impression should have correct bucketing key")
assert.Equal(t, int64(1), imps[0].KeyImpressions[0].Pt, "t1 first impression should have correct pt")
assert.Equal(t, "{'prop':'val'}", imps[0].KeyImpressions[0].Properties, "First impression of t1 should have properties")

// Verify second impression of t1
assert.Equal(t, "k2", imps[0].KeyImpressions[1].KeyName, "t1 second impression should have correct key name")
assert.Equal(t, "on", imps[0].KeyImpressions[1].Treatment, "t1 second impression should have correct treatment")
assert.Equal(t, int64(1), imps[0].KeyImpressions[1].Time, "t1 second impression should have correct time")
assert.Equal(t, int64(2), imps[0].KeyImpressions[1].ChangeNumber, "t1 second impression should have correct change number")
assert.Equal(t, "l1", imps[0].KeyImpressions[1].Label, "t1 second impression should have correct label")
assert.Equal(t, "b1", imps[0].KeyImpressions[1].BucketingKey, "t1 second impression should have correct bucketing key")
assert.Equal(t, int64(1), imps[0].KeyImpressions[1].Pt, "t1 second impression should have correct pt")
// Second impression should not have properties
assert.Empty(t, imps[0].KeyImpressions[1].Properties, "Second impression of t1 should not have properties")

// Verify second impression group (t2)
assert.Equal(t, "t2", imps[1].TestName, "Second group should be t2")
assert.Equal(t, 2, len(imps[1].KeyImpressions), "t2 should have 2 impressions")

// Verify first impression of t2
assert.Equal(t, "k1", imps[1].KeyImpressions[0].KeyName, "t2 first impression should have correct key name")
assert.Equal(t, "off", imps[1].KeyImpressions[0].Treatment, "t2 first impression should have correct treatment")
assert.Equal(t, int64(2), imps[1].KeyImpressions[0].Time, "t2 first impression should have correct time")
assert.Equal(t, int64(3), imps[1].KeyImpressions[0].ChangeNumber, "t2 first impression should have correct change number")
assert.Equal(t, "l2", imps[1].KeyImpressions[0].Label, "t2 first impression should have correct label")
assert.Equal(t, "b2", imps[1].KeyImpressions[0].BucketingKey, "t2 first impression should have correct bucketing key")
assert.Equal(t, int64(2), imps[1].KeyImpressions[0].Pt, "t2 first impression should have correct pt")

// Verify second impression of t2
assert.Equal(t, "k2", imps[1].KeyImpressions[1].KeyName, "t2 second impression should have correct key name")
assert.Equal(t, "off", imps[1].KeyImpressions[1].Treatment, "t2 second impression should have correct treatment")
assert.Equal(t, int64(2), imps[1].KeyImpressions[1].Time, "t2 second impression should have correct time")
assert.Equal(t, int64(3), imps[1].KeyImpressions[1].ChangeNumber, "t2 second impression should have correct change number")
assert.Equal(t, "l2", imps[1].KeyImpressions[1].Label, "t2 second impression should have correct label")
assert.Equal(t, "b2", imps[1].KeyImpressions[1].BucketingKey, "t2 second impression should have correct bucketing key")
assert.Equal(t, int64(3), imps[1].KeyImpressions[1].Pt, "t2 second impression should have correct pt")
}))
defer ts.Close()

listener, err := NewImpressionBulkListener(ts.URL, 10, nil)
if err != nil {
t.Error("error cannot be nil: ", err)
}
assert.False(t, err != nil, "error cannot be nil: %v", err)

if err = listener.Start(); err != nil {
t.Error("start() should not fail. Got: ", err)
}
err = listener.Start()
assert.False(t, err != nil, "start() should not fail. Got: %v", err)
defer listener.Stop(true)

listener.Submit([]ImpressionsForListener{
Expand All @@ -77,6 +244,7 @@ func TestImpressionListener(t *testing.T) {
Label: "l1",
BucketingKey: "b1",
Pt: 1,
Properties: "{'prop':'val'}",
},
ImpressionForListener{
KeyName: "k2",
Expand Down
20 changes: 20 additions & 0 deletions splitio/common/impressionlistener/mocks/listener.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package mocks

import (
"github.com/splitio/split-synchronizer/v5/splitio/common/impressionlistener"
"github.com/stretchr/testify/mock"

"github.com/splitio/go-split-commons/v9/dtos"
)
Expand All @@ -23,3 +24,22 @@ func (l *ImpressionBulkListenerMock) Start() error {
func (l *ImpressionBulkListenerMock) Stop(blocking bool) error {
return l.StopCall(blocking)
}

type MockImpressionBulkListener struct {
mock.Mock
}

func (l *MockImpressionBulkListener) Submit(imps []impressionlistener.ImpressionsForListener, metadata *dtos.Metadata) error {
args := l.Called(imps, metadata)
return args.Error(1)
}

func (l *MockImpressionBulkListener) Start() error {
args := l.Called()
return args.Error(1)
}

func (l *MockImpressionBulkListener) Stop(blocking bool) error {
args := l.Called()
return args.Error(1)
}
2 changes: 2 additions & 0 deletions splitio/producer/task/impressions.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ func (i *ImpressionsPipelineWorker) sendImpressionsToListener(b *impBatches) {
Label: ki.Label,
BucketingKey: ki.BucketingKey,
Pt: ki.Pt,
Properties: ki.Properties,
})
}
payload = append(payload, forTest)
Expand Down Expand Up @@ -268,6 +269,7 @@ func (s *impsWithMetadata) add(i *dtos.Impression) {
Label: i.Label,
BucketingKey: i.BucketingKey,
Pt: i.Pt,
Properties: i.Properties,
})
s.count++
}
Expand Down
Loading
Loading