├── .gitignore ├── .idea └── vcs.xml ├── Dependencies Programming Test.pdf ├── README.md ├── pom.xml └── src ├── main ├── java │ └── org │ │ └── bongiorno │ │ └── interviews │ │ └── salesforce │ │ ├── Jumpstart.java │ │ ├── commands │ │ ├── Command.java │ │ ├── DependCommand.java │ │ ├── InstallCommand.java │ │ ├── ListCommand.java │ │ └── RemoveCommand.java │ │ └── dependency │ │ └── Module.java └── resources │ └── commands.dat └── test ├── java └── org │ └── bongiorno │ └── interviews │ └── salesforce │ └── CommandTest.java └── resources ├── expected.dat └── testing.dat /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | 3 | ### JetBrains template 4 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio 5 | 6 | *.iml 7 | 8 | ## Directory-based project format: 9 | .idea/ 10 | # if you remove the above rule, at least ignore the following: 11 | 12 | # User-specific stuff: 13 | # .idea/workspace.xml 14 | # .idea/tasks.xml 15 | # .idea/dictionaries 16 | 17 | # Sensitive or high-churn files: 18 | # .idea/dataSources.ids 19 | # .idea/dataSources.xml 20 | # .idea/sqlDataSources.xml 21 | # .idea/dynamic.xml 22 | # .idea/uiDesigner.xml 23 | 24 | # Gradle: 25 | # .idea/gradle.xml 26 | # .idea/libraries 27 | 28 | # Mongo Explorer plugin: 29 | # .idea/mongoSettings.xml 30 | 31 | ## File-based project format: 32 | *.ipr 33 | *.iws 34 | 35 | ## Plugin-specific files: 36 | 37 | # IntelliJ 38 | /out/ 39 | 40 | # mpeltonen/sbt-idea plugin 41 | .idea_modules/ 42 | 43 | # JIRA plugin 44 | atlassian-ide-plugin.xml 45 | 46 | # Crashlytics plugin (for Android Studio and IntelliJ) 47 | com_crashlytics_export_strings.xml 48 | crashlytics.properties 49 | crashlytics-build.properties 50 | 51 | # Created by .ignore support plugin (hsz.mobi) 52 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Dependencies Programming Test.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chb0github/salesforce/54a29c8f004ca72bc88dd8059a354bc6742b610e/Dependencies Programming Test.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | *SALESFORCE PROGRAMMING TEST* 2 | 3 | Congratulations. You are a strong candidate and we would like to see what you can do. You 4 | have two hours 5 | rs from the time you receive th 6 | this test to complete and return it, based on emailtime stamps. 7 | 8 | This challenge contains a problem description and some requirements for the implementation. 9 | Please read the description and requirements carefully. Here’s how your solution will be 10 | evaluated, 11 | ed, in priority order (1 is highest priority) 12 | priority): 13 | 1. Does the program have your name included in a comment? 14 | 2. Does the program compile and execute according to the problem description? 15 | 3. Does the program exhibit good design techniques? 16 | 4. Do you use data structures and algorithms that would allow your program to work 17 | under high volume – that is, is your code scalable? 18 | 5. Is your code well formatted and easy to read? Do you have sufficient comments? Can 19 | the reviewer quickly determine how your program is organized and what you are trying 20 | to accomplish by each class / method? 21 | 6. Have you thoroughly tested all possible input combinations? 22 | Please write your code in Python, Ruby, Perl, BASH, C/C++, or Java. 23 | Thanks and good luck! 24 | 25 | Problem Description: Package Installation and System Dependencies 26 | Dependencies between software packages are common in any Unix/Linux system. This means 27 | that to install a given software package 28 | package, another package must be installed beforehand. 29 | Additionally lower level software components are often required by multiple upper level 30 | packages. For example, both the telnet client program and the ftp client program require that 31 | the TCP/IP networking package.. Conversely, the TCP/IP p 32 | package 33 | ackage cannot be removed until all 34 | packages that depend on it (telnet 35 | telnet, ftp) are removed. 36 | We want you to design and write a program to automate the process of adding and removing 37 | software packages. To do this you will need to: 38 | 39 | 1 40 | Salesforce.com 41 | 42 | 1. Maintain a record of installed packages and their dependencies. 43 | 2. Support explicitly installing a package in response to a command (unless it is already 44 | installed). 45 | 3. Support implicitly installing a package if it is needed to install another package. 46 | 4. Support explicitly removing a package in response to a command (if it is not needed to 47 | support other packages). 48 | 5. Support implicitly removing a package if it is no longer needed to support another 49 | component. 50 | 51 | Requirements 52 | • 53 | • 54 | 55 | Before installing a package, automatically install all the packages it requires. 56 | Before removing a package, confirm that no other packages require it. Dependent 57 | packages must be removed manually before the package can be removed. 58 | 59 | Input 60 | The input received by your program will contain a sequence of commands, each on a separate 61 | line, containing no more than eighty characters. The command names (DEPEND, INSTALL, 62 | REMOVE, and LIST) always appear in uppercase starting in column one and the command line 63 | separator is one or more spaces. All appropriate DEPEND commands will appear before the 64 | occurrence of any INSTALL dependencies. The end of the input is marked by a line containing 65 | only the word END. 66 | Command Syntax: 67 | DEPEND item1 item2 68 | [item3] 69 | 70 | Package item1 depends on package item2 (and item3 or any 71 | additional packages). 72 | 73 | INSTALL item1 74 | 75 | Installs item1 and any other packages required by item1. 76 | 77 | REMOVE item1 78 | 79 | Removes item1 and, if possible, packages required by item1. 80 | 81 | LIST 82 | 83 | Lists the names of all currently installed packages. 84 | 85 | END 86 | 87 | Marks the end of input, when used in a line by itself. 88 | 89 | 2 90 | Salesforce.com 91 | 92 | Output 93 | 1. Echo each line of input. 94 | 2. Follow each echoed INSTALL or REMOVE line with the actions taken in response, 95 | making certain that the actions are given in the proper order. 96 | 3. For the LIST command, display the names of the components currently installed. 97 | 4. For the DEPEND and END commands, no output, except the echo, is produced. 98 | 5. For the DEPEND command, there will only be one dependency list per item. 99 | Sample Input 100 | DEPEND TELNET TCPIP NETCARD 101 | DEPEND TCPIP NETCARD 102 | DEPEND DNS TCPIP NETCARD 103 | DEPEND BROWSER TCPIP HTML 104 | INSTALL NETCARD 105 | INSTALL TELNET 106 | INSTALL foo 107 | REMOVE NETCARD 108 | INSTALL BROWSER 109 | INSTALL DNS 110 | LIST 111 | REMOVE TELNET 112 | REMOVE NETCARD 113 | REMOVE DNS 114 | REMOVE NETCARD 115 | INSTALL NETCARD 116 | REMOVE TCPIP 117 | REMOVE BROWSER 118 | REMOVE TCPIP 119 | LIST 120 | END 121 | Expected Sample Output 122 | DEPEND TELNET TCPIP NETCARD 123 | DEPEND TCPIP NETCARD 124 | DEPEND DNS TCPIP NETCARD 125 | DEPEND BROWSER TCPIP HTML 126 | INSTALL NETCARD 127 | NETCARD successfully installed 128 | INSTALL TELNET 129 | TCPIP successfully installed 130 | TELNET successfully installed 131 | INSTALL foo 132 | foo successfully installed 133 | REMOVE NETCARD 134 | 135 | 3 136 | Salesforce.com 137 | 138 | NETCARD is still needed. 139 | INSTALL BROWSER 140 | HTML successfully installed 141 | BROWSER successfully installed 142 | INSTALL DNS 143 | DNS successfully installed 144 | LIST 145 | HTML 146 | BROWSER 147 | DNS 148 | NETCARD 149 | foo 150 | TCPIP 151 | TELNET 152 | REMOVE TELNET 153 | TELNET successfully removed 154 | REMOVE NETCARD 155 | NETCARD is still needed 156 | REMOVE DNS 157 | DNS successfully removed 158 | REMOVE NETCARD 159 | NETCARD is still needed 160 | INSTALL NETCARD 161 | NETCARD is already installed 162 | REMOVE TCPIP 163 | TCPIP is still needed 164 | REMOVE BROWSER 165 | BROWSER successfully removed 166 | HTML is no longer needed 167 | HTML successfully removed 168 | TCPIP is no longer needed 169 | TCPIP successfully removed 170 | REMOVE TCPIP 171 | TCPIP is not installed 172 | LIST 173 | NETCARD 174 | foo 175 | END 176 | 177 | 4 178 | Salesforce.com 179 | 180 | 181 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | org.bongiorno.interviews 8 | salesforce 9 | 1.0.0-SNAPSHOT 10 | jar 11 | 12 | Salesforce programming challenge 13 | Programming challenge requested by Salesforce 14 | https://github.com/chb0github/salesforce 15 | 16 | 17 | 18 | The Apache Software License, Version 2.0 19 | http://www.apache.org/licenses/LICENSE-2.0.txt 20 | repo 21 | 22 | 23 | 24 | 25 | 26 | cbongiorno 27 | Christian Bongiorno 28 | christian@bongiorno.org 29 | 30 | 31 | 32 | 33 | scm:git:git@github.com:chb0github/salesforce.git 34 | https://github.com/chb0github/salesforce/ 35 | 36 | 37 | 38 | 39 | 40 | junit 41 | junit 42 | 4.12 43 | test 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | org.apache.maven.plugins 52 | maven-compiler-plugin 53 | 3.1 54 | 55 | 1.8 56 | 1.8 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /src/main/java/org/bongiorno/interviews/salesforce/Jumpstart.java: -------------------------------------------------------------------------------- 1 | package org.bongiorno.interviews.salesforce; 2 | 3 | import org.bongiorno.interviews.salesforce.commands.*; 4 | import org.bongiorno.interviews.salesforce.dependency.Module; 5 | 6 | import java.io.*; 7 | import java.util.*; 8 | 9 | /* 10 | * main.Jumpstart 11 | */ 12 | 13 | /** 14 | * Class which will read input from the console, and call the appropriate 15 | * command. 16 | * 17 | * @author interview 18 | */ 19 | public class Jumpstart { 20 | 21 | /** 22 | * Input stream for commands 23 | */ 24 | private BufferedReader _input; 25 | 26 | /** 27 | * Output stream for results 28 | */ 29 | private PrintStream _output; 30 | 31 | private static Map COMMANDS = new HashMap<>(); 32 | 33 | static { 34 | 35 | COMMANDS.put("DEPEND", new DependCommand()); 36 | COMMANDS.put("INSTALL", new InstallCommand()); 37 | COMMANDS.put("REMOVE", new RemoveCommand()); 38 | COMMANDS.put("LIST", new ListCommand()); 39 | } 40 | 41 | /** 42 | * Runs the parser on the supplied test data set. Expects a file in the 43 | * current working directory. Output is sent to stdout 44 | * 45 | * @param args not used 46 | */ 47 | public static void main(String[] args) throws Exception { 48 | 49 | InputStream in = null; 50 | try { 51 | if (args.length > 0 && args[0] != null) 52 | in = new FileInputStream(args[0]); 53 | } catch (FileNotFoundException e) { 54 | in = Jumpstart.class.getResourceAsStream("/commands.dat"); 55 | } 56 | if(in == null) 57 | throw new IllegalArgumentException("no input file found"); 58 | 59 | Jumpstart parser = new Jumpstart(in, System.out); 60 | parser.process(); 61 | } 62 | 63 | /** 64 | * Creates a new CommandParser, sending input and output to the specified 65 | * locations 66 | * 67 | * @param in input stream for commmands 68 | * @param out output stream for results 69 | */ 70 | public Jumpstart(InputStream in, PrintStream out) { 71 | _input = new BufferedReader(new InputStreamReader(in)); 72 | _output = out; 73 | 74 | } 75 | 76 | /** 77 | * Processes a command from user. invalid commands are not printed, and 78 | * silently ignored. An invalid command includes a command which is missing 79 | * its argument. For example: "mkdir " is invalid. 80 | * 81 | * @param line line of text representing the command string 82 | */ 83 | public void processLine(String line) { 84 | String[] arguments = line.split("[ ]+"); 85 | Command cmd = COMMANDS.get(arguments[0]); 86 | if (cmd == null) 87 | throw new IllegalArgumentException("Unknown command " + line); 88 | 89 | _output.println(line); 90 | List args = new LinkedList(Arrays.asList(arguments)); 91 | args.remove(0); // ditch the command piece 92 | Map success = cmd.execute(args); 93 | success.entrySet().stream().forEach(e -> _output.println("\t" + e.getKey() + " " + e.getValue())); 94 | } 95 | 96 | /** 97 | * Reads all commands from the input, and executes them 98 | * 99 | * @throws IOException if a read error occurs while parsing commands 100 | */ 101 | public void process() throws IOException { 102 | String line = _input.readLine(); 103 | while (line != null && line.length() > 0) { 104 | if (line.equals("END")) { 105 | _output.println(line); 106 | break; 107 | 108 | } 109 | processLine(line); 110 | line = _input.readLine(); 111 | } 112 | } 113 | 114 | } -------------------------------------------------------------------------------- /src/main/java/org/bongiorno/interviews/salesforce/commands/Command.java: -------------------------------------------------------------------------------- 1 | package org.bongiorno.interviews.salesforce.commands; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | 6 | /** 7 | * Created by IntelliJ IDEA. 8 | * User: christian 9 | */ 10 | public interface Command { 11 | 12 | Map execute(List args); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/bongiorno/interviews/salesforce/commands/DependCommand.java: -------------------------------------------------------------------------------- 1 | package org.bongiorno.interviews.salesforce.commands; 2 | 3 | 4 | import org.bongiorno.interviews.salesforce.dependency.Module; 5 | 6 | import java.util.Collections; 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | /** 11 | * Created by IntelliJ IDEA. 12 | * User: christian 13 | */ 14 | public class DependCommand implements Command { 15 | 16 | 17 | @Override 18 | public Map execute(List args) { 19 | String depName = args.get(0); 20 | 21 | Module current = Module.getInstance(depName); 22 | 23 | for (String strDependency : args.subList(1, args.size())) { 24 | Module dependency = Module.getInstance(strDependency); 25 | current.addDependency(dependency); 26 | dependency.addDependent(current); 27 | } 28 | return Collections.emptyMap(); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/bongiorno/interviews/salesforce/commands/InstallCommand.java: -------------------------------------------------------------------------------- 1 | package org.bongiorno.interviews.salesforce.commands; 2 | 3 | import org.bongiorno.interviews.salesforce.dependency.Module; 4 | 5 | 6 | import java.util.HashMap; 7 | import java.util.LinkedHashMap; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | /** 12 | * Created by IntelliJ IDEA. 13 | * User: christian 14 | * To change this template use File | Settings | File Templates. 15 | */ 16 | public class InstallCommand implements Command { 17 | 18 | @Override 19 | public Map execute(List args) { 20 | Map result = new LinkedHashMap<>(); 21 | for (String depName : args) { 22 | 23 | Module dep = Module.getInstance(depName); 24 | install(dep, result); 25 | } 26 | return result; 27 | } 28 | 29 | private Map install(Module current, Map result) { 30 | if (!current.isInstalled()) { 31 | current.setInstalled(true); 32 | 33 | 34 | for (Module dependency : current.getDependencies()) { 35 | if (!dependency.isInstalled()) { // not entirely necessary 36 | install(dependency, result); 37 | } 38 | 39 | } 40 | result.put(current.getName(), "successfully installed"); 41 | 42 | } 43 | else { 44 | result.put(current.getName(), "is already installed"); 45 | 46 | } 47 | return result; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/bongiorno/interviews/salesforce/commands/ListCommand.java: -------------------------------------------------------------------------------- 1 | package org.bongiorno.interviews.salesforce.commands; 2 | 3 | import org.bongiorno.interviews.salesforce.dependency.Module; 4 | 5 | import java.util.LinkedHashMap; 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | 10 | /** 11 | * Created by IntelliJ IDEA. 12 | * User: christian 13 | */ 14 | public class ListCommand implements Command { 15 | 16 | 17 | @Override 18 | public Map execute(List args) { 19 | Map result = new LinkedHashMap<>(); 20 | Module.getInstalled().forEach(m -> result.put(m.getName(),"")); 21 | return result; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/bongiorno/interviews/salesforce/commands/RemoveCommand.java: -------------------------------------------------------------------------------- 1 | package org.bongiorno.interviews.salesforce.commands; 2 | 3 | import org.bongiorno.interviews.salesforce.dependency.Module; 4 | 5 | import java.util.*; 6 | 7 | import static java.util.stream.Collectors.toSet; 8 | 9 | 10 | /** 11 | * Created by IntelliJ IDEA. 12 | * User: christian 13 | */ 14 | public class RemoveCommand implements Command { 15 | 16 | @Override 17 | public Map execute(List args) { 18 | Module d = Module.getInstance(args.get(0)); 19 | if(d != null) 20 | return uninstall(d); 21 | Map result = new LinkedHashMap<>(); 22 | result.put(args.get(0),"is not installed"); 23 | return result; 24 | } 25 | 26 | private Map uninstall(Module parent) { 27 | Map result = new HashMap<>(); 28 | Set installedDependents = parent.getDependents().stream().filter(Module::isInstalled).collect(toSet()); 29 | if(installedDependents.isEmpty()) { 30 | result.put(parent.getName(),"successfully removed"); 31 | parent.setInstalled(false); 32 | 33 | for (Module dependency : parent.getDependencies()) { 34 | if(dependency.isInstalled()) { 35 | result.putAll(uninstall(dependency)); 36 | } 37 | } 38 | } 39 | else { 40 | 41 | result.put(parent.getName(),"is still needed."); 42 | } 43 | return result; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/org/bongiorno/interviews/salesforce/dependency/Module.java: -------------------------------------------------------------------------------- 1 | package org.bongiorno.interviews.salesforce.dependency; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * Created by IntelliJ IDEA. 7 | * 8 | * @author christian bongiorno 9 | */ 10 | public class Module { 11 | protected static Map dependencyMap = new HashMap(); 12 | 13 | private String name; 14 | private Set dependencies = new HashSet(); 15 | private Set dependents = new HashSet(); 16 | 17 | private boolean installed; 18 | 19 | private Module(String name) { 20 | this.name = name; 21 | } 22 | 23 | 24 | 25 | public static Module getInstance(String name) { 26 | Module target = dependencyMap.get(name); 27 | if (target == null) { 28 | target = new Module(name); 29 | dependencyMap.put(name, target); 30 | } 31 | return target; 32 | } 33 | 34 | public String getName() { 35 | return name; 36 | } 37 | 38 | public boolean isInstalled() { 39 | return installed; 40 | } 41 | 42 | public void setInstalled(boolean installed) { 43 | this.installed = installed; 44 | } 45 | 46 | public Set getDependents() { 47 | return dependents; 48 | } 49 | 50 | public boolean hasDependents() { 51 | return !dependents.isEmpty(); 52 | } 53 | 54 | public boolean hasDependencies() { 55 | return !dependencies.isEmpty(); 56 | } 57 | 58 | public Set getDependencies() { 59 | return dependencies; 60 | } 61 | 62 | public boolean addDependency(Module d) { 63 | return dependencies.add(d); 64 | } 65 | 66 | public boolean addDependent(Module d) { 67 | return dependents.add(d); 68 | } 69 | @Override 70 | public boolean equals(Object o) { 71 | if (this == o) return true; 72 | if (o == null || getClass() != o.getClass()) return false; 73 | 74 | Module that = (Module) o; 75 | 76 | if (name != null ? !name.equals(that.name) : that.name != null) return false; 77 | 78 | return true; 79 | } 80 | 81 | @Override 82 | public String toString() { 83 | return name; 84 | } 85 | 86 | @Override 87 | public int hashCode() { 88 | return name != null ? name.hashCode() : 0; 89 | } 90 | 91 | 92 | public static Collection getAll() { 93 | return dependencyMap.values(); 94 | } 95 | 96 | public static Set getInstalled() { 97 | Set installed = new HashSet(); 98 | for (Module module : dependencyMap.values()) { 99 | if (module.isInstalled()) 100 | installed.add(module); 101 | } 102 | return installed; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/main/resources/commands.dat: -------------------------------------------------------------------------------- 1 | DEPEND TELNET TCPIP NETCARD 2 | DEPEND TCPIP NETCARD 3 | DEPEND DNS TCPIP NETCARD 4 | DEPEND BROWSER TCPIP HTML 5 | INSTALL NETCARD 6 | INSTALL TELNET 7 | INSTALL foo 8 | REMOVE NETCARD 9 | INSTALL BROWSER 10 | INSTALL DNS 11 | LIST 12 | REMOVE TELNET 13 | REMOVE NETCARD 14 | REMOVE DNS 15 | REMOVE NETCARD 16 | INSTALL NETCARD 17 | REMOVE TCPIP 18 | REMOVE BROWSER 19 | REMOVE TCPIP 20 | LIST 21 | END -------------------------------------------------------------------------------- /src/test/java/org/bongiorno/interviews/salesforce/CommandTest.java: -------------------------------------------------------------------------------- 1 | package org.bongiorno.interviews.salesforce; 2 | 3 | import org.bongiorno.interviews.salesforce.dependency.Module; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | import java.io.ByteArrayInputStream; 8 | import java.io.ByteArrayOutputStream; 9 | import java.io.PrintStream; 10 | import java.util.*; 11 | import java.util.concurrent.ExecutionException; 12 | import java.util.stream.Collectors; 13 | 14 | import static java.util.Arrays.*; 15 | import static java.util.stream.Collectors.*; 16 | import static org.bongiorno.interviews.salesforce.dependency.Module.getInstance; 17 | import static org.junit.Assert.assertEquals; 18 | import static org.junit.Assert.assertTrue; 19 | 20 | /** 21 | * User: christian 22 | */ 23 | public class CommandTest { 24 | 25 | @Before 26 | public void reset() { 27 | // Should not be using static. This was a mistake. No time to reverse 28 | Module.getAll().clear(); 29 | } 30 | 31 | @Test 32 | public void testInstall() throws Exception { 33 | String input = "DEPEND TELNET TCPIP NETCARD\n" + 34 | "DEPEND TCPIP NETCARD\n" + 35 | "DEPEND DNS TCPIP NETCARD\n" + 36 | "DEPEND BROWSER TCPIP HTML\n" + 37 | "INSTALL NETCARD\n" + 38 | "INSTALL TELNET\n" + 39 | "INSTALL foo\n" + 40 | "END"; 41 | 42 | Jumpstart app = new Jumpstart(new ByteArrayInputStream(input.getBytes()), new PrintStream(new ByteArrayOutputStream())); 43 | app.process(); 44 | 45 | 46 | Set expected = new HashSet<>(asList(getInstance("NETCARD"), getInstance("TCPIP"), getInstance("TELNET"), getInstance("foo"))); 47 | assertEquals(expected, Module.getInstalled()); 48 | 49 | } 50 | 51 | @Test 52 | public void testListCommand() throws Exception { 53 | 54 | 55 | // essentially tested in remove 56 | } 57 | 58 | @Test 59 | public void testDependCommand() throws Exception { 60 | String input = "DEPEND TELNET TCPIP NETCARD\n" + 61 | "DEPEND TCPIP NETCARD\n" + 62 | "DEPEND DNS TCPIP NETCARD\n" + 63 | "DEPEND BROWSER TCPIP HTML\n" + 64 | "END"; 65 | Jumpstart app = new Jumpstart(new ByteArrayInputStream(input.getBytes()), new PrintStream(new ByteArrayOutputStream())); 66 | app.process(); 67 | 68 | 69 | Module module = getInstance("TELNET"); 70 | 71 | assertEquals(2, module.getDependencies().size()); 72 | assertTrue(module.getDependencies().containsAll(asList(getInstance("TCPIP"), getInstance("NETCARD")))); 73 | 74 | module = getInstance("TCPIP"); 75 | assertEquals(1, module.getDependencies().size()); 76 | assertTrue(module.getDependencies().iterator().next().equals(getInstance("NETCARD"))); 77 | 78 | module = getInstance("NETCARD"); 79 | assertEquals(0, module.getDependencies().size()); 80 | 81 | 82 | module = getInstance("DNS"); 83 | assertEquals(2, module.getDependencies().size()); 84 | assertTrue(module.getDependencies().containsAll(asList(getInstance("TCPIP"), getInstance("NETCARD")))); 85 | 86 | module = getInstance("BROWSER"); 87 | assertEquals(2, module.getDependencies().size()); 88 | assertTrue(module.getDependencies().containsAll(asList(getInstance("TCPIP"), getInstance("HTML")))); 89 | } 90 | 91 | @Test 92 | public void testRemoveCommand() throws Exception { 93 | String input = "DEPEND TELNET TCPIP NETCARD\n" + 94 | "DEPEND TCPIP NETCARD\n" + 95 | "DEPEND DNS TCPIP NETCARD\n" + 96 | "DEPEND BROWSER TCPIP HTML\n" + 97 | "INSTALL NETCARD\n" + 98 | "INSTALL TELNET\n" + 99 | "INSTALL foo\n" + 100 | "REMOVE NETCARD\n" + 101 | "INSTALL BROWSER\n" + 102 | "INSTALL DNS\n" + 103 | "END"; 104 | 105 | Jumpstart app = new Jumpstart(new ByteArrayInputStream(input.getBytes()), new PrintStream(new ByteArrayOutputStream())); 106 | app.process(); 107 | 108 | 109 | List result = Module.getAll().stream().filter(Module::isInstalled).collect(toList()); 110 | assertEquals(7, result.size()); 111 | assertTrue(result.containsAll(asList(getInstance("NETCARD"), getInstance("TCPIP"), getInstance("TELNET"), 112 | getInstance("foo"), getInstance("BROWSER"), getInstance("HTML"), getInstance("DNS")))); 113 | } 114 | 115 | @Test 116 | public void testBigRemoveCommand() throws Exception { 117 | String input = "DEPEND TELNET TCPIP NETCARD\n" + 118 | "DEPEND TCPIP NETCARD\n" + 119 | "DEPEND DNS TCPIP NETCARD\n" + 120 | "DEPEND BROWSER TCPIP HTML\n" + 121 | "INSTALL NETCARD\n" + 122 | "INSTALL TELNET\n" + 123 | "INSTALL foo\n" + 124 | "REMOVE NETCARD\n" + 125 | "INSTALL BROWSER\n" + 126 | "INSTALL DNS\n" + 127 | "LIST\n" + 128 | "REMOVE TELNET\n" + 129 | "REMOVE NETCARD\n" + 130 | "REMOVE DNS\n" + 131 | "REMOVE NETCARD\n" + 132 | "INSTALL NETCARD\n" + 133 | "REMOVE TCPIP\n" + 134 | "REMOVE BROWSER\n" + 135 | "REMOVE TCPIP\n" + 136 | "END"; 137 | Jumpstart app = new Jumpstart(new ByteArrayInputStream(input.getBytes()), new PrintStream(new ByteArrayOutputStream())); 138 | app.process(); 139 | assertEquals(new HashSet<>(asList(getInstance("NETCARD"), getInstance("foo"))), Module.getInstalled()); 140 | } 141 | 142 | @Test 143 | public void testStringOutput() throws Exception { 144 | String input = "DEPEND TELNET TCPIP NETCARD\n" + 145 | "DEPEND TCPIP NETCARD\n" + 146 | "DEPEND DNS TCPIP NETCARD\n" + 147 | "DEPEND BROWSER TCPIP HTML\n" + 148 | "INSTALL NETCARD\n" + 149 | "INSTALL TELNET\n" + 150 | "INSTALL foo\n" + 151 | "REMOVE NETCARD\n" + 152 | "INSTALL BROWSER\n" + 153 | "INSTALL DNS\n" + 154 | "LIST\n" + 155 | "REMOVE TELNET\n" + 156 | "REMOVE NETCARD\n" + 157 | "REMOVE DNS\n" + 158 | "REMOVE NETCARD\n" + 159 | "INSTALL NETCARD\n" + 160 | "REMOVE TCPIP\n" + 161 | "REMOVE BROWSER\n" + 162 | "REMOVE TCPIP\n" + 163 | "LIST\n" + 164 | "END"; 165 | 166 | ByteArrayOutputStream baos = new ByteArrayOutputStream(); 167 | 168 | Jumpstart app = new Jumpstart(new ByteArrayInputStream(input.getBytes()), new PrintStream(baos)); 169 | app.process(); 170 | String result = baos.toString(); 171 | String[] lines = result.split("\n"); 172 | Arrays.stream(lines).forEach(System.out::println); 173 | assertEquals(50, lines.length); 174 | 175 | } 176 | } 177 | 178 | -------------------------------------------------------------------------------- /src/test/resources/expected.dat: -------------------------------------------------------------------------------- 1 | DEPEND TELNET TCPIP NETCARD 2 | DEPEND TCPIP NETCARD 3 | DEPEND DNS TCPIP NETCARD 4 | DEPEND BROWSER TCPIP HTML 5 | INSTALL NETCARD 6 | NETCARD successfully installed 7 | INSTALL TELNET 8 | TCPIP successfully installed 9 | TELNET successfully installed 10 | INSTALL foo 11 | foo successfully installed 12 | REMOVE NETCARD 13 | NETCARD is still needed. 14 | INSTALL BROWSER 15 | HTML successfully installed 16 | BROWSER successfully installed 17 | INSTALL DNS 18 | DNS successfully installed 19 | LIST 20 | HTML 21 | BROWSER 22 | DNS 23 | NETCARD 24 | foo 25 | TCPIP 26 | TELNET 27 | REMOVE TELNET 28 | TELNET successfully removed 29 | REMOVE NETCARD 30 | NETCARD is still needed 31 | REMOVE DNS 32 | DNS successfully removed 33 | REMOVE NETCARD 34 | NETCARD is still needed 35 | INSTALL NETCARD 36 | NETCARD is already installed 37 | REMOVE TCPIP 38 | TCPIP is still needed 39 | REMOVE BROWSER 40 | BROWSER successfully removed 41 | HTML is no longer needed 42 | HTML successfully removed 43 | TCPIP is no longer needed 44 | TCPIP successfully removed 45 | REMOVE TCPIP 46 | TCPIP is not installed 47 | LIST 48 | NETCARD 49 | foo 50 | END -------------------------------------------------------------------------------- /src/test/resources/testing.dat: -------------------------------------------------------------------------------- 1 | DEPEND TELNET TCPIP NETCARD 2 | DEPEND TCPIP NETCARD 3 | DEPEND DNS TCPIP NETCARD 4 | DEPEND BROWSER TCPIP HTML 5 | INSTALL NETCARD 6 | NETCARD successfully installed 7 | INSTALL TELNET 8 | TCPIP successfully installed 9 | TELNET successfully installed 10 | INSTALL foo 11 | foo successfully installed 12 | REMOVE NETCARD 13 | NETCARD is still needed. 14 | INSTALL BROWSER 15 | HTML successfully installed 16 | BROWSER successfully installed 17 | INSTALL DNS 18 | DNS successfully installed 19 | LIST 20 | BROWSER 21 | TELNET 22 | TCPIP 23 | foo 24 | DNS 25 | HTML 26 | NETCARD 27 | REMOVE TELNET 28 | TELNET successfully removed 29 | REMOVE NETCARD 30 | NETCARD is still needed. 31 | REMOVE DNS 32 | DNS successfully removed 33 | REMOVE NETCARD 34 | NETCARD is still needed. 35 | INSTALL NETCARD 36 | NETCARD is already installed 37 | REMOVE TCPIP 38 | NETCARD is still needed. 39 | TCPIP is still needed. 40 | REMOVE BROWSER 41 | BROWSER successfully removed 42 | REMOVE TCPIP 43 | NETCARD is still needed. 44 | TCPIP is still needed. 45 | LIST 46 | TCPIP 47 | foo 48 | HTML 49 | NETCARD 50 | END 51 | --------------------------------------------------------------------------------