View Javadoc
1   /*
2    * SPDX-License-Identifier: Apache-2.0
3    * See LICENSE file for details.
4    *
5    * Copyright 2025-2026 Hazendaz
6    * Copyright 2011-2025 Acegi Technology Pty Limited.
7    */
8   package au.com.acegi.xmlformat;
9   
10  import static au.com.acegi.xmlformat.TestUtil.fileToString;
11  import static au.com.acegi.xmlformat.TestUtil.stringToFile;
12  import static org.hamcrest.CoreMatchers.is;
13  import static org.hamcrest.MatcherAssert.assertThat;
14  import static org.junit.jupiter.api.Assertions.fail;
15  import static org.mockito.ArgumentMatchers.anyString;
16  import static org.mockito.Mockito.atLeastOnce;
17  import static org.mockito.Mockito.mock;
18  import static org.mockito.Mockito.never;
19  import static org.mockito.Mockito.verify;
20  import static org.mockito.Mockito.when;
21  
22  import java.io.File;
23  import java.io.IOException;
24  
25  import org.apache.maven.plugin.MojoExecutionException;
26  import org.apache.maven.plugin.MojoFailureException;
27  import org.apache.maven.plugin.logging.Log;
28  import org.junit.jupiter.api.Assertions;
29  import org.junit.jupiter.api.BeforeEach;
30  import org.junit.jupiter.api.Test;
31  import org.junit.jupiter.api.io.TempDir;
32  
33  /**
34   * Tests {@link XmlCheckPlugin}.
35   */
36  public class XmlCheckPluginTest {
37  
38      private static final String EMPTY_FILE_NAME = "empty.xml";
39      private static final String EMPTY_TXT = "";
40      private static final String ERR_FILE_NAME = "error.xml";
41      private static final String ERR_TXT = "<xml> <hello> hello not closed! </xml>";
42      private static final String NO_CHG_TXT = "<xml> <leave-me-alone/> </xml>";
43      private static final String TO_CHG_FILE_NAME = "my.xml";
44      private static final String TO_CHG_TXT = "<xml> <hello/> </xml>";
45  
46      @TempDir
47      private File tmp;
48  
49      @SuppressWarnings("PMD.ProperLogger")
50      private Log log;
51  
52      private File proj;
53      private File target;
54  
55      @BeforeEach
56      void before() throws IOException {
57          proj = newFolder(tmp, "junit");
58          target = proj.toPath().resolve("target").toFile();
59          assertThat(target.mkdir(), is(true));
60  
61          final File toChange = proj.toPath().resolve(TO_CHG_FILE_NAME).toFile();
62          stringToFile(TO_CHG_TXT, toChange);
63  
64          final File noChange = target.toPath().resolve("exclude-me.xml").toFile();
65          stringToFile(NO_CHG_TXT, noChange);
66  
67          final File empty = proj.toPath().resolve(EMPTY_FILE_NAME).toFile();
68          stringToFile(EMPTY_TXT, empty);
69  
70          final File error = proj.toPath().resolve(ERR_FILE_NAME).toFile();
71          stringToFile(ERR_TXT, error);
72  
73          assertThat(fileToString(toChange), is(TO_CHG_TXT));
74          assertThat(fileToString(noChange), is(NO_CHG_TXT));
75          assertThat(fileToString(empty), is(EMPTY_TXT));
76          assertThat(fileToString(error), is(ERR_TXT));
77  
78          log = mock(Log.class);
79      }
80  
81      @Test
82      @SuppressWarnings("PMD.JUnitUseExpected")
83      void pluginReportsError() throws MojoExecutionException {
84          final XmlCheckPlugin plugin = new XmlCheckPlugin();
85          plugin.setLog(log);
86          when(log.isDebugEnabled()).thenReturn(true);
87          when(log.isErrorEnabled()).thenReturn(true);
88  
89          plugin.setBaseDirectory(proj);
90          plugin.setIncludes("**/*.xml");
91          plugin.setTargetDirectory(target);
92  
93          Assertions.assertThrows(MojoFailureException.class, () -> { 
94              plugin.execute();
95              fail("Should have raised exception when handling error");
96          });
97  
98          verify(log, atLeastOnce()).isErrorEnabled();
99          verify(log, atLeastOnce()).isDebugEnabled();
100         verify(log, atLeastOnce()).debug(anyString());
101     }
102 
103     @Test
104     @SuppressWarnings("PMD.JUnitUseExpected")
105     void pluginReportsFormattingNeeded() throws MojoFailureException {
106         final XmlCheckPlugin plugin = new XmlCheckPlugin();
107         plugin.setLog(log);
108         when(log.isDebugEnabled()).thenReturn(true);
109         when(log.isErrorEnabled()).thenReturn(true);
110 
111         plugin.setBaseDirectory(proj);
112         plugin.setExcludes("**/" + ERR_FILE_NAME);
113         plugin.setIncludes("**/*.xml");
114         plugin.setTargetDirectory(target);
115 
116         Assertions.assertThrows(MojoExecutionException.class, () -> { 
117             plugin.execute();
118             fail("Should have raised exception when encountering non-formatted file");
119         });
120 
121         verify(log, atLeastOnce()).isErrorEnabled();
122         verify(log, atLeastOnce()).isDebugEnabled();
123         verify(log, atLeastOnce()).debug(anyString());
124     }
125 
126     @Test
127     void pluginSucceedsWhenAllFormatted() throws MojoExecutionException, MojoFailureException {
128         final XmlCheckPlugin plugin = new XmlCheckPlugin();
129         plugin.setLog(log);
130         when(log.isDebugEnabled()).thenReturn(true);
131         when(log.isErrorEnabled()).thenReturn(true);
132 
133         plugin.setBaseDirectory(proj);
134         plugin.setExcludes("**/" + ERR_FILE_NAME, "**/" + TO_CHG_FILE_NAME);
135         plugin.setIncludes("**/*.xml");
136         plugin.setTargetDirectory(target);
137 
138         plugin.execute();
139 
140         verify(log, never()).isErrorEnabled();
141         verify(log, atLeastOnce()).isDebugEnabled();
142         verify(log, atLeastOnce()).debug(anyString());
143     }
144 
145     @Test
146     void pluginSkip() throws MojoExecutionException, MojoFailureException {
147         final XmlCheckPlugin plugin = new XmlCheckPlugin();
148         plugin.setLog(log);
149         plugin.setSkip(true);
150         when(log.isDebugEnabled()).thenReturn(true);
151         when(log.isInfoEnabled()).thenReturn(true);
152         when(log.isErrorEnabled()).thenReturn(true);
153 
154         plugin.setBaseDirectory(proj);
155         plugin.setIncludes("**/*.xml");
156         plugin.setTargetDirectory(target);
157 
158         // Should not throw even though unformatted files exist
159         plugin.execute();
160 
161         verify(log, atLeastOnce()).info("[xml-format] Skipped");
162     }
163 
164     private static File newFolder(final File root, final String... subDirs) throws IOException {
165         final String subFolder = String.join("/", subDirs);
166         final File result = root.toPath().resolve(subFolder).toFile();
167         if (!result.mkdirs()) {
168             throw new IOException("Couldn't create folders " + root);
169         }
170         return result;
171     }
172 }