embulk-input-marketo_extended 0.6.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }