├── .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 |
--------------------------------------------------------------------------------