1+ package org .cryptomator .integrations .common ;
2+
3+ import org .junit .jupiter .api .Assertions ;
4+ import org .junit .jupiter .api .BeforeEach ;
5+ import org .junit .jupiter .api .DisplayName ;
6+ import org .junit .jupiter .api .Nested ;
7+ import org .junit .jupiter .api .Test ;
8+ import org .junit .jupiter .api .io .TempDir ;
9+ import org .mockito .Mockito ;
10+
11+ import java .io .ByteArrayInputStream ;
12+ import java .io .IOException ;
13+ import java .net .URL ;
14+ import java .net .URLClassLoader ;
15+ import java .nio .file .Files ;
16+ import java .nio .file .Path ;
17+ import java .util .Arrays ;
18+ import java .util .Comparator ;
19+
20+ public class ClassLoaderFactoryTest {
21+
22+ @ Nested
23+ @ DisplayName ("When two .jars exist in the plugin dir" )
24+ public class WithJars {
25+
26+ private static final byte [] FOO_CONTENTS = "foo = 42" .getBytes ();
27+ private static final byte [] BAR_CONTENTS = "bar = 23" .getBytes ();
28+ private Path pluginDir ;
29+
30+ @ BeforeEach
31+ public void setup (@ TempDir Path tmpDir ) throws IOException {
32+ Files .createDirectory (tmpDir .resolve ("plugin1" ));
33+ try (var out = Files .newOutputStream (tmpDir .resolve ("plugin1/foo.jar" ));
34+ var jar = JarBuilder .withTarget (out )) {
35+ jar .addFile ("foo.properties" , new ByteArrayInputStream (FOO_CONTENTS ));
36+ }
37+
38+ Files .createDirectory (tmpDir .resolve ("plugin2" ));
39+ try (var out = Files .newOutputStream (tmpDir .resolve ("plugin2/bar.jar" ));
40+ var jar = JarBuilder .withTarget (out )) {
41+ jar .addFile ("bar.properties" , new ByteArrayInputStream (BAR_CONTENTS ));
42+ }
43+
44+ this .pluginDir = tmpDir ;
45+ }
46+
47+ @ Test
48+ @ DisplayName ("can load resources from both jars" )
49+ public void testForPluginDirWithPath () throws IOException {
50+ var cl = ClassLoaderFactory .forPluginDirWithPath (pluginDir );
51+ var fooContents = cl .getResourceAsStream ("foo.properties" ).readAllBytes ();
52+ var barContents = cl .getResourceAsStream ("bar.properties" ).readAllBytes ();
53+
54+ Assertions .assertArrayEquals (FOO_CONTENTS , fooContents );
55+ Assertions .assertArrayEquals (BAR_CONTENTS , barContents );
56+ }
57+
58+ @ Test
59+ @ DisplayName ("can load resources when path is set in cryptomator.pluginDir" )
60+ public void testForPluginDirFromSysProp () throws IOException {
61+ System .setProperty ("cryptomator.pluginDir" , pluginDir .toString ());
62+
63+ var cl = ClassLoaderFactory .forPluginDir ();
64+ var fooContents = cl .getResourceAsStream ("foo.properties" ).readAllBytes ();
65+ var barContents = cl .getResourceAsStream ("bar.properties" ).readAllBytes ();
66+
67+ Assertions .assertArrayEquals (FOO_CONTENTS , fooContents );
68+ Assertions .assertArrayEquals (BAR_CONTENTS , barContents );
69+ }
70+ }
71+
72+ @ Test
73+ @ DisplayName ("read path from cryptomator.pluginDir" )
74+ public void testReadPluginDirFromSysProp () {
75+ var ucl = Mockito .mock (URLClassLoader .class , "ucl" );
76+ var absPath = "/there/will/be/plugins" ;
77+ try (var mockedClass = Mockito .mockStatic (ClassLoaderFactory .class )) {
78+ mockedClass .when (() -> ClassLoaderFactory .forPluginDir ()).thenCallRealMethod ();
79+ mockedClass .when (() -> ClassLoaderFactory .forPluginDirWithPath (Path .of (absPath ))).thenReturn (ucl );
80+
81+ System .setProperty ("cryptomator.pluginDir" , absPath );
82+ var result = ClassLoaderFactory .forPluginDir ();
83+
84+ Assertions .assertSame (ucl , result );
85+ }
86+ }
87+
88+ @ Test
89+ @ DisplayName ("read path from cryptomator.pluginDir and replace ~/ with user.home" )
90+ public void testReadPluginDirFromSysPropAndReplaceHome () {
91+ var ucl = Mockito .mock (URLClassLoader .class , "ucl" );
92+ var relPath = "~/there/will/be/plugins" ;
93+ var absPath = Path .of (System .getProperty ("user.home" )).resolve ("there/will/be/plugins" );
94+ try (var mockedClass = Mockito .mockStatic (ClassLoaderFactory .class )) {
95+ mockedClass .when (() -> ClassLoaderFactory .forPluginDir ()).thenCallRealMethod ();
96+ mockedClass .when (() -> ClassLoaderFactory .forPluginDirWithPath (absPath )).thenReturn (ucl );
97+
98+ System .setProperty ("cryptomator.pluginDir" , relPath );
99+ var result = ClassLoaderFactory .forPluginDir ();
100+
101+ Assertions .assertSame (ucl , result );
102+ }
103+ }
104+
105+ @ Test
106+ @ DisplayName ("findJars returns empty list if not containing jars" )
107+ public void testFindJars1 (@ TempDir Path tmpDir ) throws IOException {
108+ Files .createDirectories (tmpDir .resolve ("dir1" ));
109+ Files .createFile (tmpDir .resolve ("file1" ));
110+
111+ var urls = ClassLoaderFactory .findJars (tmpDir );
112+
113+ Assertions .assertArrayEquals (new URL [0 ], urls );
114+ }
115+
116+ @ Test
117+ @ DisplayName ("findJars returns urls of found jars" )
118+ public void testFindJars2 (@ TempDir Path tmpDir ) throws IOException {
119+ Files .createDirectories (tmpDir .resolve ("dir1" ));
120+ Files .createDirectories (tmpDir .resolve ("dir2" ));
121+ Files .createDirectories (tmpDir .resolve ("dir1" ).resolve ("dir2" ));
122+ Files .createFile (tmpDir .resolve ("a.jar" ));
123+ Files .createFile (tmpDir .resolve ("a.txt" ));
124+ Files .createFile (tmpDir .resolve ("dir2" ).resolve ("b.jar" ));
125+
126+ var urls = ClassLoaderFactory .findJars (tmpDir );
127+
128+ Arrays .sort (urls , Comparator .comparing (URL ::toString ));
129+ Assertions .assertArrayEquals (new URL []{
130+ new URL (tmpDir .toUri () + "a.jar" ),
131+ new URL (tmpDir .toUri () + "dir2/b.jar" )
132+ }, urls );
133+ }
134+
135+ }
0 commit comments