View Javadoc
1   package com.atlassian.plugin.manager;
2   
3   import com.atlassian.plugin.Plugin;
4   import com.atlassian.plugin.PluginDependencies;
5   import com.atlassian.plugin.PluginState;
6   import com.google.common.collect.Collections2;
7   import org.junit.Before;
8   
9   import java.util.ArrayList;
10  import java.util.HashSet;
11  import java.util.List;
12  import java.util.Objects;
13  import java.util.Set;
14  
15  import static com.atlassian.plugin.manager.PluginWithDeps.GET_KEY;
16  
17  public class TestDependentPlugins {
18      protected List<Plugin> allPlugins;
19  
20      protected List<SingleAction> pluginActions;
21  
22      @Before
23      public void setUp() throws Exception {
24          pluginActions = new ArrayList<>();
25          final PluginWithDeps.StateChangeListener stateChangeListener = new PluginWithDeps.StateChangeListener() {
26  
27              @Override
28              public void enabled(Plugin plugin) {
29                  pluginActions.add(new SingleAction(plugin.getKey(), PluginState.ENABLED));
30              }
31  
32              @Override
33              public void disabled(Plugin plugin) {
34                  pluginActions.add(new SingleAction(plugin.getKey(), PluginState.DISABLED));
35              }
36  
37              @Override
38              public void uninstalled(Plugin plugin) {
39                  pluginActions.add(new SingleAction(plugin.getKey(), PluginState.UNINSTALLED));
40              }
41          };
42  
43          allPlugins = new ArrayList<>();
44  
45          //  X --- uses --(m - mandatory, etc.) Y
46  
47          // A ---m B ---d C --m G
48          //    \_o D __/o
49          //    \_d E _/m
50  
51          // F ---d B
52          //    \_m D
53          //    \_o E
54  
55          // H ---o B
56          //    \_d D
57          //    \_m E
58  
59          allPlugins.add(new PluginWithDeps("A", stateChangeListener, PluginDependencies.builder()
60                  .withMandatory("B")
61                  .withOptional("D")
62                  .withDynamic("E")
63                  .build()));
64  
65          allPlugins.add(new PluginWithDeps("F", stateChangeListener, PluginDependencies.builder()
66                  .withDynamic("B")
67                  .withMandatory("D")
68                  .withOptional("E")
69                  .build()));
70  
71          allPlugins.add(new PluginWithDeps("H", stateChangeListener, PluginDependencies.builder()
72                  .withOptional("B")
73                  .withDynamic("D")
74                  .withMandatory("E")
75                  .build()));
76  
77          allPlugins.add(new PluginWithDeps("B", stateChangeListener, PluginDependencies.builder()
78                  .withDynamic("C")
79                  .build()));
80  
81          allPlugins.add(new PluginWithDeps("D", stateChangeListener, PluginDependencies.builder()
82                  .withOptional("C")
83                  .build()));
84  
85          allPlugins.add(new PluginWithDeps("E", stateChangeListener, PluginDependencies.builder()
86                  .withMandatory("C")
87                  .build()));
88  
89          allPlugins.add(new PluginWithDeps("C", stateChangeListener, PluginDependencies.builder()
90                  .withMandatory("G")
91                  .build()));
92  
93          allPlugins.add(new PluginWithDeps("G", stateChangeListener, PluginDependencies.builder()
94                  .build()));
95  
96          // circular a -m b -m c -m a
97          allPlugins.add(new PluginWithDeps("a", stateChangeListener, PluginDependencies.builder()
98                  .withMandatory("b")
99                  .build()));
100         allPlugins.add(new PluginWithDeps("b", stateChangeListener, PluginDependencies.builder()
101                 .withMandatory("c")
102                 .build()));
103         allPlugins.add(new PluginWithDeps("c", stateChangeListener, PluginDependencies.builder()
104                 .withMandatory("a")
105                 .build()));
106 
107         // circular AC -o AC
108         //          AC /d
109         //          AC /m
110 
111         allPlugins.add(new PluginWithDeps("aC", stateChangeListener, PluginDependencies.builder()
112                 .withOptional("aC")
113                 .withDynamic("aC")
114                 .withMandatory("aC")
115                 .build()));
116 
117         // Multiple dependency types
118 
119         // mX ---m mA ---m mB ---d mC
120         //             \_o mD __/o
121         //             \_d mE _/m
122 
123         // mA ---d mB
124         //     \_m mD
125         //     \_o mE
126 
127         // mA ---o mB
128         //     \_d mD
129         //     \_m mE
130 
131         allPlugins.add(new PluginWithDeps("mA", stateChangeListener, PluginDependencies.builder()
132                 .withMandatory("mB", "mD", "mE")
133                 .withOptional("mB", "mD", "mE")
134                 .withDynamic("mB", "mD", "mE")
135                 .build()));
136 
137         allPlugins.add(new PluginWithDeps("mB", stateChangeListener, PluginDependencies.builder()
138                 .withDynamic("mC")
139                 .build()));
140 
141         allPlugins.add(new PluginWithDeps("mD", stateChangeListener, PluginDependencies.builder()
142                 .withOptional("mC")
143                 .build()));
144 
145         allPlugins.add(new PluginWithDeps("mE", stateChangeListener, PluginDependencies.builder()
146                 .withMandatory("mC")
147                 .build()));
148 
149         allPlugins.add(new PluginWithDeps("mX", stateChangeListener, PluginDependencies.builder()
150                 .withMandatory("mA")
151                 .build()));
152 
153         allPlugins.add(new PluginWithDeps("mC", stateChangeListener, PluginDependencies.builder()
154                 .withMandatory("mE")
155                 .withOptional("mD")
156                 .withDynamic("mB")
157                 .build()));
158 
159         // k5 ---m k4 ---m k3 ---m k2 ---m k1 ---m k0
160 
161         allPlugins.add(new PluginWithDeps("k5", stateChangeListener, PluginDependencies.builder()
162                 .withMandatory("k4")
163                 .build()));
164 
165         allPlugins.add(new PluginWithDeps("k4", stateChangeListener, PluginDependencies.builder()
166                 .withMandatory("k3")
167                 .build()));
168 
169         allPlugins.add(new PluginWithDeps("k3", stateChangeListener, PluginDependencies.builder()
170                 .withMandatory("k2")
171                 .build()));
172 
173         allPlugins.add(new PluginWithDeps("k2", stateChangeListener, PluginDependencies.builder()
174                 .withMandatory("k1")
175                 .build()));
176 
177         allPlugins.add(new PluginWithDeps("k1", stateChangeListener, PluginDependencies.builder()
178                 .withMandatory("k0")
179                 .build()));
180 
181         allPlugins.add(new PluginWithDeps("k0", stateChangeListener, PluginDependencies.builder()
182                 .build()));
183     }
184 
185     protected Set<String> getKeys(final List<Plugin> plugins) {
186         return new HashSet<>(Collections2.transform(plugins, GET_KEY));
187     }
188 
189     protected static class SingleAction {
190         protected final String plugin;
191         protected final PluginState action;
192 
193         public SingleAction(String plugin, PluginState action) {
194             this.plugin = plugin;
195             this.action = action;
196         }
197 
198         @Override
199         public boolean equals(Object o) {
200             if (this == o) return true;
201             if (o == null || getClass() != o.getClass()) return false;
202             SingleAction that = (SingleAction) o;
203             return action == that.action &&
204                     Objects.equals(plugin, that.plugin);
205         }
206 
207         @Override
208         public int hashCode() {
209             return Objects.hash(plugin, action);
210         }
211 
212         @Override
213         public String toString() {
214             return "{" + action + " " + plugin + "}";
215         }
216     }
217 
218 }