3535import java .nio .charset .StandardCharsets ;
3636import java .nio .file .Files ;
3737import java .nio .file .Path ;
38+ import java .util .Arrays ;
39+ import java .util .List ;
3840
3941public class BlenderSetupUtils
4042{
4143
4244 public static boolean verifyBlenderBinary ( Path blenderPath )
4345 {
44- try {
45- String output = runPythonWithinBlender ( blenderPath ,
46- "print('Blender started from within Mastodon.')" );
47- return output .contains ( "Blender started from within Mastodon." );
46+ try
47+ {
48+ String expectOutput = "Blender started from within Mastodon." ;
49+ String python = "print('" + expectOutput + "')" ;
50+ return runPythonWithinBlender ( blenderPath , python , expectOutput );
4851 }
4952 catch ( Throwable e ) {
5053 return false ;
@@ -58,32 +61,43 @@ public static void installAddon( Path blenderPath ) throws IOException
5861 Path pythonScript = tmpDir .resolve ( "install_addon.py" );
5962 FileUtils .copyURLToFile ( BlenderSetupUtils .class .getResource ( "/mastodon_blender_view.zip" ), addonZip .toFile () );
6063 FileUtils .copyURLToFile ( BlenderSetupUtils .class .getResource ( "/blender-scripts/install_addon.py" ), pythonScript .toFile () );
61- String output = runCommandGetOutput ( blenderPath .toString (), //
64+ Result result = runCommand ( blenderPath .toString (), //
6265 "--background" , //
6366 "--python" , pythonScript .toAbsolutePath ().toString (), //
6467 "--" , addonZip .toAbsolutePath ().toString () ); //
65- if ( !output .contains ( "dependencies installed" ) )
66- throw new RuntimeException ( "Installation of the dependencies for the mastodon_blender_view addon failed:\n " + output );
67- if ( !output .contains ( "mastodon blender view addon installed" ) )
68- throw new RuntimeException ( "Installation of the mastodon_blender_view addon failed:\n " + output );
69- if ( !output .contains ( "google RPC code compiled" ))
70- throw new RuntimeException ( "Installation of the mastodon_blender_view addon failed:\n " + output );
68+
69+ if ( result .exitCode != 0 )
70+ throw new RuntimeException ( "Installation failed.\n \n " + result );
71+
72+ if ( !result .stdout .contains ( "dependencies installed" ) )
73+ throw new RuntimeException ( "Installation of the dependencies for the mastodon_blender_view addon failed:\n \n " + result );
74+
75+ if ( !result .stdout .contains ( "mastodon blender view addon installed" ) )
76+ throw new RuntimeException ( "Installation of the mastodon_blender_view addon failed:\n \n " + result );
77+
78+ if ( !result .stdout .contains ( "google RPC code compiled" ) )
79+ throw new RuntimeException ( "Installation of the mastodon_blender_view addon failed:\n \n " + result );
80+
7181 Files .delete ( pythonScript );
7282 Files .delete ( addonZip );
7383 Files .delete ( tmpDir );
7484 }
7585
7686 public static void uninstallAddon ( Path blenderPath )
7787 {
78- String python = "import bpy; bpy.ops.preferences.addon_remove(module='mastodon_blender_view')" ;
79- String output = runPythonWithinBlender ( blenderPath , python );
88+ String python = "import bpy; " + //
89+ "bpy.ops.preferences.addon_remove(module='mastodon_blender_view'); " + //
90+ "print('uninstall completed');" ;
91+ runPythonWithinBlender ( blenderPath , python , "uninstall completed" );
8092 }
8193
8294 public static boolean isMastodonAddonInstalled ( Path blenderPath )
8395 {
84- String python = "import addon_utils; print([module.__name__ for module in addon_utils.modules()])" ;
85- String output = runPythonWithinBlender ( blenderPath , python );
86- return output .contains ( "'mastodon_blender_view'" );
96+ String python = "import addon_utils; " + //
97+ "print([module.__name__ for module in addon_utils.modules()])" ;
98+ String expectedOutput = "'mastodon_blender_view'" ;
99+ boolean success = runPythonWithinBlender ( blenderPath , python , expectedOutput );
100+ return success ;
87101 }
88102
89103 public static void runAddonTest ( Path blenderPath )
@@ -106,24 +120,67 @@ public static void runAddonTest( Path blenderPath )
106120 process .waitFor ();
107121 }
108122
109- private static String runPythonWithinBlender ( Path blenderPath , String python )
123+ private static boolean runPythonWithinBlender ( Path blenderPath , String python , String expectedOutput )
110124 {
111- return runCommandGetOutput ( blenderPath .toString (), "--background" , "--python-expr" , python );
125+ Result result = runCommand ( blenderPath .toString (), "--background" , "--python-expr" , python );
126+ return result .exitCode == 0 && result .stdout .contains ( expectedOutput );
112127 }
113128
114- private static String runCommandGetOutput ( String ... command )
129+ private static Result runCommand ( String ... command )
115130 {
116131 try
117132 {
118133 Process process = new ProcessBuilder ( command ).start ();
119- String output = IOUtils .toString ( process .getInputStream (), StandardCharsets .UTF_8 );
120134 process .waitFor ();
121- return output ;
135+ String output = IOUtils .toString ( process .getInputStream (), StandardCharsets .UTF_8 );
136+ String error = IOUtils .toString ( process .getErrorStream (), StandardCharsets .UTF_8 );
137+ int exitCode = process .exitValue ();
138+ return new Result ( Arrays .asList ( command ), output , error , exitCode );
122139 }
123140 catch ( IOException | InterruptedException e )
124141 {
125142 throw new RuntimeException ( e );
126143 }
127144 }
128145
146+ public static class Result
147+ {
148+
149+ private final List < String > command ;
150+
151+ private final String stdout ;
152+
153+ private final String stderr ;
154+
155+ private final int exitCode ;
156+
157+ public Result ( List < String > command , String stdout , String stderr ,
158+ int exitCode )
159+ {
160+ this .command = command ;
161+ this .stdout = stdout ;
162+ this .stderr = stderr ;
163+ this .exitCode = exitCode ;
164+ }
165+
166+ @ Override
167+ public String toString ()
168+ {
169+ final StringBuilder s = new StringBuilder ();
170+ s .append ( "Command:\n " ).append ( command .get ( 0 ) );
171+ for ( int i = 1 ; i < command .size (); i ++ )
172+ s .append ( " " ).append ( addQuotes ( command .get ( i ) ) );
173+ s .append ( "\n \n " );
174+ s .append ( "Exit Code:\n " ).append ( exitCode ).append ("\n \n " );
175+ s .append ( "Command Output:\n \n " ).append ( stdout ).append ("\n \n " );
176+ s .append ( "Command Error:\n \n " ).append ( stderr ).append ("\n \n " );
177+ return s .toString ();
178+ }
179+
180+ static String addQuotes (String value )
181+ {
182+ boolean simple = value .matches ("[a-zA-Z0-9_-]+" );
183+ return simple ? value : "'" + value + "'" ;
184+ }
185+ }
129186}
0 commit comments