embulk-input-marketo-extended 0.6.18

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +7 -0
  2. data/.github/PULL_REQUEST_TEMPLATE.md +37 -0
  3. data/.gitignore +14 -0
  4. data/.travis.yml +6 -0
  5. data/CHANGELOG.md +170 -0
  6. data/LICENSE.txt +21 -0
  7. data/README.md +213 -0
  8. data/build.gradle +103 -0
  9. data/config/checkstyle/checkstyle.xml +128 -0
  10. data/config/checkstyle/default.xml +108 -0
  11. data/gradle/wrapper/gradle-wrapper.jar +0 -0
  12. data/gradle/wrapper/gradle-wrapper.properties +6 -0
  13. data/gradlew +169 -0
  14. data/gradlew.bat +84 -0
  15. data/lib/embulk/input/marketo.rb +3 -0
  16. data/settings.gradle +1 -0
  17. data/src/main/java/org/embulk/input/marketo/CsvTokenizer.java +700 -0
  18. data/src/main/java/org/embulk/input/marketo/MarketoInputPlugin.java +15 -0
  19. data/src/main/java/org/embulk/input/marketo/MarketoInputPluginDelegate.java +100 -0
  20. data/src/main/java/org/embulk/input/marketo/MarketoService.java +38 -0
  21. data/src/main/java/org/embulk/input/marketo/MarketoServiceImpl.java +245 -0
  22. data/src/main/java/org/embulk/input/marketo/MarketoUtils.java +212 -0
  23. data/src/main/java/org/embulk/input/marketo/delegate/ActivityBulkExtractInputPlugin.java +167 -0
  24. data/src/main/java/org/embulk/input/marketo/delegate/CampaignInputPlugin.java +48 -0
  25. data/src/main/java/org/embulk/input/marketo/delegate/CustomObjectInputPlugin.java +75 -0
  26. data/src/main/java/org/embulk/input/marketo/delegate/CustomObjectResponseMapperBuilder.java +81 -0
  27. data/src/main/java/org/embulk/input/marketo/delegate/LeadBulkExtractInputPlugin.java +66 -0
  28. data/src/main/java/org/embulk/input/marketo/delegate/LeadServiceResponseMapperBuilder.java +85 -0
  29. data/src/main/java/org/embulk/input/marketo/delegate/LeadWithListInputPlugin.java +64 -0
  30. data/src/main/java/org/embulk/input/marketo/delegate/LeadWithProgramInputPlugin.java +60 -0
  31. data/src/main/java/org/embulk/input/marketo/delegate/MarketoBaseBulkExtractInputPlugin.java +441 -0
  32. data/src/main/java/org/embulk/input/marketo/delegate/MarketoBaseInputPluginDelegate.java +92 -0
  33. data/src/main/java/org/embulk/input/marketo/delegate/ProgramInputPlugin.java +228 -0
  34. data/src/main/java/org/embulk/input/marketo/exception/MarketoAPIException.java +30 -0
  35. data/src/main/java/org/embulk/input/marketo/model/BulkExtractRangeHeader.java +26 -0
  36. data/src/main/java/org/embulk/input/marketo/model/MarketoAccessTokenResponse.java +92 -0
  37. data/src/main/java/org/embulk/input/marketo/model/MarketoBulkExtractRequest.java +68 -0
  38. data/src/main/java/org/embulk/input/marketo/model/MarketoError.java +40 -0
  39. data/src/main/java/org/embulk/input/marketo/model/MarketoField.java +126 -0
  40. data/src/main/java/org/embulk/input/marketo/model/MarketoResponse.java +82 -0
  41. data/src/main/java/org/embulk/input/marketo/model/filter/DateRangeFilter.java +40 -0
  42. data/src/main/java/org/embulk/input/marketo/rest/MarketoBaseRestClient.java +306 -0
  43. data/src/main/java/org/embulk/input/marketo/rest/MarketoInputStreamResponseEntityReader.java +69 -0
  44. data/src/main/java/org/embulk/input/marketo/rest/MarketoRESTEndpoint.java +47 -0
  45. data/src/main/java/org/embulk/input/marketo/rest/MarketoResponseJetty92EntityReader.java +89 -0
  46. data/src/main/java/org/embulk/input/marketo/rest/MarketoRestClient.java +569 -0
  47. data/src/main/java/org/embulk/input/marketo/rest/RecordPagingIterable.java +180 -0
  48. data/src/test/java/org/embulk/input/marketo/MarketoServiceImplTest.java +140 -0
  49. data/src/test/java/org/embulk/input/marketo/MarketoUtilsTest.java +87 -0
  50. data/src/test/java/org/embulk/input/marketo/delegate/ActivityBulkExtractInputPluginTest.java +128 -0
  51. data/src/test/java/org/embulk/input/marketo/delegate/CampaignInputPluginTest.java +73 -0
  52. data/src/test/java/org/embulk/input/marketo/delegate/CustomObjectInputPluginTest.java +102 -0
  53. data/src/test/java/org/embulk/input/marketo/delegate/LeadBulkExtractInputPluginTest.java +99 -0
  54. data/src/test/java/org/embulk/input/marketo/delegate/LeadServiceResponseMapperBuilderTest.java +119 -0
  55. data/src/test/java/org/embulk/input/marketo/delegate/LeadWithListInputPluginTest.java +101 -0
  56. data/src/test/java/org/embulk/input/marketo/delegate/LeadWithProgramInputPluginTest.java +103 -0
  57. data/src/test/java/org/embulk/input/marketo/delegate/MarketoBaseBulkExtractInputPluginTest.java +169 -0
  58. data/src/test/java/org/embulk/input/marketo/delegate/ProgramInputPluginTest.java +343 -0
  59. data/src/test/java/org/embulk/input/marketo/rest/MarketoBaseRestClientTest.java +368 -0
  60. data/src/test/java/org/embulk/input/marketo/rest/MarketoRestClientTest.java +584 -0
  61. data/src/test/resources/config/activity_bulk_extract_config.yaml +7 -0
  62. data/src/test/resources/config/custom_object_config.yaml +8 -0
  63. data/src/test/resources/config/lead_bulk_extract_config.yaml +8 -0
  64. data/src/test/resources/config/rest_config.yaml +3 -0
  65. data/src/test/resources/fixtures/activity_extract1.csv +35 -0
  66. data/src/test/resources/fixtures/activity_extract2.csv +22 -0
  67. data/src/test/resources/fixtures/activity_types.json +22 -0
  68. data/src/test/resources/fixtures/all_program_full.json +53 -0
  69. data/src/test/resources/fixtures/campaign_response.json +38 -0
  70. data/src/test/resources/fixtures/campaign_response_full.json +102 -0
  71. data/src/test/resources/fixtures/custom_object_describe.json +124 -0
  72. data/src/test/resources/fixtures/custom_object_describe_marketo_fields_full.json +22 -0
  73. data/src/test/resources/fixtures/custom_object_expected.json +66 -0
  74. data/src/test/resources/fixtures/custom_object_response.json +24 -0
  75. data/src/test/resources/fixtures/custom_object_response_full.json +23 -0
  76. data/src/test/resources/fixtures/lead_by_list.json +33 -0
  77. data/src/test/resources/fixtures/lead_by_program_response.json +47 -0
  78. data/src/test/resources/fixtures/lead_describe.json +221 -0
  79. data/src/test/resources/fixtures/lead_describe_expected.json +66 -0
  80. data/src/test/resources/fixtures/lead_describe_marketo_fields_full.json +518 -0
  81. data/src/test/resources/fixtures/lead_extract1.csv +11 -0
  82. data/src/test/resources/fixtures/lead_response_full.json +2402 -0
  83. data/src/test/resources/fixtures/lead_with_program_full.json +17 -0
  84. data/src/test/resources/fixtures/leads_extract2.csv +10 -0
  85. data/src/test/resources/fixtures/list_reponse_full.json +191 -0
  86. data/src/test/resources/fixtures/lists_response.json +31 -0
  87. data/src/test/resources/fixtures/program_response.json +71 -0
  88. metadata +171 -0
