View Javadoc
1   /*-
2    * #%L
3    * io.earcam.instrumental.module.manifest
4    * %%
5    * Copyright (C) 2018 earcam
6    * %%
7    * SPDX-License-Identifier: (BSD-3-Clause OR EPL-1.0 OR Apache-2.0 OR MIT)
8    * 
9    * You <b>must</b> choose to accept, in full - any individual or combination of 
10   * the following licenses:
11   * <ul>
12   * 	<li><a href="https://opensource.org/licenses/BSD-3-Clause">BSD-3-Clause</a></li>
13   * 	<li><a href="https://www.eclipse.org/legal/epl-v10.html">EPL-1.0</a></li>
14   * 	<li><a href="https://www.apache.org/licenses/LICENSE-2.0">Apache-2.0</a></li>
15   * 	<li><a href="https://opensource.org/licenses/MIT">MIT</a></li>
16   * </ul>
17   * #L%
18   */
19  package io.earcam.instrumental.module.manifest;
20  
21  import static io.earcam.instrumental.module.manifest.ManifestInfoBuilder.attribute;
22  import static io.earcam.instrumental.module.manifest.ManifestInfoBuilder.ManifestNamedEntry.entry;
23  import static java.util.jar.Attributes.Name.IMPLEMENTATION_TITLE;
24  import static org.hamcrest.MatcherAssert.assertThat;
25  import static org.hamcrest.Matchers.*;
26  import static org.hamcrest.Matchers.is;
27  import static org.hamcrest.Matchers.not;
28  import static org.junit.jupiter.api.Assertions.*;
29  
30  import java.io.ByteArrayInputStream;
31  import java.io.ByteArrayOutputStream;
32  import java.io.IOException;
33  import java.util.jar.Attributes;
34  import java.util.jar.Manifest;
35  
36  import org.junit.jupiter.api.Nested;
37  import org.junit.jupiter.api.Test;
38  
39  import io.earcam.unexceptional.Closing;
40  
41  public class AbstractManifestBuilderTest {
42  
43  	static final class TestManifestBuilder extends AbstractManifestBuilder<TestManifestBuilder> {
44  
45  		public boolean hookWasInvoked;
46  
47  
48  		@Override
49  		protected TestManifestBuilder self()
50  		{
51  			return this;
52  		}
53  
54  
55  		@Override
56  		protected void preBuildHook()
57  		{
58  			hookWasInvoked = true;
59  		}
60  
61  
62  		@Override
63  		public boolean equals(AbstractManifestBuilder<?> that)
64  		{
65  			return same(that);
66  		}
67  	}
68  
69  	@Nested
70  	class Equality {
71  
72  		private TestManifestBuilder a = new TestManifestBuilder()
73  				.manifestMain(attribute(IMPLEMENTATION_TITLE, "Imps"))
74  				.manifestNamed(entry("com.acme.SomeThing").attribute("XYZ-Digest", "xyz=="));
75  
76  
77  		@Test
78  		void equal()
79  		{
80  			ManifestInfo b = new TestManifestBuilder()
81  					.manifestMain(attribute(IMPLEMENTATION_TITLE, "Imps"))
82  					.manifestNamed(entry("com.acme.SomeThing").attribute("XYZ-Digest", "xyz=="));
83  
84  			assertThat(a, is(equalTo(b)));
85  			assertThat(a.hashCode(), is(equalTo(b.hashCode())));
86  		}
87  
88  
89  		@Test
90  		void notEqualWhenMainAttributesDiffer()
91  		{
92  			ManifestInfo b = new TestManifestBuilder()
93  					.manifestMain(attribute(IMPLEMENTATION_TITLE, "Something completely different"))
94  					.manifestNamed(entry("com.acme.SomeThing").attribute("XYZ-Digest", "xyz=="));
95  
96  			assertThat(a, is(not(equalTo(b))));
97  		}
98  
99  
100 		@Test
101 		void notEqualWhenNamedEntriesDiffer()
102 		{
103 			ManifestInfo b = new TestManifestBuilder()
104 					.manifestMain(attribute(IMPLEMENTATION_TITLE, "Imps"))
105 					.manifestNamed(entry("com.acme.SomeThing").attribute("XYZ-Digest", "ABC=="));
106 
107 			assertThat(a, is(not(equalTo(b))));
108 		}
109 
110 
111 		@Test
112 		void notEqualToNull()
113 		{
114 			TestManifestBuilder b = null;
115 			assertFalse(a.equals(b));
116 		}
117 
118 
119 		@Test
120 		void notEqualToNullObject()
121 		{
122 			Object b = null;
123 			assertFalse(a.equals(b));
124 		}
125 
126 
127 		@Test
128 		void notSameAsNullObject()
129 		{
130 			TestManifestBuilder b = null;
131 			assertFalse(a.same(b));
132 		}
133 	}
134 
135 	@Nested
136 	class Properties {
137 
138 		@Test
139 		void mainAttribute()
140 		{
141 
142 			ManifestInfo info = new TestManifestBuilder()
143 					.manifestMain(attribute(IMPLEMENTATION_TITLE, "Imps"));
144 
145 			assertThat(info.mainAttribute(IMPLEMENTATION_TITLE.toString()), is(equalTo("Imps")));
146 		}
147 
148 
149 		@Test
150 		void namedEntry()
151 		{
152 
153 			ManifestInfo info = new TestManifestBuilder()
154 					.manifestNamed(entry("com.acme.SomeThing").attribute("XYZ-Digest", "xyz=="));
155 
156 			assertThat(info.namedEntry("com.acme.SomeThing"), hasEntry(new Attributes.Name("XYZ-Digest"), "xyz=="));
157 		}
158 	}
159 
160 
161 	@Test
162 	void hookInvokedWhenToManifest()
163 	{
164 		TestManifestBuilder builder = new TestManifestBuilder();
165 
166 		builder.mergeFrom(createManifest()).toManifest();
167 
168 		assertThat(builder.hookWasInvoked, is(true));
169 	}
170 
171 
172 	@Test
173 	void hookInvokedWhenToOutputStream()
174 	{
175 		TestManifestBuilder builder = new TestManifestBuilder();
176 
177 		builder.mergeFrom(createManifest()).to(new ByteArrayOutputStream());
178 
179 		assertThat(builder.hookWasInvoked, is(true));
180 	}
181 
182 
183 	@Test
184 	void symmetricFromTo()
185 	{
186 		Manifest manifest = createManifest();
187 
188 		TestManifestBuilder builder = new TestManifestBuilder();
189 
190 		Manifest rehydrated = builder.mergeFrom(manifest).toManifest();
191 
192 		assertThat(rehydrated, is(equalTo(manifest)));
193 	}
194 
195 
196 	private Manifest createManifest()
197 	{
198 		Manifest manifest = new Manifest();
199 		Attributes main = manifest.getMainAttributes();
200 		main.put(Attributes.Name.IMPLEMENTATION_TITLE, "A test");
201 		main.put(Attributes.Name.MANIFEST_VERSION, "1.0");
202 		Attributes attributes = new Attributes();
203 		attributes.putValue("aka", "anon");
204 		manifest.getEntries().put("nom.de.plume", attributes);
205 		return manifest;
206 	}
207 
208 
209 	@Test
210 	void symmetricFromToOutputStream()
211 	{
212 		Manifest manifest = createManifest();
213 
214 		TestManifestBuilder builder = new TestManifestBuilder();
215 
216 		ByteArrayOutputStream noCloseOut = new ByteArrayOutputStream() {
217 			@Override
218 			public void close() throws IOException
219 			{
220 				throw new IOException("open 24/7, 365");
221 			}
222 		};
223 		builder.mergeFrom(manifest).to(noCloseOut);
224 
225 		ByteArrayInputStream in = new ByteArrayInputStream(noCloseOut.toByteArray());
226 		Manifest rehydrated = Closing.closeAfterApplying(in, Manifest::new);
227 
228 		assertThat(rehydrated, is(equalTo(manifest)));
229 	}
230 
231 
232 	@Test
233 	void unhook()
234 	{
235 		Manifest manifest = createManifest();
236 
237 		TestManifestBuilder builder = new TestManifestBuilder();
238 		builder.mergeFrom(manifest).to(new ByteArrayOutputStream());
239 
240 		assertThat(builder.hooked, is(true));
241 		builder.unhook();
242 		assertThat(builder.hooked, is(false));
243 	}
244 }