Skip to content

Commit cbd3137

Browse files
authored
Merge pull request #338 from splitio/FME-11990
Added impression properties for proxy and sync
2 parents 133ded2 + 28bd979 commit cbd3137

File tree

8 files changed

+533
-23
lines changed

8 files changed

+533
-23
lines changed

splitio/common/impressionlistener/dtos.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ type ImpressionForListener struct {
99
Label string `json:"label"`
1010
BucketingKey string `json:"bucketingKey,omitempty"`
1111
Pt int64 `json:"pt,omitempty"`
12+
Properties string `json:"properties,omitempty"`
1213
}
1314

1415
// ImpressionsForListener struct for payload

splitio/common/impressionlistener/listener_test.go

Lines changed: 190 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,61 +8,228 @@ import (
88
"testing"
99

1010
"github.com/splitio/go-split-commons/v9/dtos"
11+
"github.com/stretchr/testify/assert"
1112
)
1213

1314
func TestImpressionListener(t *testing.T) {
1415

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

22+
// Read and parse request body
2223
body, err := ioutil.ReadAll(r.Body)
2324
r.Body.Close()
25+
assert.False(t, err != nil, "Error reading body")
2426
if err != nil {
25-
t.Error("Error reading body")
2627
return
2728
}
2829

2930
var all impressionListenerPostBody
3031
err = json.Unmarshal(body, &all)
32+
assert.False(t, err != nil, "Error parsing json: %v", err)
3133
if err != nil {
32-
t.Errorf("Error parsing json: %s", err)
3334
return
3435
}
3536

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

40+
// Verify impressions
4041
imps := all.Impressions
41-
if len(imps) != 2 {
42-
t.Error("invalid number of impression groups received")
43-
return
44-
}
42+
assert.Equal(t, 2, len(imps), "Should have 2 impression groups")
43+
44+
// Verify first impression group (t1)
45+
assert.Equal(t, "t1", imps[0].TestName, "First group should be t1")
46+
assert.Equal(t, 2, len(imps[0].KeyImpressions), "t1 should have 2 impressions")
47+
48+
// Verify first impression of t1
49+
assert.Equal(t, "k1", imps[0].KeyImpressions[0].KeyName, "t1 first impression should have correct key name")
50+
assert.Equal(t, "on", imps[0].KeyImpressions[0].Treatment, "t1 first impression should have correct treatment")
51+
assert.Equal(t, int64(1), imps[0].KeyImpressions[0].Time, "t1 first impression should have correct time")
52+
assert.Equal(t, int64(2), imps[0].KeyImpressions[0].ChangeNumber, "t1 first impression should have correct change number")
53+
assert.Equal(t, "l1", imps[0].KeyImpressions[0].Label, "t1 first impression should have correct label")
54+
assert.Equal(t, "b1", imps[0].KeyImpressions[0].BucketingKey, "t1 first impression should have correct bucketing key")
55+
assert.Equal(t, int64(1), imps[0].KeyImpressions[0].Pt, "t1 first impression should have correct pt")
56+
57+
// Verify second impression of t1
58+
assert.Equal(t, "k2", imps[0].KeyImpressions[1].KeyName, "t1 second impression should have correct key name")
59+
assert.Equal(t, "on", imps[0].KeyImpressions[1].Treatment, "t1 second impression should have correct treatment")
60+
assert.Equal(t, int64(1), imps[0].KeyImpressions[1].Time, "t1 second impression should have correct time")
61+
assert.Equal(t, int64(2), imps[0].KeyImpressions[1].ChangeNumber, "t1 second impression should have correct change number")
62+
assert.Equal(t, "l1", imps[0].KeyImpressions[1].Label, "t1 second impression should have correct label")
63+
assert.Equal(t, "b1", imps[0].KeyImpressions[1].BucketingKey, "t1 second impression should have correct bucketing key")
64+
assert.Equal(t, int64(1), imps[0].KeyImpressions[1].Pt, "t1 second impression should have correct pt")
65+
66+
// Verify second impression group (t2)
67+
assert.Equal(t, "t2", imps[1].TestName, "Second group should be t2")
68+
assert.Equal(t, 2, len(imps[1].KeyImpressions), "t2 should have 2 impressions")
69+
70+
// Verify first impression of t2
71+
assert.Equal(t, "k1", imps[1].KeyImpressions[0].KeyName, "t2 first impression should have correct key name")
72+
assert.Equal(t, "off", imps[1].KeyImpressions[0].Treatment, "t2 first impression should have correct treatment")
73+
assert.Equal(t, int64(2), imps[1].KeyImpressions[0].Time, "t2 first impression should have correct time")
74+
assert.Equal(t, int64(3), imps[1].KeyImpressions[0].ChangeNumber, "t2 first impression should have correct change number")
75+
assert.Equal(t, "l2", imps[1].KeyImpressions[0].Label, "t2 first impression should have correct label")
76+
assert.Equal(t, "b2", imps[1].KeyImpressions[0].BucketingKey, "t2 first impression should have correct bucketing key")
77+
assert.Equal(t, int64(2), imps[1].KeyImpressions[0].Pt, "t2 first impression should have correct pt")
78+
79+
// Verify second impression of t2
80+
assert.Equal(t, "k2", imps[1].KeyImpressions[1].KeyName, "t2 second impression should have correct key name")
81+
assert.Equal(t, "off", imps[1].KeyImpressions[1].Treatment, "t2 second impression should have correct treatment")
82+
assert.Equal(t, int64(2), imps[1].KeyImpressions[1].Time, "t2 second impression should have correct time")
83+
assert.Equal(t, int64(3), imps[1].KeyImpressions[1].ChangeNumber, "t2 second impression should have correct change number")
84+
assert.Equal(t, "l2", imps[1].KeyImpressions[1].Label, "t2 second impression should have correct label")
85+
assert.Equal(t, "b2", imps[1].KeyImpressions[1].BucketingKey, "t2 second impression should have correct bucketing key")
86+
assert.Equal(t, int64(3), imps[1].KeyImpressions[1].Pt, "t2 second impression should have correct pt")
87+
}))
88+
defer ts.Close()
89+
90+
listener, err := NewImpressionBulkListener(ts.URL, 10, nil)
91+
assert.False(t, err != nil, "error cannot be nil: %v", err)
92+
93+
err = listener.Start()
94+
assert.False(t, err != nil, "start() should not fail. Got: %v", err)
95+
defer listener.Stop(true)
96+
97+
listener.Submit([]ImpressionsForListener{
98+
ImpressionsForListener{
99+
TestName: "t1",
100+
KeyImpressions: []ImpressionForListener{
101+
ImpressionForListener{
102+
KeyName: "k1",
103+
Treatment: "on",
104+
Time: 1,
105+
ChangeNumber: 2,
106+
Label: "l1",
107+
BucketingKey: "b1",
108+
Pt: 1,
109+
},
110+
ImpressionForListener{
111+
KeyName: "k2",
112+
Treatment: "on",
113+
Time: 1,
114+
ChangeNumber: 2,
115+
Label: "l1",
116+
BucketingKey: "b1",
117+
Pt: 1,
118+
},
119+
},
120+
},
121+
ImpressionsForListener{
122+
TestName: "t2",
123+
KeyImpressions: []ImpressionForListener{
124+
ImpressionForListener{
125+
KeyName: "k1",
126+
Treatment: "off",
127+
Time: 2,
128+
ChangeNumber: 3,
129+
Label: "l2",
130+
BucketingKey: "b2",
131+
Pt: 2,
132+
},
133+
ImpressionForListener{
134+
KeyName: "k2",
135+
Treatment: "off",
136+
Time: 2,
137+
ChangeNumber: 3,
138+
Label: "l2",
139+
BucketingKey: "b2",
140+
Pt: 3,
141+
},
142+
},
143+
},
144+
}, &dtos.Metadata{SDKVersion: "go-1.1.1", MachineIP: "1.2.3.4", MachineName: "ip-1-2-3-4"})
145+
146+
<-reqsDone
147+
}
148+
149+
func TestImpressionListenerWithProperties(t *testing.T) {
45150

46-
if imps[0].TestName != "t1" || len(imps[0].KeyImpressions) != 2 {
47-
t.Errorf("invalid ipmressions for t1")
151+
reqsDone := make(chan struct{}, 1)
152+
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
153+
defer func() { reqsDone <- struct{}{} }()
154+
// Verify request method and path
155+
assert.False(t, r.URL.Path != "/someUrl" && r.Method != "POST", "Invalid request. Should be POST to /someUrl")
156+
157+
// Read and parse request body
158+
body, err := ioutil.ReadAll(r.Body)
159+
r.Body.Close()
160+
assert.False(t, err != nil, "Error reading body")
161+
if err != nil {
48162
return
49163
}
50164

51-
if imps[1].TestName != "t2" || len(imps[1].KeyImpressions) != 2 {
52-
t.Errorf("invalid ipmressions for t2")
165+
var all impressionListenerPostBody
166+
err = json.Unmarshal(body, &all)
167+
assert.False(t, err != nil, "Error parsing json: %v", err)
168+
if err != nil {
53169
return
54170
}
171+
172+
// Verify metadata
173+
assert.False(t, all.SdkVersion != "go-1.1.1" || all.MachineIP != "1.2.3.4" || all.MachineName != "ip-1-2-3-4", "invalid metadata")
174+
175+
// Verify impressions
176+
imps := all.Impressions
177+
assert.Equal(t, 2, len(imps), "Should have 2 impression groups")
178+
179+
// Verify first impression group (t1)
180+
assert.Equal(t, "t1", imps[0].TestName, "First group should be t1")
181+
assert.Equal(t, 2, len(imps[0].KeyImpressions), "t1 should have 2 impressions")
182+
183+
// Verify first impression of t1
184+
assert.Equal(t, "k1", imps[0].KeyImpressions[0].KeyName, "t1 first impression should have correct key name")
185+
assert.Equal(t, "on", imps[0].KeyImpressions[0].Treatment, "t1 first impression should have correct treatment")
186+
assert.Equal(t, int64(1), imps[0].KeyImpressions[0].Time, "t1 first impression should have correct time")
187+
assert.Equal(t, int64(2), imps[0].KeyImpressions[0].ChangeNumber, "t1 first impression should have correct change number")
188+
assert.Equal(t, "l1", imps[0].KeyImpressions[0].Label, "t1 first impression should have correct label")
189+
assert.Equal(t, "b1", imps[0].KeyImpressions[0].BucketingKey, "t1 first impression should have correct bucketing key")
190+
assert.Equal(t, int64(1), imps[0].KeyImpressions[0].Pt, "t1 first impression should have correct pt")
191+
assert.Equal(t, "{'prop':'val'}", imps[0].KeyImpressions[0].Properties, "First impression of t1 should have properties")
192+
193+
// Verify second impression of t1
194+
assert.Equal(t, "k2", imps[0].KeyImpressions[1].KeyName, "t1 second impression should have correct key name")
195+
assert.Equal(t, "on", imps[0].KeyImpressions[1].Treatment, "t1 second impression should have correct treatment")
196+
assert.Equal(t, int64(1), imps[0].KeyImpressions[1].Time, "t1 second impression should have correct time")
197+
assert.Equal(t, int64(2), imps[0].KeyImpressions[1].ChangeNumber, "t1 second impression should have correct change number")
198+
assert.Equal(t, "l1", imps[0].KeyImpressions[1].Label, "t1 second impression should have correct label")
199+
assert.Equal(t, "b1", imps[0].KeyImpressions[1].BucketingKey, "t1 second impression should have correct bucketing key")
200+
assert.Equal(t, int64(1), imps[0].KeyImpressions[1].Pt, "t1 second impression should have correct pt")
201+
// Second impression should not have properties
202+
assert.Empty(t, imps[0].KeyImpressions[1].Properties, "Second impression of t1 should not have properties")
203+
204+
// Verify second impression group (t2)
205+
assert.Equal(t, "t2", imps[1].TestName, "Second group should be t2")
206+
assert.Equal(t, 2, len(imps[1].KeyImpressions), "t2 should have 2 impressions")
207+
208+
// Verify first impression of t2
209+
assert.Equal(t, "k1", imps[1].KeyImpressions[0].KeyName, "t2 first impression should have correct key name")
210+
assert.Equal(t, "off", imps[1].KeyImpressions[0].Treatment, "t2 first impression should have correct treatment")
211+
assert.Equal(t, int64(2), imps[1].KeyImpressions[0].Time, "t2 first impression should have correct time")
212+
assert.Equal(t, int64(3), imps[1].KeyImpressions[0].ChangeNumber, "t2 first impression should have correct change number")
213+
assert.Equal(t, "l2", imps[1].KeyImpressions[0].Label, "t2 first impression should have correct label")
214+
assert.Equal(t, "b2", imps[1].KeyImpressions[0].BucketingKey, "t2 first impression should have correct bucketing key")
215+
assert.Equal(t, int64(2), imps[1].KeyImpressions[0].Pt, "t2 first impression should have correct pt")
216+
217+
// Verify second impression of t2
218+
assert.Equal(t, "k2", imps[1].KeyImpressions[1].KeyName, "t2 second impression should have correct key name")
219+
assert.Equal(t, "off", imps[1].KeyImpressions[1].Treatment, "t2 second impression should have correct treatment")
220+
assert.Equal(t, int64(2), imps[1].KeyImpressions[1].Time, "t2 second impression should have correct time")
221+
assert.Equal(t, int64(3), imps[1].KeyImpressions[1].ChangeNumber, "t2 second impression should have correct change number")
222+
assert.Equal(t, "l2", imps[1].KeyImpressions[1].Label, "t2 second impression should have correct label")
223+
assert.Equal(t, "b2", imps[1].KeyImpressions[1].BucketingKey, "t2 second impression should have correct bucketing key")
224+
assert.Equal(t, int64(3), imps[1].KeyImpressions[1].Pt, "t2 second impression should have correct pt")
55225
}))
56226
defer ts.Close()
57227

58228
listener, err := NewImpressionBulkListener(ts.URL, 10, nil)
59-
if err != nil {
60-
t.Error("error cannot be nil: ", err)
61-
}
229+
assert.False(t, err != nil, "error cannot be nil: %v", err)
62230

63-
if err = listener.Start(); err != nil {
64-
t.Error("start() should not fail. Got: ", err)
65-
}
231+
err = listener.Start()
232+
assert.False(t, err != nil, "start() should not fail. Got: %v", err)
66233
defer listener.Stop(true)
67234

68235
listener.Submit([]ImpressionsForListener{
@@ -77,6 +244,7 @@ func TestImpressionListener(t *testing.T) {
77244
Label: "l1",
78245
BucketingKey: "b1",
79246
Pt: 1,
247+
Properties: "{'prop':'val'}",
80248
},
81249
ImpressionForListener{
82250
KeyName: "k2",

splitio/common/impressionlistener/mocks/listener.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package mocks
22

33
import (
44
"github.com/splitio/split-synchronizer/v5/splitio/common/impressionlistener"
5+
"github.com/stretchr/testify/mock"
56

67
"github.com/splitio/go-split-commons/v9/dtos"
78
)
@@ -23,3 +24,22 @@ func (l *ImpressionBulkListenerMock) Start() error {
2324
func (l *ImpressionBulkListenerMock) Stop(blocking bool) error {
2425
return l.StopCall(blocking)
2526
}
27+
28+
type MockImpressionBulkListener struct {
29+
mock.Mock
30+
}
31+
32+
func (l *MockImpressionBulkListener) Submit(imps []impressionlistener.ImpressionsForListener, metadata *dtos.Metadata) error {
33+
args := l.Called(imps, metadata)
34+
return args.Error(1)
35+
}
36+
37+
func (l *MockImpressionBulkListener) Start() error {
38+
args := l.Called()
39+
return args.Error(1)
40+
}
41+
42+
func (l *MockImpressionBulkListener) Stop(blocking bool) error {
43+
args := l.Called()
44+
return args.Error(1)
45+
}

splitio/producer/task/impressions.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ func (i *ImpressionsPipelineWorker) sendImpressionsToListener(b *impBatches) {
165165
Label: ki.Label,
166166
BucketingKey: ki.BucketingKey,
167167
Pt: ki.Pt,
168+
Properties: ki.Properties,
168169
})
169170
}
170171
payload = append(payload, forTest)
@@ -268,6 +269,7 @@ func (s *impsWithMetadata) add(i *dtos.Impression) {
268269
Label: i.Label,
269270
BucketingKey: i.BucketingKey,
270271
Pt: i.Pt,
272+
Properties: i.Properties,
271273
})
272274
s.count++
273275
}

0 commit comments

Comments
 (0)