@@ -0,0 +1,180 @@
1
+ package org.embulk.input.marketo.rest;
2
+
3
+ import java.util.Iterator;
4
+ import java.util.List;
5
+ import java.util.NoSuchElementException;
6
+
7
+ /**
8
+ * Record Iterable class that will go through Marketo Paging
9
+ * Warning this iterator implementation do not cached page due to reduce memory usage. So iterate through a
10
+ * RecordIterate multiple time is not recommended since it will sent query to Marketo on every call.
11
+ * Created by tai.khuu on 9/5/17.
12
+ */
13
+ public class RecordPagingIterable<T> implements Iterable<T>
14
+ {
15
+ private PagingFunction<Page<T>> pagingFunction;
16
+
17
+ public RecordPagingIterable(PagingFunction pagingFunction)
18
+ {
19
+ this.pagingFunction = pagingFunction;
20
+ }
21
+
22
+ @Override
23
+ public Iterator<T> iterator()
24
+ {
25
+ return this.new RecordIterator();
26
+ }
27
+
28
+ private class RecordIterator implements Iterator<T>
29
+ {
30
+ Page<T> currentPage;
31
+ private Iterator<T> currentIterator;
32
+
33
+ public RecordIterator()
34
+ {
35
+ }
36
+
37
+ @Override
38
+ public boolean hasNext()
39
+ {
40
+ if (currentPage == null) {
41
+ currentPage = pagingFunction.getFirstPage();
42
+ this.currentIterator = currentPage.getRecordsIter();
43
+ }
44
+ if (currentIterator.hasNext()) {
45
+ return true;
46
+ }
47
+ if (!currentPage.hasNext) {
48
+ return false;
49
+ }
50
+ Page<T> nextPage = pagingFunction.getNextPage(currentPage);
51
+ currentIterator = nextPage.getRecordsIter();
52
+ currentPage = nextPage;
53
+ return currentIterator.hasNext();
54
+ }
55
+
56
+ @Override
57
+ public T next()
58
+ {
59
+ if (!hasNext()) {
60
+ throw new NoSuchElementException("Call next on an empty iterator");
61
+ }
62
+ return currentIterator.next();
63
+ }
64
+
65
+ @Override
66
+ public void remove()
67
+ {
68
+ throw new UnsupportedOperationException("RecordIterator not support remove");
69
+ }
70
+ }
71
+
72
+ public interface PagingFunction<P extends Page>
73
+ {
74
+ P getNextPage(P currentPage);
75
+ /**
76
+ * All implementation must make sure calling get first page multiple time should always return.
77
+ * @return P
78
+ */
79
+ P getFirstPage();
80
+ }
81
+
82
+ public static class Page<T>
83
+ {
84
+ private Iterable<T> records;
85
+
86
+ private boolean hasNext;
87
+
88
+ public Page(Iterable<T> records, boolean hasNext)
89
+ {
90
+ this.records = records;
91
+ this.hasNext = hasNext;
92
+ }
93
+
94
+ public Iterable<T> getRecords()
95
+ {
96
+ return records;
97
+ }
98
+ public Iterator<T> getRecordsIter()
99
+ {
100
+ return records.iterator();
101
+ }
102
+ public void setRecords(List<T> records)
103
+ {
104
+ this.records = records;
105
+ }
106
+
107
+ public boolean isHasNext()
108
+ {
109
+ return hasNext;
110
+ }
111
+
112
+ public void setHasNext(boolean hasNext)
113
+ {
114
+ this.hasNext = hasNext;
115
+ }
116
+ }
117
+
118
+ public static class TokenPage<T> extends Page<T>
119
+ {
120
+ private String nextPageToken;
121
+
122
+ public TokenPage(Iterable<T> records, String nextPageToken, boolean moreResult)
123
+ {
124
+ super(records, moreResult);
125
+ this.nextPageToken = nextPageToken;
126
+ }
127
+
128
+ public String getNextPageToken()
129
+ {
130
+ return nextPageToken;
131
+ }
132
+
133
+ public void setNextPageToken(String nextPageToken)
134
+ {
135
+ this.nextPageToken = nextPageToken;
136
+ }
137
+ }
138
+
139
+ public static class OffsetPage<T> extends Page<T>
140
+ {
141
+ private int nextOffSet;
142
+
143
+ public OffsetPage(Iterable<T> records, int nextOffSet, boolean moreResult)
144
+ {
145
+ super(records, moreResult);
146
+ this.nextOffSet = nextOffSet;
147
+ }
148
+
149
+ public int getNextOffSet()
150
+ {
151
+ return nextOffSet;
152
+ }
153
+ }
154
+ public static class OffsetWithTokenPage<T> extends Page<T>
155
+ {
156
+ private int nextOffSet;
157
+ private String nextPageToken;
158
+ public OffsetWithTokenPage(Iterable<T> records, int nextOffSet, String nextPageToken, boolean moreResult)
159
+ {
160
+ super(records, moreResult);
161
+ this.nextOffSet = nextOffSet;
162
+ this.nextPageToken = nextPageToken;
163
+ }
164
+
165
+ public int getNextOffSet()
166
+ {
167
+ return nextOffSet;
168
+ }
169
+
170
+ public String getNextPageToken()
171
+ {
172
+ return nextPageToken;
173
+ }
174
+
175
+ public void setNextPageToken(String nextPageToken)
176
+ {
177
+ this.nextPageToken = nextPageToken;
178
+ }
179
+ }
180
+ }
@@ -0,0 +1,140 @@
1
+ package org.embulk.input.marketo;
2
+
3
+ import com.fasterxml.jackson.databind.ObjectMapper;
4
+ import com.fasterxml.jackson.databind.node.ObjectNode;
5
+ import com.google.common.io.ByteStreams;
6
+ import org.embulk.EmbulkTestRuntime;
7
+ import org.embulk.input.marketo.model.BulkExtractRangeHeader;
8
+ import org.embulk.input.marketo.rest.MarketoRestClient;
9
+ import org.embulk.input.marketo.rest.RecordPagingIterable;
10
+ import org.junit.Assert;
11
+ import org.junit.Before;
12
+ import org.junit.Rule;
13
+ import org.junit.Test;
14
+ import org.mockito.Mockito;
15
+
16
+ import java.io.ByteArrayInputStream;
17
+ import java.io.File;
18
+ import java.io.FileInputStream;
19
+ import java.util.ArrayList;
20
+ import java.util.Arrays;
21
+ import java.util.Date;
22
+ import java.util.Iterator;
23
+ import java.util.List;
24
+
25
+ import static org.mockito.ArgumentMatchers.any;
26
+
27
+ /**
28
+ * Created by tai.khuu on 10/9/17.
29
+ */
30
+ public class MarketoServiceImplTest
31
+ {
32
+ private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
33
+ @Rule
34
+ public EmbulkTestRuntime embulkTestRuntime = new EmbulkTestRuntime();
35
+ private MarketoService marketoService;
36
+
37
+ private MarketoRestClient mockMarketoRestClient;
38
+ @Before
39
+ public void prepare()
40
+ {
41
+ mockMarketoRestClient = Mockito.mock(MarketoRestClient.class);
42
+ marketoService = new MarketoServiceImpl(mockMarketoRestClient);
43
+ }
44
+
45
+ @Test
46
+ public void extractLead() throws Exception
47
+ {
48
+ Date startDate = new Date(1507223374000L);
49
+ Date endDate = new Date(1507655374000L);
50
+ List<String> extractedFields = Arrays.asList("field1", "fActivityBulkExtractInputPluginTest.java:78ield2");
51
+ String filerField = "field1";
52
+ String exportId = "exportId";
53
+ Mockito.when(mockMarketoRestClient.createLeadBulkExtract(Mockito.eq(startDate), Mockito.eq(endDate), Mockito.eq(extractedFields), Mockito.eq(filerField))).thenReturn(exportId);
54
+ ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream("Test File Content".getBytes());
55
+ Mockito.when(mockMarketoRestClient.getLeadBulkExtractResult(Mockito.eq(exportId), any(BulkExtractRangeHeader.class))).thenReturn(byteArrayInputStream);
56
+ File file = marketoService.extractLead(startDate, endDate, extractedFields, filerField, 1, 3);
57
+ Assert.assertEquals("Test File Content", new String(ByteStreams.toByteArray(new FileInputStream(file))));
58
+ Mockito.verify(mockMarketoRestClient, Mockito.times(1)).startLeadBulkExtract(Mockito.eq(exportId));
59
+ Mockito.verify(mockMarketoRestClient, Mockito.times(1)).waitLeadExportJobComplete(Mockito.eq(exportId), Mockito.eq(1), Mockito.eq(3));
60
+ }
61
+
62
+ @Test
63
+ public void extractAllActivity() throws Exception
64
+ {
65
+ Date startDate = new Date(1507223374000L);
66
+ Date endDate = new Date(1507655374000L);
67
+ List<Integer> activityTypeIds = new ArrayList<>();
68
+ String exportId = "exportId";
69
+ Mockito.when(mockMarketoRestClient.createActivityExtract(any(List.class), Mockito.eq(startDate), Mockito.eq(endDate))).thenReturn(exportId);
70
+ ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream("Test File Content".getBytes());
71
+ Mockito.when(mockMarketoRestClient.getActivitiesBulkExtractResult(Mockito.eq(exportId), any(BulkExtractRangeHeader.class))).thenReturn(byteArrayInputStream);
72
+ File file = marketoService.extractAllActivity(activityTypeIds, startDate, endDate, 1, 3);
73
+ Assert.assertEquals("Test File Content", new String(ByteStreams.toByteArray(new FileInputStream(file))));
74
+ Mockito.verify(mockMarketoRestClient, Mockito.times(1)).startActitvityBulkExtract(Mockito.eq(exportId));
75
+ Mockito.verify(mockMarketoRestClient, Mockito.times(1)).waitActitvityExportJobComplete(Mockito.eq(exportId), Mockito.eq(1), Mockito.eq(3));
76
+ }
77
+
78
+ @Test
79
+ public void getAllListLead() throws Exception
80
+ {
81
+ List<String> extractFields = Arrays.asList("field1", "field2");
82
+ RecordPagingIterable<ObjectNode> listObjectNodes = Mockito.mock(RecordPagingIterable.class);
83
+ Iterator listIterator = Mockito.mock(Iterator.class);
84
+ Mockito.when(listIterator.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false);
85
+ Mockito.when(listIterator.next()).thenReturn(OBJECT_MAPPER.readTree("{\"id\":1}")).thenReturn(OBJECT_MAPPER.readTree("{\"id\":2}"));
86
+ Mockito.when(listObjectNodes.iterator()).thenReturn(listIterator);
87
+ List<ObjectNode> leadList1 = new ArrayList<>();
88
+ leadList1.add((ObjectNode) OBJECT_MAPPER.readTree("{\"id\":\"lead1\"}"));
89
+ List<ObjectNode> leadList2 = new ArrayList<>();
90
+ leadList2.add((ObjectNode) OBJECT_MAPPER.readTree("{\"id\":\"lead2\"}"));
91
+ Mockito.when(mockMarketoRestClient.getLists()).thenReturn(listObjectNodes);
92
+ RecordPagingIterable leadIterable1 = Mockito.mock(RecordPagingIterable.class);
93
+ RecordPagingIterable leadsIterable2 = Mockito.mock(RecordPagingIterable.class);
94
+ Mockito.when(leadIterable1.iterator()).thenReturn(leadList1.iterator());
95
+ Mockito.when(leadsIterable2.iterator()).thenReturn(leadList2.iterator());
96
+ Mockito.when(mockMarketoRestClient.getLeadsByList(Mockito.eq("1"), Mockito.eq("field1,field2"))).thenReturn(leadIterable1);
97
+ Mockito.when(mockMarketoRestClient.getLeadsByList(Mockito.eq("2"), Mockito.eq("field1,field2"))).thenReturn(leadsIterable2);
98
+ Iterable<ObjectNode> allListLead = marketoService.getAllListLead(extractFields);
99
+ Assert.assertEquals(leadList1.get(0), allListLead.iterator().next());
100
+ Assert.assertEquals(leadList2.get(0), allListLead.iterator().next());
101
+ }
102
+
103
+ @Test
104
+ public void getAllProgramLead() throws Exception
105
+ {
106
+ RecordPagingIterable<ObjectNode> listObjectNodes = Mockito.mock(RecordPagingIterable.class);
107
+ Iterator listIterator = Mockito.mock(Iterator.class);
108
+ Mockito.when(listIterator.hasNext()).thenReturn(true).thenReturn(true).thenReturn(false);
109
+ Mockito.when(listIterator.next()).thenReturn(OBJECT_MAPPER.readTree("{\"id\":1}")).thenReturn(OBJECT_MAPPER.readTree("{\"id\":2}"));
110
+ Mockito.when(listObjectNodes.iterator()).thenReturn(listIterator);
111
+ List<ObjectNode> leadList1 = new ArrayList<>();
112
+ leadList1.add((ObjectNode) OBJECT_MAPPER.readTree("{\"id\":\"lead1\"}"));
113
+ List<ObjectNode> leadList2 = new ArrayList<>();
114
+ leadList2.add((ObjectNode) OBJECT_MAPPER.readTree("{\"id\":\"lead2\"}"));
115
+ Mockito.when(mockMarketoRestClient.getPrograms()).thenReturn(listObjectNodes);
116
+ RecordPagingIterable leadIterable1 = Mockito.mock(RecordPagingIterable.class);
117
+ RecordPagingIterable leadsIterable2 = Mockito.mock(RecordPagingIterable.class);
118
+ Mockito.when(leadIterable1.iterator()).thenReturn(leadList1.iterator());
119
+ Mockito.when(leadsIterable2.iterator()).thenReturn(leadList2.iterator());
120
+ Mockito.when(mockMarketoRestClient.getLeadsByProgram(Mockito.eq("1"), Mockito.eq("field1,field2"))).thenReturn(leadIterable1);
121
+ Mockito.when(mockMarketoRestClient.getLeadsByProgram(Mockito.eq("2"), Mockito.eq("field1,field2"))).thenReturn(leadsIterable2);
122
+ Iterable<ObjectNode> allListLead = marketoService.getAllProgramLead(Arrays.asList("field1", "field2"));
123
+ Assert.assertEquals(leadList1.get(0), allListLead.iterator().next());
124
+ Assert.assertEquals(leadList2.get(0), allListLead.iterator().next());
125
+ }
126
+
127
+ @Test
128
+ public void getCampaign() throws Exception
129
+ {
130
+ marketoService.getCampaign();
131
+ Mockito.verify(mockMarketoRestClient, Mockito.times(1)).getCampaign();
132
+ }
133
+
134
+ @Test
135
+ public void describeLead() throws Exception
136
+ {
137
+ marketoService.describeLead();
138
+ Mockito.verify(mockMarketoRestClient, Mockito.times(1)).describeLead();
139
+ }
140
+ }
@@ -0,0 +1,87 @@
1
+ package org.embulk.input.marketo;
2
+
3
+ import org.embulk.base.restclient.ServiceResponseMapper;
4
+ import org.embulk.base.restclient.record.ValueLocator;
5
+ import org.embulk.input.marketo.model.MarketoField;
6
+ import org.embulk.spi.Column;
7
+ import org.embulk.spi.type.Types;
8
+ import org.joda.time.DateTime;
9
+ import org.junit.Test;
10
+
11
+ import java.util.ArrayList;
12
+ import java.util.List;
13
+
14
+ import static org.junit.Assert.assertEquals;
15
+ import static org.junit.Assert.assertFalse;
16
+
17
+ /**
18
+ * Created by tai.khuu on 10/7/17.
19
+ */
20
+ public class MarketoUtilsTest
21
+ {
22
+ @Test
23
+ public void buildDynamicResponseMapper() throws Exception
24
+ {
25
+ List<MarketoField> marketoFields = new ArrayList<>();
26
+ marketoFields.add(new MarketoField("marketoField1", "text"));
27
+ marketoFields.add(new MarketoField("marketoField2", "date"));
28
+ marketoFields.add(new MarketoField("marketoField3", "datetime"));
29
+ ServiceResponseMapper<? extends ValueLocator> mapper = MarketoUtils.buildDynamicResponseMapper("marketo", marketoFields);
30
+ List<Column> columns = mapper.getEmbulkSchema().getColumns();
31
+ Column column1 = columns.get(0);
32
+ assertEquals("marketo_marketoField1", column1.getName());
33
+ assertEquals(Types.STRING, column1.getType());
34
+ Column column2 = columns.get(1);
35
+ assertEquals(Types.TIMESTAMP, column2.getType());
36
+ assertEquals("marketo_marketoField2", column2.getName());
37
+ Column column3 = columns.get(2);
38
+ assertEquals("marketo_marketoField3", column3.getName());
39
+ assertEquals(Types.TIMESTAMP, column3.getType());
40
+ }
41
+
42
+ @Test
43
+ public void getFieldNameFromMarketoFields() throws Exception
44
+ {
45
+ List<MarketoField> marketoFields = new ArrayList<>();
46
+ marketoFields.add(new MarketoField("marketoField1", "text"));
47
+ marketoFields.add(new MarketoField("marketoField2", "date"));
48
+ marketoFields.add(new MarketoField("marketoField3", "datetime"));
49
+ List<String> marketoFieldList = MarketoUtils.getFieldNameFromMarketoFields(marketoFields, "marketoField2");
50
+ assertEquals(2, marketoFieldList.size());
51
+ assertFalse(marketoFieldList.contains("marketoField2"));
52
+ }
53
+
54
+ @Test
55
+ public void buildColumnName() throws Exception
56
+ {
57
+ String columnName = MarketoUtils.buildColumnName("prefix", "columnName");
58
+ assertEquals("prefix_columnName", columnName);
59
+ }
60
+
61
+ @Test
62
+ public void getIdentityEndPoint() throws Exception
63
+ {
64
+ String identityEndPoint = MarketoUtils.getIdentityEndPoint("accountId");
65
+ assertEquals("https://accountId.mktorest.com/identity", identityEndPoint);
66
+ }
67
+
68
+ @Test
69
+ public void getEndPoint() throws Exception
70
+ {
71
+ String endPoint = MarketoUtils.getEndPoint("accountId");
72
+ assertEquals("https://accountId.mktorest.com", endPoint);
73
+ }
74
+
75
+ @Test
76
+ public void sliceRange() throws Exception
77
+ {
78
+ DateTime startDate = new DateTime(1507369760000L);
79
+ List<MarketoUtils.DateRange> dateRanges1 = MarketoUtils.sliceRange(startDate, startDate.plusDays(7), 2);
80
+ assertEquals(4, dateRanges1.size());
81
+ assertEquals(startDate.plusDays(7), dateRanges1.get(3).toDate);
82
+
83
+ List<MarketoUtils.DateRange> dateRanges2 = MarketoUtils.sliceRange(startDate, startDate.plusDays(1), 2);
84
+ assertEquals(1, dateRanges2.size());
85
+ assertEquals(startDate.plusDays(1), dateRanges2.get(0).toDate);
86
+ }
87
+ }
@@ -0,0 +1,128 @@
1
+ package org.embulk.input.marketo.delegate;
2
+
3
+ import com.fasterxml.jackson.databind.JavaType;
4
+ import com.fasterxml.jackson.databind.ObjectMapper;
5
+ import com.fasterxml.jackson.databind.node.ObjectNode;
6
+ import org.embulk.EmbulkTestRuntime;
7
+ import org.embulk.base.restclient.ServiceResponseMapper;
8
+ import org.embulk.base.restclient.record.ValueLocator;
9
+ import org.embulk.config.ConfigDiff;
10
+ import org.embulk.config.ConfigException;
11
+ import org.embulk.config.ConfigLoader;
12
+ import org.embulk.config.ConfigSource;
13
+ import org.embulk.config.TaskReport;
14
+ import org.embulk.input.marketo.MarketoUtils;
15
+ import org.embulk.input.marketo.model.BulkExtractRangeHeader;
16
+ import org.embulk.input.marketo.rest.MarketoRestClient;
17
+ import org.embulk.input.marketo.rest.RecordPagingIterable;
18
+ import org.embulk.spi.Column;
19
+ import org.embulk.spi.PageBuilder;
20
+ import org.embulk.spi.Schema;
21
+ import org.joda.time.DateTime;
22
+ import org.junit.Assert;
23
+ import org.junit.Before;
24
+ import org.junit.Rule;
25
+ import org.junit.Test;
26
+ import org.junit.function.ThrowingRunnable;
27
+ import org.mockito.ArgumentCaptor;
28
+ import org.mockito.Mockito;
29
+
30
+ import java.io.IOException;
31
+ import java.text.DateFormat;
32
+ import java.text.SimpleDateFormat;
33
+ import java.util.ArrayList;
34
+ import java.util.Arrays;
35
+ import java.util.Date;
36
+ import java.util.List;
37
+
38
+ import static org.mockito.ArgumentMatchers.any;
39
+
40
+ /**
41
+ * Created by khuutantaitai on 10/3/17.
42
+ */
43
+ public class ActivityBulkExtractInputPluginTest
44
+ {
45
+ private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
46
+
47
+ @Rule
48
+ public EmbulkTestRuntime embulkTestRuntime = new EmbulkTestRuntime();
49
+
50
+ private ActivityBulkExtractInputPlugin activityBulkExtractInputPlugin;
51
+
52
+ private ConfigSource configSource;
53
+
54
+ private MarketoRestClient mockMarketoRestclient;
55
+
56
+ @Before
57
+ public void prepare() throws IOException
58
+ {
59
+ activityBulkExtractInputPlugin = Mockito.spy(new ActivityBulkExtractInputPlugin());
60
+ ConfigLoader configLoader = embulkTestRuntime.getInjector().getInstance(ConfigLoader.class);
61
+ configSource = configLoader.fromYaml(this.getClass().getResourceAsStream("/config/activity_bulk_extract_config.yaml"));
62
+ mockMarketoRestclient = Mockito.mock(MarketoRestClient.class);
63
+ Mockito.doReturn(mockMarketoRestclient).when(activityBulkExtractInputPlugin).createMarketoRestClient(any(ActivityBulkExtractInputPlugin.PluginTask.class));
64
+ }
65
+
66
+ @Test
67
+ public void testInvalidActivityTypeIds()
68
+ {
69
+ configSource.set("activity_type_ids", Arrays.asList(" ", "abc", "123"));
70
+ final ActivityBulkExtractInputPlugin.PluginTask task = configSource.loadConfig(ActivityBulkExtractInputPlugin.PluginTask.class);
71
+
72
+ Assert.assertThrows("Invalid activity type id: [ , abc]", ConfigException.class, new ThrowingRunnable()
73
+ {
74
+ @Override
75
+ public void run() throws Throwable
76
+ {
77
+ activityBulkExtractInputPlugin.validateInputTask(task);
78
+ }
79
+ });
80
+ }
81
+
82
+ @Test
83
+ public void testActivityTypeIdsValid() throws IOException
84
+ {
85
+ configSource.set("activity_type_ids", Arrays.asList("1", "2", "3 "));
86
+ final ActivityBulkExtractInputPlugin.PluginTask task = configSource.loadConfig(ActivityBulkExtractInputPlugin.PluginTask.class);
87
+
88
+ RecordPagingIterable<ObjectNode> mockRecordPagingIterable = Mockito.mock(RecordPagingIterable.class);
89
+ JavaType javaType = OBJECT_MAPPER.getTypeFactory().constructParametrizedType(List.class, List.class, ObjectNode.class);
90
+ List<ObjectNode> objectNodeList = OBJECT_MAPPER.readValue(this.getClass().getResourceAsStream("/fixtures/activity_types.json"), javaType);
91
+ Mockito.when(mockRecordPagingIterable.iterator()).thenReturn(objectNodeList.iterator());
92
+
93
+ Mockito.when(mockMarketoRestclient.getActivityTypes()).thenReturn(mockRecordPagingIterable);
94
+ activityBulkExtractInputPlugin.validateInputTask(task);
95
+ }
96
+
97
+ @Test
98
+ public void testRun() throws InterruptedException
99
+ {
100
+ ActivityBulkExtractInputPlugin.PluginTask task = configSource.loadConfig(ActivityBulkExtractInputPlugin.PluginTask.class);
101
+
102
+ DateTime startDate = new DateTime(task.getFromDate());
103
+ List<Integer> activityTypeIds = new ArrayList<>();
104
+
105
+ PageBuilder pageBuilder = Mockito.mock(PageBuilder.class);
106
+ String exportId1 = "exportId1";
107
+ String exportId2 = "exportId2";
108
+ Mockito.when(mockMarketoRestclient.createActivityExtract(any(List.class), any(Date.class), any(Date.class))).thenReturn(exportId1).thenReturn(exportId2).thenReturn(null);
109
+ Mockito.when(mockMarketoRestclient.getActivitiesBulkExtractResult(Mockito.eq(exportId1), any(BulkExtractRangeHeader.class))).thenReturn(this.getClass().getResourceAsStream("/fixtures/activity_extract1.csv"));
110
+ Mockito.when(mockMarketoRestclient.getActivitiesBulkExtractResult(Mockito.eq(exportId2), any(BulkExtractRangeHeader.class))).thenReturn(this.getClass().getResourceAsStream("/fixtures/activity_extract2.csv"));
111
+ ServiceResponseMapper<? extends ValueLocator> mapper = activityBulkExtractInputPlugin.buildServiceResponseMapper(task);
112
+ activityBulkExtractInputPlugin.validateInputTask(task);
113
+ TaskReport taskReport = activityBulkExtractInputPlugin.ingestServiceData(task, mapper.createRecordImporter(), 1, pageBuilder);
114
+ ArgumentCaptor<String> argumentCaptor = ArgumentCaptor.forClass(String.class);
115
+ Column marketoGUID = mapper.getEmbulkSchema().lookupColumn("marketoGUID");
116
+ Mockito.verify(pageBuilder, Mockito.times(55)).setString(Mockito.eq(marketoGUID), argumentCaptor.capture());
117
+ Mockito.verify(mockMarketoRestclient, Mockito.times(1)).startActitvityBulkExtract(Mockito.eq(exportId1));
118
+ Mockito.verify(mockMarketoRestclient, Mockito.times(1)).waitActitvityExportJobComplete(Mockito.eq(exportId1), Mockito.eq(task.getPollingIntervalSecond()), Mockito.eq(task.getBulkJobTimeoutSecond()));
119
+ Mockito.verify(mockMarketoRestclient, Mockito.times(1)).startActitvityBulkExtract(Mockito.eq(exportId2));
120
+ Mockito.verify(mockMarketoRestclient, Mockito.times(1)).waitActitvityExportJobComplete(Mockito.eq(exportId2), Mockito.eq(task.getPollingIntervalSecond()), Mockito.eq(task.getBulkJobTimeoutSecond()));
121
+ Mockito.verify(mockMarketoRestclient, Mockito.times(1)).createActivityExtract(activityTypeIds, startDate.toDate(), startDate.plusDays(30).toDate());
122
+ DateTime startDate2 = startDate.plusDays(30).plusSeconds(1);
123
+ Mockito.verify(mockMarketoRestclient, Mockito.times(1)).createActivityExtract(activityTypeIds, startDate2.toDate(), startDate.plusDays(task.getFetchDays()).toDate());
124
+ ConfigDiff configDiff = activityBulkExtractInputPlugin.buildConfigDiff(task, Mockito.mock(Schema.class), 1, Arrays.asList(taskReport));
125
+ DateFormat df = new SimpleDateFormat(MarketoUtils.MARKETO_DATE_SIMPLE_DATE_FORMAT);
126
+ Assert.assertEquals(df.format(startDate.plusDays(task.getFetchDays()).toDate()), configDiff.get(String.class, "from_date"));
127
+ }
128
+ }