diff --git a/Jenkinsfile b/Jenkinsfile
index 641d8a0..8b1892a 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -6,7 +6,7 @@ boolean onJenkinsCI = env.JENKINS_URL &&
if (onJenkinsCI) {
/* running on ci.jenkins.io, we will have `buildPlugin` step provided by: https://github.com/jenkins-infra/pipeline-library */
- buildPlugin()
+ buildPlugin(['platforms': ['linux']])
return
}
@@ -59,12 +59,11 @@ try {
// notify if compile+unit test successful
notify.testResults(null)
- archive "**/${hpiFiles},**/target/site/jacoco/**"
+ archive "**/${hpiFiles}"
}
stage('Report') {
- // this is not working properly yet
- // step([$class: 'JacocoPublisher'])
+ step([$class: 'JacocoPublisher'])
}
}
}
diff --git a/README.md b/README.md
index 197c5d6..52947e6 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-[![Build Status](https://ci.jenkins.io/buildStatus/icon?job=Plugins/zanata-plugin/master)](https://ci.jenkins.io/job/Plugins/job/zanata-plugin/job/master/)
+master branch: [![Build Status](https://ci.jenkins.io/buildStatus/icon?job=Plugins/zanata-plugin/master)](https://ci.jenkins.io/job/Plugins/job/zanata-plugin/job/master/)
### A Jenkins plugin to synchronize localization resources between SCM repository and Zanata
diff --git a/pom.xml b/pom.xml
index 30a1bdf..b6a38ba 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,6 +13,7 @@
hpi
+ 0.64
1.625.3
@@ -232,6 +233,19 @@
+
+
+ check-coverage
+
+
+ windows
+
+
+
+
+ 0
+
+
@@ -239,6 +253,7 @@
org.jacoco
jacoco-maven-plugin
+ 0.7.9
default-prepare-agent
@@ -264,9 +279,9 @@
BUNDLE
- COMPLEXITY
+ INSTRUCTION
COVEREDRATIO
- 0.60
+ ${coverage.limit}
diff --git a/src/main/java/org/jenkinsci/plugins/zanata/cli/service/ZanataSyncService.java b/src/main/java/org/jenkinsci/plugins/zanata/cli/service/ZanataSyncService.java
index 2a34fc3..97b6896 100644
--- a/src/main/java/org/jenkinsci/plugins/zanata/cli/service/ZanataSyncService.java
+++ b/src/main/java/org/jenkinsci/plugins/zanata/cli/service/ZanataSyncService.java
@@ -32,10 +32,6 @@
*/
public interface ZanataSyncService extends Serializable {
- PullOptions getPullOptions();
-
- PushOptions getPushOptions();
-
void pushToZanata(Path repoBase) throws ZanataSyncException;
void pullFromZanata(Path repoBase) throws ZanataSyncException;
diff --git a/src/main/java/org/jenkinsci/plugins/zanata/cli/service/impl/ZanataSyncServiceImpl.java b/src/main/java/org/jenkinsci/plugins/zanata/cli/service/impl/ZanataSyncServiceImpl.java
index 882f9b0..183564e 100644
--- a/src/main/java/org/jenkinsci/plugins/zanata/cli/service/impl/ZanataSyncServiceImpl.java
+++ b/src/main/java/org/jenkinsci/plugins/zanata/cli/service/impl/ZanataSyncServiceImpl.java
@@ -23,6 +23,7 @@
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
+import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collections;
@@ -30,6 +31,8 @@
import java.util.Set;
import org.jenkinsci.plugins.zanata.cli.HasSyncJobDetail;
+import org.jenkinsci.plugins.zanata.cli.service.PullService;
+import org.jenkinsci.plugins.zanata.cli.service.PushService;
import org.jenkinsci.plugins.zanata.cli.service.ZanataSyncService;
import org.jenkinsci.plugins.zanata.cli.util.PushPullOptionsUtil;
import org.jenkinsci.plugins.zanata.exception.ZanataSyncException;
@@ -41,6 +44,7 @@
import org.zanata.client.commands.push.PushOptions;
import org.zanata.client.commands.push.PushOptionsImpl;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
@@ -54,51 +58,71 @@ public class ZanataSyncServiceImpl implements ZanataSyncService {
LoggerFactory.getLogger(ZanataSyncServiceImpl.class);
private static final long serialVersionUID = 1L;
- private final transient PullOptions pullOptions;
- private final transient PushOptions pushOptions;
-
- private final PushServiceImpl pushService = new PushServiceImpl();
- private final PullServiceImpl pullService = new PullServiceImpl();
+ private final PushService pushService;
+ private final PullService pullService;
private final Set projectConfigs;
-
- public ZanataSyncServiceImpl(HasSyncJobDetail jobDetail) {
- String zanataUrl = jobDetail.getZanataURL();
+ private final String zanataUrl;
+ private final String username;
+ private final String apiKey;
+ private final String localeId;
+ private final String pushToZanataOption;
+
+ @VisibleForTesting
+ protected ZanataSyncServiceImpl(PullService pullService,
+ PushService pushService, HasSyncJobDetail jobDetail) {
+ this.pullService = pullService;
+ this.pushService = pushService;
+ zanataUrl = jobDetail.getZanataURL();
String syncToZanataOption = jobDetail.getSyncOption();
- String pushToZanataOption = Strings.emptyToNull(syncToZanataOption);
- String username = jobDetail.getZanataUsername();
- String apiKey = jobDetail.getZanataSecret();
+ pushToZanataOption = Strings.emptyToNull(syncToZanataOption);
+ username = jobDetail.getZanataUsername();
+ apiKey = jobDetail.getZanataSecret();
projectConfigs = getProjectConfigs(jobDetail.getZanataProjectConfigs());
- String localeId = jobDetail.getZanataLocaleIds();
- PullOptionsImpl pullOptions = new PullOptionsImpl();
+ localeId = jobDetail.getZanataLocaleIds();
+
+
+ // if project id is given from webhook, only handle this project
+ // String projectId = jobDetail.getProject();
+ // if (!Strings.isNullOrEmpty(projectId)) {
+ // pullOptions.setProj(projectId);
+ // pushOptions.setProj(projectId);
+ // }
+ }
+
+ public ZanataSyncServiceImpl(HasSyncJobDetail jobDetail) {
+ this(new PullServiceImpl(), new PushServiceImpl(), jobDetail);
+ }
+
+ private PushOptionsImpl newPushOptionsFromJobConfig() {
PushOptionsImpl pushOptions = new PushOptionsImpl();
- pullOptions.setInteractiveMode(false);
pushOptions.setInteractiveMode(false);
- pullOptions.setUsername(username);
- pullOptions.setKey(apiKey);
pushOptions.setUsername(username);
pushOptions.setKey(apiKey);
pushOptions.setPushType(pushToZanataOption);
- // TODO until https://zanata.atlassian.net/browse/ZNTA-1427 is fixed we can't trust etag cache
- pullOptions.setUseCache(false);
+ // if localeId is given, only handle this locale
+ if (!Strings.isNullOrEmpty(localeId)) {
+ pushOptions.setLocales(localeId);
+ }
+ overrideURLIfSpecified(pushOptions, zanataUrl);
+ // this.pushOptions.setLogHttp(true);
+ return pushOptions;
+ }
- this.pushOptions = pushOptions;
- this.pullOptions = pullOptions;
-// this.pushOptions.setLogHttp(true);
-// this.pullOptions.setLogHttp(true);
+ private PullOptionsImpl newPullOptionsFromJobConfig() {
+ PullOptionsImpl pullOptions = new PullOptionsImpl();
+ pullOptions.setInteractiveMode(false);
+ pullOptions.setUsername(username);
+ pullOptions.setKey(apiKey);
// if localeId is given, only handle this locale
if (!Strings.isNullOrEmpty(localeId)) {
pullOptions.setLocales(localeId);
- pushOptions.setLocales(localeId);
}
- // if project id is given, only handle this project
-// String projectId = jobDetail.getProject();
-// if (!Strings.isNullOrEmpty(projectId)) {
-// pullOptions.setProj(projectId);
-// pushOptions.setProj(projectId);
-// }
- overrideURLIfSpecified(getPushOptions(), zanataUrl);
- overrideURLIfSpecified(getPullOptions(), zanataUrl);
+ overrideURLIfSpecified(pullOptions, zanataUrl);
+ // TODO https://zanata.atlassian.net/browse/ZNTA-1427 is fixed, we should set cacheDir to workspace root
+ pullOptions.setUseCache(false);
+ // this.pullOptions.setLogHttp(true);
+ return pullOptions;
}
private static Set getProjectConfigs(String projectConfigs) {
@@ -110,43 +134,43 @@ private static Set getProjectConfigs(String projectConfigs) {
.split(projectConfigs));
}
- @Override
- public PullOptions getPullOptions() {
- return pullOptions;
- }
-
- @Override
- public PushOptions getPushOptions() {
- return pushOptions;
- }
-
@Override
public void pushToZanata(Path repoBase) throws ZanataSyncException {
- String project = getPushOptions().getProj();
if (projectConfigs.isEmpty()) {
Set projectConfigs = findProjectConfigsOrThrow(repoBase);
for (File config : projectConfigs) {
+ PushOptionsImpl opts = newPushOptionsFromJobConfig();
+ String project = opts.getProj();
+
PushPullOptionsUtil
- .applyProjectConfig(getPushOptions(), config);
- log.info("{} - {}", getPushOptions());
- pushIfProjectIdMatchesConfig(project, config);
+ .applyProjectConfig(opts, config);
+ pushIfProjectIdMatchesConfig(opts, project, config);
}
} else {
for (String projectConfig : projectConfigs) {
Path absPath = Paths.get(repoBase.toString(), projectConfig);
- PushPullOptionsUtil.applyProjectConfig(getPushOptions(), absPath.toFile());
- pushIfProjectIdMatchesConfig(project, absPath.toFile());
+ if (Files.exists(absPath)) {
+ PushOptionsImpl opts = newPushOptionsFromJobConfig();
+ String project = opts.getProj();
+
+ PushPullOptionsUtil.applyProjectConfig(
+ opts, absPath.toFile());
+ pushIfProjectIdMatchesConfig(opts, project, absPath.toFile());
+ } else {
+ log.warn("{} does not exist! Ignored!", projectConfig);
+ }
}
}
}
- private void pushIfProjectIdMatchesConfig(String project, File config) {
- if (Strings.isNullOrEmpty(project) || Objects.equals(getPushOptions().getProj(), project)) {
- pushService.pushToZanata(getPushOptions());
+ private void pushIfProjectIdMatchesConfig(PushOptions opts, String project,
+ File config) {
+ if (Strings.isNullOrEmpty(project) || Objects.equals(opts.getProj(), project)) {
+ pushService.pushToZanata(opts);
} else if (!Strings.isNullOrEmpty(project)) {
log.warn(
"project id is provided as {}. Skip {} which has project set to {}",
- config, getPushOptions().getProj());
+ config, opts.getProj());
}
}
@@ -176,31 +200,42 @@ private Set findProjectConfigsOrThrow(Path repoBase) {
@Override
public void pullFromZanata(Path repoBase) throws ZanataSyncException {
- String project = getPullOptions().getProj();
if (projectConfigs.isEmpty()) {
Set projectConfigs =
findProjectConfigsOrThrow(repoBase);
for (File config : projectConfigs) {
+ PullOptionsImpl opts = newPullOptionsFromJobConfig();
+ String project = opts.getProj();
+
PushPullOptionsUtil
- .applyProjectConfig(getPullOptions(), config);
- pullIfProjectIdMatchesConfig(project, config);
+ .applyProjectConfig(opts, config);
+ pullIfProjectIdMatchesConfig(opts, project, config);
}
} else {
for (String projectConfig : projectConfigs) {
Path absPath = Paths.get(repoBase.toString(), projectConfig);
- PushPullOptionsUtil.applyProjectConfig(getPullOptions(), absPath.toFile());
- pullIfProjectIdMatchesConfig(project, absPath.toFile());
+ if (Files.exists(absPath)) {
+ PullOptionsImpl opts = newPullOptionsFromJobConfig();
+ String project = opts.getProj();
+
+ opts = PushPullOptionsUtil.applyProjectConfig(opts,
+ absPath.toFile());
+ pullIfProjectIdMatchesConfig(opts, project, absPath.toFile());
+ } else {
+ log.warn("{} does not exist! Ignored!", projectConfig);
+ }
}
}
}
- private void pullIfProjectIdMatchesConfig(String project, File config) {
- if (Strings.isNullOrEmpty(project) || Objects.equals(getPushOptions().getProj(), project)) {
- pullService.pullFromZanata(getPullOptions());
+ private void pullIfProjectIdMatchesConfig(PullOptions opts,
+ String project, File config) {
+ if (Strings.isNullOrEmpty(project) || Objects.equals(opts.getProj(), project)) {
+ pullService.pullFromZanata(opts);
} else if (!Strings.isNullOrEmpty(project)) {
log.warn(
"project id is provided as {}. Skip {} which has project set to {}",
- config, getPushOptions().getProj());
+ config, opts.getProj());
}
}
}
diff --git a/src/main/java/org/jenkinsci/plugins/zanata/cli/util/PushPullOptionsUtil.java b/src/main/java/org/jenkinsci/plugins/zanata/cli/util/PushPullOptionsUtil.java
index 988c331..bf41f70 100644
--- a/src/main/java/org/jenkinsci/plugins/zanata/cli/util/PushPullOptionsUtil.java
+++ b/src/main/java/org/jenkinsci/plugins/zanata/cli/util/PushPullOptionsUtil.java
@@ -138,12 +138,6 @@ public final class PushPullOptionsUtil {
public static O applyProjectConfig(O options,
File projectConfig) {
options.setProjectConfig(projectConfig);
- // unset previous values so that we can reload them from project config
- options.setSrcDir(null);
- options.setTransDir(null);
- options.setProj(null);
- options.setProjectVersion(null);
- options.setProjectType(null);
try {
// here we must take it step by step due to an issue http://stackoverflow.com/questions/41253028/how-to-make-jenkins-plugin-aware-of-spi
@@ -169,6 +163,7 @@ public static O applyProjectConfig(O options,
options.setTransDir(
new File(baseDir, options.getTransDir() != null ?
options.getTransDir().getPath() : "."));
+ // TODO maybe we should allow this as long as user can configure their jenkins box to have the commands available?
// disable commandhook
if (!options.getCommandHooks().isEmpty()) {
throw new ZanataSyncException(
diff --git a/src/test/java/org/jenkinsci/plugins/zanata/cli/service/impl/ZanataSyncServiceImplTest.java b/src/test/java/org/jenkinsci/plugins/zanata/cli/service/impl/ZanataSyncServiceImplTest.java
new file mode 100644
index 0000000..4ad40cb
--- /dev/null
+++ b/src/test/java/org/jenkinsci/plugins/zanata/cli/service/impl/ZanataSyncServiceImplTest.java
@@ -0,0 +1,248 @@
+package org.jenkinsci.plugins.zanata.cli.service.impl;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+import static org.jenkinsci.plugins.zanata.SyncJobDetail.Builder.builder;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+
+import org.jenkinsci.plugins.zanata.SyncJobDetail;
+import org.jenkinsci.plugins.zanata.cli.service.PullService;
+import org.jenkinsci.plugins.zanata.cli.service.PushService;
+import org.jenkinsci.plugins.zanata.exception.ZanataSyncException;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.jvnet.hudson.test.WithoutJenkins;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.zanata.client.commands.pull.PullOptions;
+import org.zanata.client.commands.push.PushOptions;
+import org.zanata.client.config.LocaleList;
+import org.zanata.client.config.LocaleMapping;
+import org.zanata.client.config.ZanataConfig;
+
+import com.google.common.collect.Lists;
+
+public class ZanataSyncServiceImplTest {
+ @Rule
+ public TemporaryFolder temporaryFolder = new TemporaryFolder();
+
+ private ZanataSyncServiceImpl service;
+ @Mock
+ private PullService pullService;
+ @Mock
+ private PushService pushService;
+ private File workspace;
+ @Captor
+ private ArgumentCaptor pushOptionsCaptor;
+ @Captor
+ private ArgumentCaptor pullOptionsCaptor;
+ private static Marshaller marshaller;
+
+ @BeforeClass
+ public static void setupMarshaller() throws JAXBException {
+ JAXBContext jc = JAXBContext.newInstance(ZanataConfig.class);
+ marshaller = jc.createMarshaller();
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ workspace = temporaryFolder.newFolder();
+
+ ZanataConfig zanataConfig = makeZanataConfig("test");
+
+ marshaller.marshal(zanataConfig, new File(workspace, "zanata.xml"));
+
+ }
+
+ private static ZanataConfig makeZanataConfig(String project) throws MalformedURLException {
+ ZanataConfig zanataConfig = new ZanataConfig();
+ LocaleList localeList = new LocaleList();
+ Lists.newArrayList("zh", "ja", "de", "pl").stream().map(
+ LocaleMapping::new).forEach(localeList::add);
+ zanataConfig.setLocales(localeList);
+ zanataConfig.setUrl(new URL("http://zanata.org"));
+ zanataConfig.setProject(project);
+ zanataConfig.setProjectVersion("master");
+ zanataConfig.setProjectType("podir");
+ return zanataConfig;
+ }
+
+ @Test
+ @WithoutJenkins
+ public void testOverrideUrlForPush() throws MalformedURLException {
+ String zanataUrl = "http://localhost";
+ SyncJobDetail jobDetail = builder().setZanataUrl(zanataUrl).build();
+ service =
+ new ZanataSyncServiceImpl(pullService, pushService, jobDetail);
+
+ service.pushToZanata(workspace.toPath());
+
+ Mockito.verify(pushService).pushToZanata(pushOptionsCaptor.capture());
+ assertThat(pushOptionsCaptor.getValue().getUrl())
+ .isEqualTo(new URL(zanataUrl));
+
+ }
+
+ @Test
+ @WithoutJenkins
+ public void testOverrideUrlForPull() throws MalformedURLException {
+ String zanataUrl = "http://localhost";
+ SyncJobDetail jobDetail = builder().setZanataUrl(zanataUrl).build();
+ service =
+ new ZanataSyncServiceImpl(pullService, pushService, jobDetail);
+
+ service.pullFromZanata(workspace.toPath());
+
+ Mockito.verify(pullService).pullFromZanata(pullOptionsCaptor.capture());
+ assertThat(pullOptionsCaptor.getValue().getUrl())
+ .isEqualTo(new URL(zanataUrl));
+
+ }
+
+ @Test
+ @WithoutJenkins
+ public void invalidURLWillTriggerError() {
+ String zanataUrl = "not valid url";
+ SyncJobDetail jobDetail = builder().setZanataUrl(zanataUrl).build();
+ service =
+ new ZanataSyncServiceImpl(pullService, pushService, jobDetail);
+
+ assertThatExceptionOfType(IllegalArgumentException.class)
+ .isThrownBy(() -> {
+ service.pushToZanata(workspace.toPath());
+ });
+
+ assertThatExceptionOfType(IllegalArgumentException.class)
+ .isThrownBy(() -> {
+ service.pullFromZanata(workspace.toPath());
+ });
+ }
+
+ @Test
+ @WithoutJenkins
+ public void canOverrideLocaleIdForPush() {
+ String localeIds = "zh,ja";
+ SyncJobDetail jobDetail = builder().setLocaleId(localeIds).build();
+ service =
+ new ZanataSyncServiceImpl(pullService, pushService, jobDetail);
+
+ service.pushToZanata(workspace.toPath());
+
+ Mockito.verify(pushService).pushToZanata(pushOptionsCaptor.capture());
+ assertThat(pushOptionsCaptor.getValue().getLocaleMapList())
+ .contains(new LocaleMapping("zh"), new LocaleMapping("ja"));
+
+ }
+
+ @Test
+ @WithoutJenkins
+ public void canOverrideLocaleIdForPull() {
+ String localeIds = "de";
+ SyncJobDetail jobDetail = builder().setLocaleId(localeIds).build();
+ service =
+ new ZanataSyncServiceImpl(pullService, pushService, jobDetail);
+
+ service.pullFromZanata(workspace.toPath());
+
+ Mockito.verify(pullService).pullFromZanata(pullOptionsCaptor.capture());
+ assertThat(pullOptionsCaptor.getValue().getLocaleMapList())
+ .contains(new LocaleMapping("de"));
+
+ }
+
+ @Test
+ @WithoutJenkins
+ public void failIfNoProjectConfigCanBeFound() throws IOException {
+ SyncJobDetail jobDetail = builder().build();
+
+ File emptyWorkspace = temporaryFolder.newFolder();
+ service =
+ new ZanataSyncServiceImpl(pullService, pushService, jobDetail);
+
+ assertThatExceptionOfType(ZanataSyncException.class)
+ .isThrownBy(() -> {
+ service.pushToZanata(emptyWorkspace.toPath());
+ })
+ .withMessage("can not find project config (zanata.xml) in the repo");
+
+ assertThatExceptionOfType(ZanataSyncException.class)
+ .isThrownBy(() -> {
+ service.pullFromZanata(emptyWorkspace.toPath());
+ })
+ .withMessage("can not find project config (zanata.xml) in the repo");
+ }
+
+ @Test
+ @WithoutJenkins
+ public void canSpecifyNonExistProjectConfigsForPush() {
+ SyncJobDetail jobDetail =
+ builder().setProjectConfigs("non-exist.xml").build();
+
+ service =
+ new ZanataSyncServiceImpl(pullService, pushService, jobDetail);
+
+ service.pushToZanata(workspace.toPath());
+
+ Mockito.verifyZeroInteractions(pushService);
+ }
+
+ @Test
+ @WithoutJenkins
+ public void canSpecifyNonExistProjectConfigsForPull() {
+ SyncJobDetail jobDetail =
+ builder().setProjectConfigs("non-exist.xml").build();
+
+ service =
+ new ZanataSyncServiceImpl(pullService, pushService, jobDetail);
+
+ service.pullFromZanata(workspace.toPath());
+
+ Mockito.verifyZeroInteractions(pullService);
+ }
+
+ @Test
+ @WithoutJenkins
+ public void canSpecifyProjectConfigsForPush() throws Exception {
+ // we have a workspace that contains two zanata.xml in two folders
+ File workspace = temporaryFolder.newFolder();
+ File folder1 = new File(workspace, "one");
+ assertThat(folder1.mkdirs()).isTrue();
+ File folder2 = new File(workspace, "two");
+ assertThat(folder2.mkdirs()).isTrue();
+
+ ZanataConfig project1 = makeZanataConfig("project-one");
+ ZanataConfig project2 = makeZanataConfig("project-two");
+ marshaller.marshal(project1, new File(folder1, "zanata.xml"));
+ marshaller.marshal(project2, new File(folder2, "zanata.xml"));
+
+ // when specify project configs in the job
+ SyncJobDetail jobDetail =
+ builder().setProjectConfigs("one/zanata.xml").build();
+
+ service =
+ new ZanataSyncServiceImpl(pullService, pushService, jobDetail);
+
+ service.pushToZanata(workspace.toPath());
+
+ // then only push the one we specified
+ Mockito.verify(pushService, Mockito.times(1))
+ .pushToZanata(pushOptionsCaptor.capture());
+ assertThat(pushOptionsCaptor.getValue().getProj()).isEqualTo("project-one");
+ }
+
+}
diff --git a/src/test/java/org/jenkinsci/plugins/zanata/cli/util/PushPullOptionsUtilTest.java b/src/test/java/org/jenkinsci/plugins/zanata/cli/util/PushPullOptionsUtilTest.java
new file mode 100644
index 0000000..4281af8
--- /dev/null
+++ b/src/test/java/org/jenkinsci/plugins/zanata/cli/util/PushPullOptionsUtilTest.java
@@ -0,0 +1,70 @@
+package org.jenkinsci.plugins.zanata.cli.util;
+
+import java.io.File;
+import java.io.IOException;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+
+import org.jenkinsci.plugins.zanata.exception.ZanataSyncException;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.zanata.client.commands.push.PushOptionsImpl;
+import org.zanata.client.config.CommandHook;
+import org.zanata.client.config.LocaleList;
+import org.zanata.client.config.LocaleMapping;
+import org.zanata.client.config.ZanataConfig;
+
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+
+public class PushPullOptionsUtilTest {
+ @Rule
+ public TemporaryFolder temporaryFolder = new TemporaryFolder();
+
+ private static Marshaller marshaller;
+
+ @BeforeClass
+ public static void setupMarshaller() throws JAXBException {
+ JAXBContext jc = JAXBContext.newInstance(ZanataConfig.class);
+ marshaller = jc.createMarshaller();
+ }
+
+ @Test
+ public void failIfZanataProjectConfigIsInvalid() throws IOException {
+
+ assertThatExceptionOfType(ZanataSyncException.class)
+ .isThrownBy(() -> PushPullOptionsUtil.applyProjectConfig(
+ new PushOptionsImpl(),
+ temporaryFolder.newFile("zanata.xml")))
+ .withMessage("Failed applying project config");
+ }
+
+ @Test
+ public void failIfProjectConfigContainsCommandHook() throws Exception {
+ ZanataConfig zanataConfig = new ZanataConfig();
+ LocaleList locales = new LocaleList();
+ locales.add(new LocaleMapping("zh"));
+ zanataConfig.setLocales(locales);
+ CommandHook hook = new CommandHook();
+ hook.setCommand("make");
+ hook.getBefores().add("make prepare");
+ zanataConfig.getHooks().add(hook);
+
+ File configFile = temporaryFolder.newFile("zanata.xml");
+ marshaller.marshal(zanataConfig, configFile);
+
+ PushOptionsImpl options = new PushOptionsImpl();
+ options.setBatchMode(true);
+ assertThatExceptionOfType(ZanataSyncException.class)
+ .isThrownBy(() -> {
+ PushPullOptionsUtil.applyProjectConfig(
+ options,
+ configFile);
+ })
+ .withMessage("Commandhook in zanata.xml is not supported");
+ }
+
+}
diff --git a/src/test/java/org/jenkinsci/plugins/zanata/zanatareposync/ZanataCLIInstallTest.java b/src/test/java/org/jenkinsci/plugins/zanata/zanatareposync/ZanataCLIInstallTest.java
index 10e3fcb..428ca60 100644
--- a/src/test/java/org/jenkinsci/plugins/zanata/zanatareposync/ZanataCLIInstallTest.java
+++ b/src/test/java/org/jenkinsci/plugins/zanata/zanatareposync/ZanataCLIInstallTest.java
@@ -35,6 +35,7 @@
public class ZanataCLIInstallTest extends WithJenkins {
+ // TODO this will fail on windows
@Test
public void testInstallation() throws IOException, InterruptedException {
VirtualChannel channel = Jenkins.getActiveInstance().getChannel();
diff --git a/src/test/java/org/jenkinsci/plugins/zanata/zanatareposync/ZanataSyncStepWithZanataTest.java b/src/test/java/org/jenkinsci/plugins/zanata/zanatareposync/ZanataSyncStepWithZanataTest.java
index a355a5c..d03acb3 100644
--- a/src/test/java/org/jenkinsci/plugins/zanata/zanatareposync/ZanataSyncStepWithZanataTest.java
+++ b/src/test/java/org/jenkinsci/plugins/zanata/zanatareposync/ZanataSyncStepWithZanataTest.java
@@ -28,6 +28,7 @@
* @author Patrick Huang
* pahuang@redhat.com
*/
+// TODO this will fail on windows
public class ZanataSyncStepWithZanataTest extends WithJenkins {
private static final int FIVE_MINUTES = 1000 * 60 * 5;
@Rule