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.
- checksums.yaml +7 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +37 -0
- data/.gitignore +14 -0
- data/.travis.yml +6 -0
- data/CHANGELOG.md +170 -0
- data/LICENSE.txt +21 -0
- data/README.md +213 -0
- data/build.gradle +103 -0
- data/config/checkstyle/checkstyle.xml +128 -0
- data/config/checkstyle/default.xml +108 -0
- data/gradle/wrapper/gradle-wrapper.jar +0 -0
- data/gradle/wrapper/gradle-wrapper.properties +6 -0
- data/gradlew +169 -0
- data/gradlew.bat +84 -0
- data/lib/embulk/input/marketo.rb +3 -0
- data/settings.gradle +1 -0
- data/src/main/java/org/embulk/input/marketo/CsvTokenizer.java +700 -0
- data/src/main/java/org/embulk/input/marketo/MarketoInputPlugin.java +15 -0
- data/src/main/java/org/embulk/input/marketo/MarketoInputPluginDelegate.java +100 -0
- data/src/main/java/org/embulk/input/marketo/MarketoService.java +38 -0
- data/src/main/java/org/embulk/input/marketo/MarketoServiceImpl.java +245 -0
- data/src/main/java/org/embulk/input/marketo/MarketoUtils.java +212 -0
- data/src/main/java/org/embulk/input/marketo/delegate/ActivityBulkExtractInputPlugin.java +167 -0
- data/src/main/java/org/embulk/input/marketo/delegate/CampaignInputPlugin.java +48 -0
- data/src/main/java/org/embulk/input/marketo/delegate/CustomObjectInputPlugin.java +75 -0
- data/src/main/java/org/embulk/input/marketo/delegate/CustomObjectResponseMapperBuilder.java +81 -0
- data/src/main/java/org/embulk/input/marketo/delegate/LeadBulkExtractInputPlugin.java +66 -0
- data/src/main/java/org/embulk/input/marketo/delegate/LeadServiceResponseMapperBuilder.java +85 -0
- data/src/main/java/org/embulk/input/marketo/delegate/LeadWithListInputPlugin.java +64 -0
- data/src/main/java/org/embulk/input/marketo/delegate/LeadWithProgramInputPlugin.java +60 -0
- data/src/main/java/org/embulk/input/marketo/delegate/MarketoBaseBulkExtractInputPlugin.java +441 -0
- data/src/main/java/org/embulk/input/marketo/delegate/MarketoBaseInputPluginDelegate.java +92 -0
- data/src/main/java/org/embulk/input/marketo/delegate/ProgramInputPlugin.java +228 -0
- data/src/main/java/org/embulk/input/marketo/exception/MarketoAPIException.java +30 -0
- data/src/main/java/org/embulk/input/marketo/model/BulkExtractRangeHeader.java +26 -0
- data/src/main/java/org/embulk/input/marketo/model/MarketoAccessTokenResponse.java +92 -0
- data/src/main/java/org/embulk/input/marketo/model/MarketoBulkExtractRequest.java +68 -0
- data/src/main/java/org/embulk/input/marketo/model/MarketoError.java +40 -0
- data/src/main/java/org/embulk/input/marketo/model/MarketoField.java +126 -0
- data/src/main/java/org/embulk/input/marketo/model/MarketoResponse.java +82 -0
- data/src/main/java/org/embulk/input/marketo/model/filter/DateRangeFilter.java +40 -0
- data/src/main/java/org/embulk/input/marketo/rest/MarketoBaseRestClient.java +306 -0
- data/src/main/java/org/embulk/input/marketo/rest/MarketoInputStreamResponseEntityReader.java +69 -0
- data/src/main/java/org/embulk/input/marketo/rest/MarketoRESTEndpoint.java +47 -0
- data/src/main/java/org/embulk/input/marketo/rest/MarketoResponseJetty92EntityReader.java +89 -0
- data/src/main/java/org/embulk/input/marketo/rest/MarketoRestClient.java +569 -0
- data/src/main/java/org/embulk/input/marketo/rest/RecordPagingIterable.java +180 -0
- data/src/test/java/org/embulk/input/marketo/MarketoServiceImplTest.java +140 -0
- data/src/test/java/org/embulk/input/marketo/MarketoUtilsTest.java +87 -0
- data/src/test/java/org/embulk/input/marketo/delegate/ActivityBulkExtractInputPluginTest.java +128 -0
- data/src/test/java/org/embulk/input/marketo/delegate/CampaignInputPluginTest.java +73 -0
- data/src/test/java/org/embulk/input/marketo/delegate/CustomObjectInputPluginTest.java +102 -0
- data/src/test/java/org/embulk/input/marketo/delegate/LeadBulkExtractInputPluginTest.java +99 -0
- data/src/test/java/org/embulk/input/marketo/delegate/LeadServiceResponseMapperBuilderTest.java +119 -0
- data/src/test/java/org/embulk/input/marketo/delegate/LeadWithListInputPluginTest.java +101 -0
- data/src/test/java/org/embulk/input/marketo/delegate/LeadWithProgramInputPluginTest.java +103 -0
- data/src/test/java/org/embulk/input/marketo/delegate/MarketoBaseBulkExtractInputPluginTest.java +169 -0
- data/src/test/java/org/embulk/input/marketo/delegate/ProgramInputPluginTest.java +343 -0
- data/src/test/java/org/embulk/input/marketo/rest/MarketoBaseRestClientTest.java +368 -0
- data/src/test/java/org/embulk/input/marketo/rest/MarketoRestClientTest.java +584 -0
- data/src/test/resources/config/activity_bulk_extract_config.yaml +7 -0
- data/src/test/resources/config/custom_object_config.yaml +8 -0
- data/src/test/resources/config/lead_bulk_extract_config.yaml +8 -0
- data/src/test/resources/config/rest_config.yaml +3 -0
- data/src/test/resources/fixtures/activity_extract1.csv +35 -0
- data/src/test/resources/fixtures/activity_extract2.csv +22 -0
- data/src/test/resources/fixtures/activity_types.json +22 -0
- data/src/test/resources/fixtures/all_program_full.json +53 -0
- data/src/test/resources/fixtures/campaign_response.json +38 -0
- data/src/test/resources/fixtures/campaign_response_full.json +102 -0
- data/src/test/resources/fixtures/custom_object_describe.json +124 -0
- data/src/test/resources/fixtures/custom_object_describe_marketo_fields_full.json +22 -0
- data/src/test/resources/fixtures/custom_object_expected.json +66 -0
- data/src/test/resources/fixtures/custom_object_response.json +24 -0
- data/src/test/resources/fixtures/custom_object_response_full.json +23 -0
- data/src/test/resources/fixtures/lead_by_list.json +33 -0
- data/src/test/resources/fixtures/lead_by_program_response.json +47 -0
- data/src/test/resources/fixtures/lead_describe.json +221 -0
- data/src/test/resources/fixtures/lead_describe_expected.json +66 -0
- data/src/test/resources/fixtures/lead_describe_marketo_fields_full.json +518 -0
- data/src/test/resources/fixtures/lead_extract1.csv +11 -0
- data/src/test/resources/fixtures/lead_response_full.json +2402 -0
- data/src/test/resources/fixtures/lead_with_program_full.json +17 -0
- data/src/test/resources/fixtures/leads_extract2.csv +10 -0
- data/src/test/resources/fixtures/list_reponse_full.json +191 -0
- data/src/test/resources/fixtures/lists_response.json +31 -0
- data/src/test/resources/fixtures/program_response.json +71 -0
- 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
|
+
}
|