1
+ package userstatistics ;
2
+
3
+ import models .FlightData ;
4
+ import models .TestHelpers ;
5
+ import models .UserStatistics ;
6
+ import org .apache .flink .api .common .eventtime .WatermarkStrategy ;
7
+ import org .apache .flink .runtime .testutils .MiniClusterResourceConfiguration ;
8
+ import org .apache .flink .streaming .api .datastream .DataStream ;
9
+ import org .apache .flink .streaming .api .environment .StreamExecutionEnvironment ;
10
+ import org .apache .flink .test .junit5 .MiniClusterExtension ;
11
+ import org .junit .jupiter .api .BeforeEach ;
12
+ import org .junit .jupiter .api .Test ;
13
+ import org .junit .jupiter .api .extension .RegisterExtension ;
14
+
15
+ import java .time .Duration ;
16
+ import java .util .ArrayList ;
17
+ import java .util .Arrays ;
18
+ import java .util .List ;
19
+
20
+ import static org .junit .jupiter .api .Assertions .*;
21
+
22
+ class UserStatisticsJobTest {
23
+
24
+ StreamExecutionEnvironment env ;
25
+ WatermarkStrategy <FlightData > defaultWatermarkStrategy ;
26
+
27
+ DataStream .Collector <UserStatistics > collector ;
28
+
29
+ static final MiniClusterResourceConfiguration miniClusterConfig = new MiniClusterResourceConfiguration .Builder ()
30
+ .setNumberSlotsPerTaskManager (2 )
31
+ .setNumberTaskManagers (1 )
32
+ .build ();
33
+
34
+ @ RegisterExtension
35
+ static final MiniClusterExtension FLINK = new MiniClusterExtension (miniClusterConfig );
36
+
37
+ private void assertContains (DataStream .Collector <UserStatistics > collector , List <UserStatistics > expected ) {
38
+ List <UserStatistics > actual = new ArrayList <>();
39
+ collector .getOutput ().forEachRemaining (actual ::add );
40
+
41
+ assertEquals (expected .size (), actual .size ());
42
+
43
+ assertTrue (actual .containsAll (expected ));
44
+ }
45
+
46
+ @ BeforeEach
47
+ public void setup () {
48
+ env = StreamExecutionEnvironment .getExecutionEnvironment ();
49
+ defaultWatermarkStrategy = WatermarkStrategy
50
+ .<FlightData >forMonotonousTimestamps ()
51
+ .withTimestampAssigner ((event , timestamp ) -> System .currentTimeMillis ());
52
+
53
+ collector = new DataStream .Collector <>();
54
+ }
55
+
56
+ @ Test
57
+ public void defineWorkflow_shouldConvertFlightDataToUserStatistics () throws Exception {
58
+ FlightData flight = new TestHelpers .FlightDataBuilder ().build ();
59
+
60
+ DataStream <FlightData > stream = env
61
+ .fromElements (flight )
62
+ .assignTimestampsAndWatermarks (defaultWatermarkStrategy );
63
+
64
+ UserStatisticsJob
65
+ .defineWorkflow (stream )
66
+ .collectAsync (collector );
67
+
68
+ env .executeAsync ();
69
+
70
+ UserStatistics expected = new UserStatistics (flight );
71
+
72
+ assertContains (collector , Arrays .asList (expected ));
73
+ }
74
+
75
+ @ Test
76
+ public void defineWorkflow_shouldGroupStatisticsByEmailAddress () throws Exception {
77
+ String email1 = TestHelpers .generateEmail ();
78
+ String email2 = TestHelpers .generateEmail ();
79
+
80
+ FlightData flight1 = new TestHelpers .FlightDataBuilder ().setEmailAddress (email1 ).build ();
81
+ FlightData flight2 = new TestHelpers .FlightDataBuilder ().setEmailAddress (email2 ).build ();
82
+ FlightData flight3 = new TestHelpers .FlightDataBuilder ().setEmailAddress (email1 ).build ();
83
+
84
+ DataStream <FlightData > stream = env
85
+ .fromElements (flight1 , flight2 , flight3 )
86
+ .assignTimestampsAndWatermarks (defaultWatermarkStrategy );
87
+
88
+ UserStatisticsJob
89
+ .defineWorkflow (stream )
90
+ .collectAsync (collector );
91
+
92
+ env .executeAsync ();
93
+
94
+ UserStatistics expected1 = new UserStatistics (flight1 ).merge (new UserStatistics (flight3 ));
95
+ UserStatistics expected2 = new UserStatistics (flight2 );
96
+
97
+ assertContains (collector , Arrays .asList (expected1 , expected2 ));
98
+ }
99
+
100
+ @ Test
101
+ public void defineWorkflow_shouldWindowStatisticsByMinute () throws Exception {
102
+ String email = TestHelpers .generateEmail ();
103
+ FlightData flight1 = new TestHelpers .FlightDataBuilder ().setEmailAddress (email ).build ();
104
+ FlightData flight2 = new TestHelpers .FlightDataBuilder ().setEmailAddress (email ).build ();
105
+ FlightData flight3 = new TestHelpers .FlightDataBuilder ().setEmailAddress (email ).setDepartureAirportCode ("LATE" ).build ();
106
+
107
+ WatermarkStrategy <FlightData > watermarkStrategy = WatermarkStrategy
108
+ .<FlightData >forMonotonousTimestamps ()
109
+ .withTimestampAssigner ((event , timestamp ) -> {
110
+ if (event .getDepartureAirportCode ().equals ("LATE" )) {
111
+ return System .currentTimeMillis () + Duration .ofMinutes (1 ).toMillis ();
112
+ } else {
113
+ return System .currentTimeMillis ();
114
+ }
115
+ });
116
+
117
+ DataStream <FlightData > stream = env
118
+ .fromElements (flight1 , flight2 , flight3 )
119
+ .assignTimestampsAndWatermarks (watermarkStrategy );
120
+
121
+ UserStatisticsJob
122
+ .defineWorkflow (stream )
123
+ .collectAsync (collector );
124
+
125
+ env .executeAsync ();
126
+
127
+ UserStatistics expected1 = new UserStatistics (flight1 ).merge (new UserStatistics (flight2 ));
128
+ UserStatistics expected2 = expected1 .merge (new UserStatistics (flight3 ));
129
+
130
+ assertContains (collector , Arrays .asList (expected1 , expected2 ));
131
+ }
132
+ }
0 commit comments