res = async(()-> {
43 | int x = await(bla1());
44 | int y = await(bla2());
45 | return a + x + y; // no task
46 | });
47 | }
48 |
49 | ```
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/async/async-stub.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/electronicarts/ea-async/18e6f5edd2151bd8e65900dbec2aea36f90dfb1f/async/async-stub.jar
--------------------------------------------------------------------------------
/async/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
29 |
32 | 4.0.0
33 |
34 | com.ea.async
35 | ea-async-parent
36 | 1.2.4-SNAPSHOT
37 | ..
38 |
39 | ea-async
40 | EA Async-Await
41 |
42 |
43 | 7.1
44 |
45 |
46 |
47 |
48 |
49 | org.apache.maven.plugins
50 | maven-compiler-plugin
51 |
52 |
53 | -proc:none
54 |
55 |
56 |
57 | org.apache.maven.plugins
58 | maven-jar-plugin
59 |
60 |
61 | true
62 |
63 | com.ea.async.instrumentation.Premain
64 | com.ea.async.instrumentation.Agent
65 | com.ea.async.instrumentation.Main
66 | true
67 | true
68 |
69 |
70 |
71 |
72 |
73 | maven-shade-plugin
74 |
75 |
76 | package
77 |
78 | shade
79 |
80 |
81 |
82 |
83 | net.bytebuddy:byte-buddy-agent
84 | org.ow2.asm:asm
85 | org.ow2.asm:asm-analysis
86 | org.ow2.asm:asm-util
87 | org.ow2.asm:asm-tree
88 |
89 |
90 |
91 |
92 | org.objectweb.
93 | com.ea.async.shaded.org.objectweb.
94 |
95 |
96 | net.bytebuddy.
97 | com.ea.async.shaded.net.bytebuddy.
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | org.ow2.asm
110 | asm
111 | ${asm.version}
112 |
113 |
114 | org.ow2.asm
115 | asm-util
116 | ${asm.version}
117 |
118 |
119 | org.ow2.asm
120 | asm-analysis
121 | ${asm.version}
122 |
123 |
124 | org.ow2.asm
125 | asm-tree
126 | ${asm.version}
127 |
128 |
129 | org.slf4j
130 | slf4j-api
131 | 1.7.25
132 |
133 |
134 | net.bytebuddy
135 | byte-buddy-agent
136 | 1.9.13
137 |
138 |
139 | org.apache.commons
140 | commons-lang3
141 | 3.7
142 | test
143 |
144 |
145 | junit
146 | junit
147 | test
148 |
149 |
150 | commons-io
151 | commons-io
152 | 2.6
153 | test
154 |
155 |
156 |
157 |
158 |
--------------------------------------------------------------------------------
/async/src/main/java/com/ea/async/Async.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async;
30 |
31 | import com.ea.async.instrumentation.InitializeAsync;
32 |
33 | import org.slf4j.Logger;
34 | import org.slf4j.LoggerFactory;
35 |
36 | import java.util.concurrent.CompletableFuture;
37 | import java.util.concurrent.CompletionStage;
38 |
39 | /**
40 | * This class together with bytecode instrumentation implements the async-await functionality in the JVM.
41 | *
42 | * To use it call Async.await(future)
from within methods whose return type is
43 | * CompletionStage, CompletableFuture or subclasses of CompletableFuture.
44 | *
45 | * Async.await(future)
won't block. It is semantically equivalent to call future.join()
46 | * But instead of blocking the code in instrumented to become a state machine that evolves as the futures passed
47 | * to await
are completed.
48 | *
49 | * This is equivalent to use CompletableFuture composition methods (ex: thenApply, handle, thenCompose).
50 | * The advantage of using await
is that the code will resemble sequential blocking code.
51 | *
52 | * Example:
53 | *
54 | * import static com.ea.async.Async.await;
55 | * import static java.util.concurrent.CompletableFuture.completedFuture;*
56 | *
57 | * public class Store
58 | * {
59 | * public CompletableFuture buyItem(String itemTypeId, int cost)
60 | * {
61 | * if(!await(bank.decrement(cost))) {
62 | * return completedFuture(false);
63 | * }
64 | * await(inventory.giveItem(itemTypeId));
65 | * return completedFuture(true);
66 | * }
67 | * }
68 | *
69 | */
70 | public class Async
71 | {
72 | /**
73 | * Ensure that if no pre instrumentation was done, that the Async runtime instrumentation is running.
74 | *
75 | * Attention! The build time instrumentation will remove calls to this method.
76 | */
77 | public static void init()
78 | {
79 | InitializeAsync.init();
80 | }
81 |
82 | private static Logger logger;
83 |
84 | /**
85 | * This method will behave as a CompletableFuture.join()
but will actually cause the
86 | * caller to return a promise instead of blocking.
87 | *
88 | * Calls to this method are replaced by the EA Async instrumentation.
89 | *
90 | * @param future a future to wait for.
91 | * @param the future value type.
92 | * @return the return value of the future
93 | * @throws java.util.concurrent.CompletionException wrapping the actual exception if an exception occured.
94 | */
95 | public static > T await(F future)
96 | {
97 | String warning;
98 | if (!InitializeAsync.isRunning())
99 | {
100 | warning = "Warning: Illegal call to await, static { Async.init(); } must be added to the main program class and the method invoking await must return a CompletableFuture";
101 | }
102 | else
103 | {
104 | warning = "Warning: Illegal call to await, the method invoking await must return a CompletableFuture";
105 | }
106 | LoggerFactory.getLogger(Async.class);
107 | if (logger == null)
108 | {
109 | logger = LoggerFactory.getLogger(Async.class);
110 | }
111 | if (logger.isDebugEnabled())
112 | {
113 | logger.warn(warning, new Throwable());
114 | }
115 | else
116 | {
117 | logger.warn(warning);
118 | }
119 | if (future instanceof CompletableFuture)
120 | {
121 | //noinspection unchecked
122 | return ((CompletableFuture) future).join();
123 | }
124 | return future.toCompletableFuture().join();
125 | }
126 | }
127 |
--------------------------------------------------------------------------------
/async/src/main/java/com/ea/async/instrumentation/Agent.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.instrumentation;
30 |
31 | import java.lang.instrument.Instrumentation;
32 |
33 | /**
34 | * Class called when a java agent is attached to the jvm in runtime.
35 | */
36 | public class Agent
37 | {
38 | /*
39 | * From https://docs.oracle.com/javase/8/docs/api/index.html?java/lang/instrument/Instrumentation.html
40 | *
41 | * Agent-Class
42 | *
43 | * If an implementation supports a mechanism to start agents sometime
44 | * after the VM has started then this attribute specifies the agent class.
45 | * That is, the class containing the agentmain method. This attribute is
46 | * required, if it is not present the agent will not be started. Note: this
47 | * is a class name, not a file name or path.
48 | */
49 | public static void agentmain(String agentArgs, Instrumentation inst)
50 | {
51 | Transformer transformer = new Transformer();
52 | inst.addTransformer(transformer, true);
53 | f1:
54 | for (Class> clazz : inst.getAllLoadedClasses())
55 | {
56 | if (inst.isModifiableClass(clazz)
57 | && !clazz.getName().startsWith("java.")
58 | && !clazz.getName().startsWith("javax.")
59 | && !clazz.getName().startsWith("sun."))
60 | {
61 | try
62 | {
63 | if (transformer.needsInstrumentation(clazz))
64 | {
65 | inst.retransformClasses(clazz);
66 | }
67 | }
68 | catch (Exception | Error e)
69 | {
70 | e.printStackTrace();
71 | }
72 | }
73 | }
74 | System.setProperty(Transformer.EA_ASYNC_RUNNING, "true");
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/async/src/main/java/com/ea/async/instrumentation/Main.java:
--------------------------------------------------------------------------------
1 | package com.ea.async.instrumentation;
2 |
3 |
4 | import org.objectweb.asm.ClassReader;
5 |
6 | import java.io.FileInputStream;
7 | import java.io.IOException;
8 | import java.io.InputStream;
9 | import java.nio.file.Files;
10 | import java.nio.file.Path;
11 | import java.nio.file.Paths;
12 | import java.util.ArrayList;
13 | import java.util.List;
14 |
15 | /**
16 | * Tool class to perform build time instrumentation.
17 | */
18 | public class Main
19 | {
20 | private boolean verbose;
21 | private List fileList;
22 | private Path outputDirectory;
23 | private ClassLoader classLoader = getClass().getClassLoader();
24 |
25 | public static void main(String args[]) throws IOException
26 | {
27 | final int ret = new Main().doMain(args);
28 | if (ret != 0)
29 | {
30 | System.exit(-1);
31 | }
32 | }
33 |
34 | public int doMain(final String[] args) throws IOException
35 | {
36 | outputDirectory = null;
37 |
38 | fileList = new ArrayList<>();
39 | if (args.length == 0)
40 | {
41 | printUsage();
42 | return 0;
43 | }
44 | for (int i = 0; i < args.length; i++)
45 | {
46 | final String arg = args[i];
47 | if ("--help".equals(arg))
48 | {
49 | printUsage();
50 | continue;
51 | }
52 | if ("-verbose".equals(arg))
53 | {
54 | verbose = true;
55 | continue;
56 | }
57 | if ("-d".equals(arg))
58 | {
59 | if (i + 1 == args.length)
60 | {
61 | error("Invalid usage of the -d option");
62 | return 1;
63 | }
64 | outputDirectory = Paths.get(args[++i]);
65 | continue;
66 | }
67 | final Path path = Paths.get(arg);
68 | if (Files.isDirectory(path))
69 | {
70 | Files.walk(path)
71 | .filter(Files::isRegularFile)
72 | .filter(p -> p.toString().endsWith(".class"))
73 | .forEach(fileList::add);
74 | continue;
75 | }
76 | if (Files.isRegularFile(path))
77 | {
78 | fileList.add(path);
79 | continue;
80 | }
81 | error("Invalid argument or file: " + arg);
82 | return 1;
83 | }
84 | return transform() >= 0 ? 0 : 1;
85 | }
86 |
87 | public int transform() throws IOException
88 | {
89 | final Transformer transformer = new Transformer();
90 | transformer.setErrorListener(System.err::println);
91 | boolean error = false;
92 | int count = 0;
93 | final Path outputDir = getOutputDirectory();
94 | for (Path path : fileList)
95 | {
96 | byte[] bytes = null;
97 | try (InputStream in = new FileInputStream(path.toFile()))
98 | {
99 | bytes = transformer.instrument(classLoader, in);
100 | }
101 | catch (Exception e)
102 | {
103 | error("Error instrumenting " + path, e);
104 | error = true;
105 | }
106 | if (bytes != null)
107 | {
108 | if (verbose)
109 | {
110 | info("instrumented: " + path);
111 | }
112 | if (outputDir != null)
113 | {
114 | // writing to the output directory, using the package name as path.
115 | final Path outPath = outputDir.resolve(new ClassReader(bytes).getClassName() + ".class");
116 | final Path outParent = outPath.getParent();
117 | if (!Files.exists(outParent))
118 | {
119 | Files.createDirectories(outParent);
120 | }
121 | Files.write(outPath, bytes);
122 | }
123 | else
124 | {
125 | // replacing the original file
126 | Files.write(path, bytes);
127 | }
128 | count++;
129 | }
130 | }
131 | return error ? -1 : count;
132 | }
133 |
134 | private void error(final String msg, final Exception e)
135 | {
136 | System.err.println(msg);
137 | e.printStackTrace();
138 | }
139 |
140 |
141 | protected void error(String msg)
142 | {
143 | System.err.println(msg);
144 | }
145 |
146 | protected void info(String msg)
147 | {
148 | System.err.println(msg);
149 | }
150 |
151 | protected void printUsage()
152 | {
153 | System.out.println("usage:");
154 | System.out.println(" java -cp project-class-path -jar ea-async.jar -d output-directory file1 input-dir1 input-dir2");
155 | System.out.println("options:");
156 | System.out.println("-d directory");
157 | System.out.println(" Set the destination directory for class files. ");
158 | System.out.println(" If not specified the original files will be modified in place");
159 | System.out.println("-help");
160 | System.out.println(" Shows this help. ");
161 | }
162 |
163 | public boolean isVerbose()
164 | {
165 | return verbose;
166 | }
167 |
168 | public void setVerbose(final boolean verbose)
169 | {
170 | this.verbose = verbose;
171 | }
172 |
173 | public List getFileList()
174 | {
175 | return fileList;
176 | }
177 |
178 | public void setFileList(final List fileList)
179 | {
180 | this.fileList = fileList;
181 | }
182 |
183 | public Path getOutputDirectory()
184 | {
185 | return outputDirectory;
186 | }
187 |
188 | public void setOutputDirectory(final Path outputDirectory)
189 | {
190 | this.outputDirectory = outputDirectory;
191 | }
192 |
193 | public ClassLoader getClassLoader()
194 | {
195 | return classLoader;
196 | }
197 |
198 | public void setClassLoader(final ClassLoader classLoader)
199 | {
200 | this.classLoader = classLoader;
201 | }
202 | }
203 |
--------------------------------------------------------------------------------
/async/src/main/java/com/ea/async/instrumentation/Premain.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.instrumentation;
30 |
31 | import java.lang.instrument.Instrumentation;
32 |
33 | /**
34 | * Class called when the jvm option -javaagent is used with the orbit-async jar.
35 | */
36 | public class Premain
37 | {
38 | /*
39 | * From https://docs.oracle.com/javase/8/docs/api/index.html?java/lang/instrument/Instrumentation.html
40 | *
41 | * Premain-Class
42 | *
43 | * When an agent is specified at JVM launch time this attribute specifies
44 | * the agent class. That is, the class containing the premain method.
45 | * When an agent is specified at JVM launch time this attribute is required.
46 | * If the attribute is not present the JVM will abort. Note: this is a class
47 | * name, not a file name or path.
48 | */
49 | public static void premain(String agentArgs, Instrumentation inst)
50 | {
51 | inst.addTransformer(new Transformer(), true);
52 | System.setProperty(Transformer.EA_ASYNC_RUNNING, "true");
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/async/src/main/resources/com/ea/async/instrumentation/async-stub.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/electronicarts/ea-async/18e6f5edd2151bd8e65900dbec2aea36f90dfb1f/async/src/main/resources/com/ea/async/instrumentation/async-stub.jar
--------------------------------------------------------------------------------
/async/src/test/java/NoPackageAsync.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | import java.util.concurrent.CompletableFuture;
30 |
31 | import static com.ea.async.Async.await;
32 |
33 | public class NoPackageAsync
34 | {
35 |
36 | static String concat(int i, long j, float f, double d, Object obj, boolean b)
37 | {
38 | return i + ":" + j + ":" + f + ":" + d + ":" + obj + ":" + b;
39 | }
40 |
41 | public CompletableFuture noPackageMethod(CompletableFuture blocker, int var)
42 | {
43 | return CompletableFuture.completedFuture(concat(var, 10_000_000_000L, 1.5f, 3.5d, await(blocker), true));
44 | }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/async/src/test/java/com/ea/async/Task.java:
--------------------------------------------------------------------------------
1 | package com.ea.async;
2 |
3 | import java.util.concurrent.CompletableFuture;
4 | import java.util.concurrent.CompletionStage;
5 | import java.util.function.Function;
6 |
7 | public class Task extends CompletableFuture
8 | {
9 | public static Task fromValue(T value)
10 | {
11 | final Task task = new Task<>();
12 | task.complete(value);
13 | return task;
14 | }
15 |
16 | public static Task done()
17 | {
18 | final Task task = new Task<>();
19 | task.complete(null);
20 | return task;
21 | }
22 |
23 | public static Task fromException(final Exception ex)
24 | {
25 | final Task task = new Task<>();
26 | task.completeExceptionally(ex);
27 | return task;
28 | }
29 |
30 | public static Task from(CompletionStage stage)
31 | {
32 | Task a;
33 | if (stage instanceof Task)
34 | {
35 | a = (Task) stage;
36 | }
37 | else
38 | {
39 | final Task t = new Task<>();
40 | stage.whenComplete((T v, Throwable ex) -> {
41 | if (ex != null)
42 | {
43 | t.completeExceptionally(ex);
44 | }
45 | else
46 | {
47 | t.complete(v);
48 | }
49 | });
50 | a = t;
51 | }
52 | return a;
53 | }
54 |
55 |
56 | /**
57 | * Wraps a CompletionStage as a Task or just casts it if it is already a Task.
58 | *
59 | * @param stage the stage to be wrapped or casted to Task
60 | * @return stage cast as Task of a new Task that is dependent on the completion of that stage.
61 | */
62 | public static Task cast(CompletionStage stage)
63 | {
64 | if (stage instanceof Task)
65 | {
66 | return (Task) stage;
67 | }
68 |
69 | final Task t = new Task<>();
70 | stage.whenComplete((T v, Throwable ex) -> {
71 | if (ex != null)
72 | {
73 | t.completeExceptionally(ex);
74 | }
75 | else
76 | {
77 | t.complete(v);
78 | }
79 | });
80 | return t;
81 | }
82 |
83 |
84 | public Task thenCompose(Function super T, ? extends CompletionStage> fn)
85 | {
86 | return Task.from(super.thenCompose(fn));
87 | }
88 |
89 | }
90 |
--------------------------------------------------------------------------------
/async/src/test/java/com/ea/async/instrumentation/ConstantTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.instrumentation;
30 |
31 | import org.junit.Test;
32 |
33 | import static org.junit.Assert.assertEquals;
34 |
35 | public class ConstantTest
36 | {
37 | @Test
38 | public void testSignalingConstant()
39 | {
40 | assertEquals("Signaling constants must match", Transformer.EA_ASYNC_RUNNING, InitializeAsync.EA_ASYNC_RUNNING);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/async/src/test/java/com/ea/async/instrumentation/DevDebug.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.instrumentation;
30 |
31 | import org.objectweb.asm.ClassReader;
32 | import org.objectweb.asm.tree.AbstractInsnNode;
33 | import org.objectweb.asm.tree.ClassNode;
34 | import org.objectweb.asm.tree.MethodNode;
35 | import org.objectweb.asm.tree.analysis.Analyzer;
36 | import org.objectweb.asm.tree.analysis.AnalyzerException;
37 | import org.objectweb.asm.tree.analysis.BasicValue;
38 | import org.objectweb.asm.tree.analysis.Frame;
39 | import org.objectweb.asm.util.Textifier;
40 | import org.objectweb.asm.util.TraceClassVisitor;
41 | import org.objectweb.asm.util.TraceMethodVisitor;
42 |
43 | import java.io.IOException;
44 | import java.io.PrintWriter;
45 | import java.io.StringWriter;
46 | import java.nio.charset.Charset;
47 | import java.nio.file.Files;
48 | import java.nio.file.Path;
49 | import java.nio.file.Paths;
50 |
51 | /**
52 | * For development use only
53 | */
54 | public class DevDebug
55 | {
56 | public static void printMethod(final ClassNode cn, final MethodNode mv)
57 | {
58 | final PrintWriter pw = new PrintWriter(System.out);
59 | pw.println("method " + mv.name + mv.desc);
60 | Textifier p = new Textifier();
61 | final TraceMethodVisitor tv = new TraceMethodVisitor(p);
62 |
63 | try
64 | {
65 | Analyzer analyzer2 = new Analyzer(new FrameAnalyzer.TypeInterpreter());
66 | Frame[] frames2;
67 | try
68 | {
69 | frames2 = analyzer2.analyze(cn.superName, mv);
70 | }
71 | catch (AnalyzerException ex)
72 | {
73 | if (ex.node != null)
74 | {
75 | pw.print("Error at: ");
76 | ex.node.accept(tv);
77 | }
78 | ex.printStackTrace();
79 | frames2 = null;
80 | }
81 | catch (Exception ex)
82 | {
83 | ex.printStackTrace();
84 | frames2 = null;
85 | }
86 |
87 | final AbstractInsnNode[] isns2 = mv.instructions.toArray();
88 |
89 | for (int i = 0; i < isns2.length; i++)
90 | {
91 | Frame frame;
92 | if (frames2 != null && (frame = frames2[i]) != null)
93 | {
94 | p.getText().add("Locals: [ ");
95 | for (int x = 0; x < frame.getLocals(); x++)
96 | {
97 | p.getText().add(String.valueOf(((BasicValue) frame.getLocal(x)).getType()));
98 | p.getText().add(" ");
99 | }
100 | p.getText().add("]\r\n");
101 | p.getText().add("Stack: [ ");
102 | for (int x = 0; x < frame.getStackSize(); x++)
103 | {
104 | p.getText().add(String.valueOf(((BasicValue) frame.getStack(x)).getType()));
105 | p.getText().add(" ");
106 | }
107 | p.getText().add("]\r\n");
108 | }
109 | p.getText().add(i + ": ");
110 | isns2[i].accept(tv);
111 | }
112 | p.print(pw);
113 | pw.println();
114 | pw.flush();
115 | }
116 | catch (Exception ex)
117 | {
118 | ex.printStackTrace();
119 | }
120 | }
121 |
122 |
123 | public static void debugSave(final ClassNode classNode, final byte[] bytes)
124 | {
125 | try
126 | {
127 |
128 | Path path = Paths.get("target/classes2/" + classNode.name + ".class");
129 | Files.createDirectories(path.getParent());
130 | Files.write(path, bytes);
131 | }
132 | catch (IOException e)
133 | {
134 | e.printStackTrace();
135 | }
136 | }
137 |
138 |
139 | public static void debugSaveTrace(String name, final byte[] bytes)
140 | {
141 | try
142 | {
143 | StringWriter sw = new StringWriter();
144 | PrintWriter pw = new PrintWriter(sw);
145 | new ClassReader(bytes).accept(new TraceClassVisitor(pw), 0);
146 | pw.flush();
147 |
148 | Path path = Paths.get("target/classes2/" + name + ".asmtrace");
149 | Files.createDirectories(path.getParent());
150 | Files.write(path, sw.toString().getBytes(Charset.forName("UTF-8")));
151 | System.out.println("Writing file to " + path.toUri());
152 | }
153 | catch (IOException e)
154 | {
155 | e.printStackTrace();
156 | }
157 | }
158 |
159 | public static void debugSaveTrace(String name, ClassNode node)
160 | {
161 | try
162 | {
163 | StringWriter sw = new StringWriter();
164 | PrintWriter pw = new PrintWriter(sw);
165 | node.accept(new TraceClassVisitor(pw));
166 | pw.flush();
167 |
168 | Path path = Paths.get("target/classes2/" + name + ".asmtrace");
169 | Files.createDirectories(path.getParent());
170 | Files.write(path, sw.toString().getBytes(Charset.forName("UTF-8")));
171 | System.out.println("Writing file to " + path.toUri());
172 | }
173 | catch (IOException e)
174 | {
175 | e.printStackTrace();
176 | }
177 | }
178 |
179 | }
180 |
--------------------------------------------------------------------------------
/async/src/test/java/com/ea/async/instrumentation/ErrorReportingTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.instrumentation;
30 |
31 | import com.ea.async.Async;
32 |
33 | import com.ea.async.test.BaseTest;
34 | import com.ea.async.Task;
35 |
36 | import org.junit.Test;
37 | import org.objectweb.asm.ClassReader;
38 | import org.objectweb.asm.tree.analysis.AnalyzerException;
39 |
40 | import java.io.IOException;
41 | import java.lang.reflect.InvocationTargetException;
42 | import java.util.concurrent.atomic.AtomicReference;
43 |
44 | import static org.junit.Assert.*;
45 |
46 | public class ErrorReportingTest extends BaseTest
47 | {
48 | public static class InvalidAwaitCall
49 | {
50 | public void invalidAwaitCall(Task task)
51 | {
52 | Async.await(task);
53 | }
54 | }
55 |
56 | @Test
57 | public void testErrorReporting() throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException, IOException, AnalyzerException
58 | {
59 | ClassReader cr = new ClassReader(InvalidAwaitCall.class.getResourceAsStream(InvalidAwaitCall.class.getName().replaceAll("^.*[.]", "") + ".class"));
60 | assertTrue(mentionsAwait(cr));
61 |
62 | AtomicReference reference = new AtomicReference<>();
63 | final Transformer transformer = new Transformer();
64 | transformer.setErrorListener(t -> reference.set(t));
65 |
66 | final byte[] bytes = transformer.transform(getClass().getClassLoader(), cr);
67 | assertNotNull(reference.get());
68 | assertTrue(reference.get().contains("invalidAwaitCall"));
69 |
70 | ClassReader cr2 = new ClassReader(bytes);
71 | assertFalse(mentionsAwait(cr2));
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/async/src/test/java/com/ea/async/instrumentation/InitRemovalTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.instrumentation;
30 |
31 | import com.ea.async.Async;
32 | import com.ea.async.test.BaseTest;
33 |
34 | import org.junit.Test;
35 | import org.objectweb.asm.ClassReader;
36 | import org.objectweb.asm.tree.analysis.AnalyzerException;
37 |
38 | import java.io.IOException;
39 | import java.lang.reflect.InvocationTargetException;
40 |
41 | import static org.junit.Assert.assertFalse;
42 | import static org.junit.Assert.assertTrue;
43 |
44 | public class InitRemovalTest extends BaseTest
45 | {
46 | public static class StaticUse
47 | {
48 | public static void callInit()
49 | {
50 | Async.init();
51 | }
52 | }
53 |
54 | @Test
55 | public void testAwaitInitRemoval() throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException, IOException, AnalyzerException
56 | {
57 | StaticUse.callInit();
58 | ClassReader cr = new ClassReader(StaticUse.class.getResourceAsStream(StaticUse.class.getName().replaceAll("^.*[.]", "") + ".class"));
59 | assertTrue(mentionsAwait(cr));
60 | final byte[] bytes = new Transformer().transform(getClass().getClassLoader(), cr);
61 | ClassReader cr2 = new ClassReader(bytes);
62 | assertFalse(mentionsAwait(cr2));
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/async/src/test/java/com/ea/async/instrumentation/TransformerMainErrorTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.instrumentation;
30 |
31 | import com.ea.async.test.BaseTest;
32 |
33 | import org.junit.Test;
34 | import org.objectweb.asm.ClassReader;
35 | import org.objectweb.asm.ClassWriter;
36 | import org.objectweb.asm.MethodVisitor;
37 | import org.objectweb.asm.tree.ClassNode;
38 |
39 | import java.io.ByteArrayOutputStream;
40 | import java.io.OutputStreamWriter;
41 | import java.io.PrintStream;
42 | import java.io.StringWriter;
43 | import java.nio.file.Files;
44 | import java.nio.file.Path;
45 | import java.nio.file.Paths;
46 | import java.util.Arrays;
47 |
48 | import static org.junit.Assert.*;
49 | import static org.objectweb.asm.Opcodes.*;
50 |
51 | public class TransformerMainErrorTest extends BaseTest
52 | {
53 |
54 | public static final String COM_EA_ASYNC_TASK = "com/ea/async/Task";
55 |
56 | // sanity check of the creator
57 | @Test
58 | @SuppressWarnings("unchecked")
59 | public void transformerError() throws Exception
60 | {
61 | final ByteArrayOutputStream out = new ByteArrayOutputStream();
62 | final PrintStream printStream = new PrintStream(out);
63 | final PrintStream err = System.err;
64 | System.setErr(printStream);
65 | try
66 | {
67 | final ClassNode cn = createClassNode(Object.class, cw -> {
68 | MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "apply", "(Ljava/lang/Object;)Ljava/lang/Object;", null, new String[]{ "java/lang/Exception" });
69 | mv.visitCode();
70 | mv.visitVarInsn(ALOAD, 1);
71 | mv.visitTypeInsn(CHECKCAST, COM_EA_ASYNC_TASK);
72 | mv.visitMethodInsn(INVOKESTATIC, ASYNC_NAME, "await", "(Ljava/util/concurrent/CompletableFuture;)Ljava/lang/Object;", false);
73 | mv.visitInsn(POP);
74 | mv.visitVarInsn(ALOAD, 1);
75 | mv.visitTypeInsn(CHECKCAST, COM_EA_ASYNC_TASK);
76 | mv.visitInsn(ARETURN);
77 | mv.visitMaxs(1, 2);
78 | mv.visitEnd();
79 | });
80 | ClassWriter cw = new ClassWriter(0);
81 | cn.accept(cw);
82 | final byte[] bytes = new Transformer().transform(getClass().getClassLoader(), new ClassReader(cw.toByteArray()));
83 |
84 | final Main main = new Main();
85 | final Path path = Paths.get("target/transformerError/classes2").resolve(cn.name + ".class");
86 | Files.deleteIfExists(path);
87 | Files.createDirectories(path.getParent());
88 | Files.write(path, cw.toByteArray());
89 |
90 | // still not transformed
91 | final byte[] original = Files.readAllBytes(path);
92 | assertFalse(Arrays.equals(bytes, original));
93 |
94 | final Path path3 = Paths.get("target/transformerError/classes3").resolve(cn.name + ".class");
95 | Files.deleteIfExists(path3);
96 | // in output dir
97 | main.doMain(new String[]{ "-d", "target/transformerError/classes3", path.toString() });
98 | printStream.flush();
99 | assertTrue(new String(out.toByteArray()).startsWith("Invalid use of"));
100 | out.reset();
101 | assertArrayEquals(bytes, Files.readAllBytes(path3));
102 | // still unchanged
103 | assertArrayEquals(original, Files.readAllBytes(path));
104 |
105 | // passing a dir as parameter
106 | final Path path4 = Paths.get("target/transformerError/classes4").resolve(cn.name + ".class");
107 | Files.deleteIfExists(path4);
108 | main.doMain(new String[]{ "-d", "target/transformerError/classes4", path.getParent().toString() });
109 | printStream.flush();
110 | assertTrue(new String(out.toByteArray()).startsWith("Invalid use of"));
111 | out.reset();
112 | assertTrue("Can't find file: " + path4, Files.exists(path4));
113 | assertArrayEquals(bytes, Files.readAllBytes(path4));
114 | // still unchanged
115 | assertArrayEquals(original, Files.readAllBytes(path));
116 |
117 | // in place
118 | main.doMain(new String[]{ path.toString() });
119 | printStream.flush();
120 | assertTrue(new String(out.toByteArray()).startsWith("Invalid use of"));
121 | out.reset();
122 | assertArrayEquals(bytes, Files.readAllBytes(path));
123 | assertFalse(Arrays.equals(original, Files.readAllBytes(path)));
124 | }
125 | finally
126 | {
127 | System.setErr(err);
128 | }
129 |
130 | }
131 |
132 |
133 | }
134 |
--------------------------------------------------------------------------------
/async/src/test/java/com/ea/async/instrumentation/TransformerMainTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.instrumentation;
30 |
31 | import com.ea.async.Task;
32 | import com.ea.async.test.BaseTest;
33 |
34 | import org.junit.Test;
35 | import org.objectweb.asm.ClassReader;
36 | import org.objectweb.asm.ClassWriter;
37 | import org.objectweb.asm.MethodVisitor;
38 | import org.objectweb.asm.tree.ClassNode;
39 |
40 | import java.io.ByteArrayInputStream;
41 | import java.nio.file.Files;
42 | import java.nio.file.Path;
43 | import java.nio.file.Paths;
44 | import java.util.Arrays;
45 |
46 | import static org.junit.Assert.*;
47 | import static org.objectweb.asm.Opcodes.*;
48 |
49 | public class TransformerMainTest extends BaseTest
50 | {
51 |
52 | public static final String COM_EA_ASYNC_TASK = "com/ea/async/Task";
53 |
54 | // sanity check of the creator
55 | @Test
56 | @SuppressWarnings("unchecked")
57 | public void transformer() throws Exception
58 | {
59 | final ClassNode cn = createClassNode(AsyncFunction.class, cw -> {
60 | MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "apply", "(Ljava/lang/Object;)Lcom/ea/async/Task;", null, new String[]{ "java/lang/Exception" });
61 | mv.visitCode();
62 | mv.visitVarInsn(ALOAD, 1);
63 | mv.visitTypeInsn(CHECKCAST, COM_EA_ASYNC_TASK);
64 | mv.visitMethodInsn(INVOKESTATIC, ASYNC_NAME, "await", "(Ljava/util/concurrent/CompletableFuture;)Ljava/lang/Object;", false);
65 | mv.visitInsn(POP);
66 | mv.visitVarInsn(ALOAD, 1);
67 | mv.visitTypeInsn(CHECKCAST, COM_EA_ASYNC_TASK);
68 | mv.visitInsn(ARETURN);
69 | mv.visitMaxs(1, 2);
70 | mv.visitEnd();
71 | });
72 | ClassWriter cw = new ClassWriter(0);
73 | cn.accept(cw);
74 | final byte[] bytes = new Transformer().transform(getClass().getClassLoader(), new ClassReader(cw.toByteArray()));
75 |
76 | final Main main = new Main();
77 | final Path path = Paths.get("target/classes2").resolve(cn.name + ".class");
78 | Files.deleteIfExists(path);
79 | Files.createDirectories(path.getParent());
80 | Files.write(path, cw.toByteArray());
81 |
82 | // still not transformed
83 | final byte[] original = Files.readAllBytes(path);
84 | assertFalse(Arrays.equals(bytes, original));
85 |
86 | final Path path3 = Paths.get("target/classes3").resolve(cn.name + ".class");
87 | Files.deleteIfExists(path3);
88 | // in output dir
89 | main.doMain(new String[]{ "-d", "target/classes3", path.toString() });
90 | assertArrayEquals(bytes, Files.readAllBytes(path3));
91 | // still unchanged
92 | assertArrayEquals(original, Files.readAllBytes(path));
93 |
94 | // passing a dir as parameter
95 | final Path path4 = Paths.get("target/classes4").resolve(cn.name + ".class");
96 | Files.deleteIfExists(path4);
97 | main.doMain(new String[]{ "-d", "target/classes4", path.getParent().toString() });
98 | assertTrue("Can't find file: " + path4, Files.exists(path4));
99 | assertArrayEquals(bytes, Files.readAllBytes(path4));
100 | // still unchanged
101 | assertArrayEquals(original, Files.readAllBytes(path));
102 |
103 | // in place
104 | main.doMain(new String[]{ path.toString() });
105 | assertArrayEquals(bytes, Files.readAllBytes(path));
106 | assertFalse(Arrays.equals(original, Files.readAllBytes(path)));
107 |
108 |
109 | }
110 |
111 |
112 | }
113 |
--------------------------------------------------------------------------------
/async/src/test/java/com/ea/async/instrumentation/TransformerTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.instrumentation;
30 |
31 | import com.ea.async.test.BaseTest;
32 | import com.ea.async.Task;
33 |
34 | import org.junit.Test;
35 | import org.objectweb.asm.ClassReader;
36 | import org.objectweb.asm.ClassWriter;
37 | import org.objectweb.asm.MethodVisitor;
38 | import org.objectweb.asm.tree.ClassNode;
39 |
40 | import static org.junit.Assert.assertEquals;
41 | import static org.objectweb.asm.Opcodes.*;
42 |
43 | public class TransformerTest extends BaseTest
44 | {
45 |
46 | public static final String COM_EA_ASYNC_TASK = "com/ea/async/Task";
47 |
48 | // sanity check of the creator
49 | @Test
50 | @SuppressWarnings("unchecked")
51 | public void simpleAsyncMethod() throws Exception
52 | {
53 | final ClassNode cn = createClassNode(AsyncFunction.class, cw -> {
54 | MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "apply", "(Ljava/lang/Object;)Lcom/ea/async/Task;", null, new String[]{ "java/lang/Exception" });
55 | mv.visitCode();
56 | mv.visitVarInsn(ALOAD, 1);
57 | mv.visitTypeInsn(CHECKCAST, COM_EA_ASYNC_TASK);
58 | mv.visitMethodInsn(INVOKESTATIC, ASYNC_NAME, "await", "(Ljava/util/concurrent/CompletableFuture;)Ljava/lang/Object;", false);
59 | mv.visitInsn(POP);
60 | mv.visitVarInsn(ALOAD, 1);
61 | mv.visitTypeInsn(CHECKCAST, COM_EA_ASYNC_TASK);
62 | mv.visitInsn(ARETURN);
63 | mv.visitMaxs(1, 2);
64 | mv.visitEnd();
65 | });
66 | ClassWriter cw = new ClassWriter(0);
67 | cn.accept(cw);
68 | final byte[] bytes = new Transformer().transform(getClass().getClassLoader(), new ClassReader(cw.toByteArray()));
69 | DevDebug.debugSaveTrace(cn.name, bytes);
70 | assertEquals("hello", createClass(AsyncFunction.class, bytes).apply(Task.fromValue("hello")).join());
71 | }
72 |
73 | @Test
74 | @SuppressWarnings("unchecked")
75 | public void withLocals() throws Exception
76 | {
77 | final ClassNode cn = createClassNode(AsyncFunction.class, cw -> {
78 | MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "apply", "(Ljava/lang/Object;)L"+COM_EA_ASYNC_TASK+";", null, new String[]{ "java/lang/Exception" });
79 | mv.visitCode();
80 | mv.visitIntInsn(SIPUSH, 1);
81 | mv.visitVarInsn(ISTORE, 2);
82 |
83 | mv.visitInsn(LCONST_0);
84 | mv.visitVarInsn(LSTORE, 3);
85 | mv.visitVarInsn(ALOAD, 1);
86 | mv.visitTypeInsn(CHECKCAST, COM_EA_ASYNC_TASK);
87 | mv.visitMethodInsn(INVOKESTATIC, ASYNC_NAME, "await", "(Ljava/util/concurrent/CompletableFuture;)Ljava/lang/Object;", false);
88 | mv.visitInsn(POP);
89 | mv.visitVarInsn(ALOAD, 1);
90 | mv.visitTypeInsn(CHECKCAST, COM_EA_ASYNC_TASK);
91 | mv.visitInsn(ARETURN);
92 | mv.visitMaxs(2, 5);
93 | mv.visitEnd();
94 | });
95 | ClassWriter cw = new ClassWriter(0);
96 | cn.accept(cw);
97 | final byte[] bytes = new Transformer().transform(getClass().getClassLoader(), new ClassReader(cw.toByteArray()));
98 | // DevDebug.debugSaveTrace(cn.name, bytes);
99 | assertEquals("hello", createClass(AsyncFunction.class, bytes).apply(Task.fromValue("hello")).join());
100 | }
101 |
102 |
103 | @Test(timeout = 10_000L)
104 | @SuppressWarnings("unchecked")
105 | public void withTwoFutures() throws Exception
106 | {
107 | final ClassNode cn = createClassNode(AsyncBiFunction.class, cw -> {
108 | MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "apply", "(Ljava/lang/Object;Ljava/lang/Object;)L"+COM_EA_ASYNC_TASK+";", null, new String[]{ "java/lang/Exception" });
109 | mv.visitCode();
110 |
111 | mv.visitVarInsn(ALOAD, 1);
112 | mv.visitTypeInsn(CHECKCAST, COM_EA_ASYNC_TASK);
113 | mv.visitMethodInsn(INVOKESTATIC, ASYNC_NAME, "await", "(Ljava/util/concurrent/CompletableFuture;)Ljava/lang/Object;", false);
114 | mv.visitInsn(POP);
115 |
116 | mv.visitVarInsn(ALOAD, 2);
117 | mv.visitTypeInsn(CHECKCAST, COM_EA_ASYNC_TASK);
118 | mv.visitMethodInsn(INVOKESTATIC, ASYNC_NAME, "await", "(Ljava/util/concurrent/CompletableFuture;)Ljava/lang/Object;", false);
119 | mv.visitInsn(POP);
120 |
121 | mv.visitVarInsn(ALOAD, 1);
122 | mv.visitTypeInsn(CHECKCAST, COM_EA_ASYNC_TASK);
123 | mv.visitInsn(ARETURN);
124 | mv.visitMaxs(2, 5);
125 | mv.visitEnd();
126 | });
127 | ClassWriter cw = new ClassWriter(0);
128 | cn.accept(cw);
129 | final byte[] bytes = new Transformer().transform(getClass().getClassLoader(), new ClassReader(cw.toByteArray()));
130 | DevDebug.debugSaveTrace(cn.name, bytes);
131 |
132 | assertEquals("hello", createClass(AsyncBiFunction.class, bytes).apply(Task.fromValue("hello"), Task.fromValue("world")).join());
133 |
134 | final Task rest = createClass(AsyncBiFunction.class, bytes).apply(getBlockedTask("hello"), getBlockedTask("world"));
135 | completeFutures();
136 | assertEquals("hello", rest.join());
137 | }
138 |
139 | }
140 |
--------------------------------------------------------------------------------
/async/src/test/java/com/ea/async/test/AConstNullTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.test;
30 |
31 | import com.ea.async.Task;
32 |
33 | import org.junit.Test;
34 |
35 | import static com.ea.async.Async.await;
36 | import static org.junit.Assert.assertNull;
37 |
38 | public class AConstNullTest extends BaseTest
39 | {
40 |
41 | @Test
42 | public void nullInitialization() throws Exception
43 | {
44 | final Task res = NullInit.doIt(getBlockedTask());
45 | completeFutures();
46 | assertNull(res.join());
47 |
48 | }
49 |
50 | public static class NullInit
51 | {
52 | public static Task doIt(Task task)
53 | {
54 | String x = null;
55 | try
56 | {
57 | await(task);
58 | return Task.done();
59 | }
60 | catch (Exception ex)
61 | {
62 | return Task.done();
63 | }
64 | }
65 | }
66 |
67 | @Test
68 | public void nullInitialization2() throws Exception
69 | {
70 | final Task res = NullInit2.doIt(getBlockedTask());
71 | completeFutures();
72 | assertNull(res.join());
73 |
74 | }
75 |
76 | public static class NullInit2
77 | {
78 | public static Task doIt(Task task)
79 | {
80 | String x = null;
81 | String y = x;
82 | try
83 | {
84 | await(task);
85 | return Task.done();
86 | }
87 | catch (Exception ex)
88 | {
89 | return Task.done();
90 | }
91 | }
92 | }
93 |
94 | @Test
95 | public void nullInitialization3() throws Exception
96 | {
97 | final Task res = NullInit3.doIt(getBlockedTask());
98 | completeFutures();
99 | assertNull(res.join());
100 |
101 | }
102 |
103 | public static class NullInit3
104 | {
105 | public static Task doIt(Task task)
106 | {
107 | String x = null;
108 | call0(x, await(task));
109 | return Task.done();
110 | }
111 | }
112 |
113 | public static void call0(final Object a, final Object b)
114 | {
115 | }
116 |
117 |
118 | @Test
119 | public void nullInitialization4() throws Exception
120 | {
121 | final Task res = NullInit4.doIt(getBlockedTask());
122 | completeFutures();
123 | assertNull(res.join());
124 |
125 | }
126 |
127 | public static class NullInit4
128 | {
129 | public static Task doIt(Task task)
130 | {
131 | String x = null;
132 | call0(await(task), x);
133 | return Task.done();
134 | }
135 | }
136 |
137 |
138 | @Test
139 | public void nullInTheStack() throws Exception
140 | {
141 | debugTransform(AConstNullTest.class.getName() + "$NullInTheStack");
142 | final Task res = NullInTheStack.doIt(getBlockedTask());
143 | completeFutures();
144 | assertNull(res.join());
145 | }
146 |
147 | public static class NullInTheStack
148 | {
149 | public static Task doIt(Task task)
150 | {
151 | call2(null, await(task));
152 | return Task.done();
153 | }
154 |
155 | private static void call2(final Object o, final Object p)
156 | {
157 | }
158 | }
159 |
160 |
161 | @Test
162 | public void nullInTheStack2() throws Exception
163 | {
164 | debugTransform(AConstNullTest.class.getName() + "$NullInTheStack2");
165 | final Task res = NullInTheStack2.doIt(getBlockedTask());
166 | completeFutures();
167 | assertNull(res.join());
168 | }
169 |
170 | public static class NullInTheStack2
171 | {
172 | public static Task doIt(Task task)
173 | {
174 | call2(null, await(task));
175 | return Task.done();
176 | }
177 | private static void call2(final String o, final Object p)
178 | {
179 | }
180 |
181 | }
182 | }
183 |
--------------------------------------------------------------------------------
/async/src/test/java/com/ea/async/test/ArrayVarsTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.test;
30 |
31 | import com.ea.async.Task;
32 |
33 | import org.junit.Test;
34 |
35 | import static com.ea.async.Async.await;
36 | import static com.ea.async.Task.fromValue;
37 | import static junit.framework.Assert.assertEquals;
38 |
39 | public class ArrayVarsTest extends BaseTest
40 | {
41 | @Test
42 | public void arrayParams01()
43 | {
44 | class Experiment
45 | {
46 | Task doIt(Object params[])
47 | {
48 | await(Task.done());
49 | return fromValue(params[0]);
50 | }
51 | }
52 | assertEquals("x", new Experiment().doIt(new Object[]{"x"}).join());
53 | }
54 |
55 | @Test
56 | public void arrayParams02()
57 | {
58 | class Experiment
59 | {
60 | Task doIt(Object params[][])
61 | {
62 | await(Task.done());
63 | return fromValue(params[0][0]);
64 | }
65 | }
66 | assertEquals("x", new Experiment().doIt(new Object[][]{{"x"}}).join());
67 | }
68 |
69 | @Test
70 | public void arrayParams03()
71 | {
72 | class Experiment
73 | {
74 | Task doIt(Object params[][][])
75 | {
76 | await(Task.done());
77 | return fromValue(params[0][0][0]);
78 | }
79 | }
80 | assertEquals("x", new Experiment().doIt(new Object[][][]{{{"x"}}}).join());
81 | }
82 |
83 | @Test
84 | public void arrayParams04()
85 | {
86 | class Experiment
87 | {
88 | Task doIt(Object params[][][][])
89 | {
90 | await(Task.done());
91 | return fromValue(params[0][0][0][0]);
92 | }
93 | }
94 | assertEquals("x", new Experiment().doIt(new Object[][][][]{{{{"x"}}}}).join());
95 | }
96 |
97 |
98 | @Test
99 | public void optionalParam()
100 | {
101 | class Experiment
102 | {
103 | Task doIt(Object... params)
104 | {
105 | await(Task.done());
106 | return fromValue(params[0]);
107 | }
108 | }
109 | assertEquals("x", new Experiment().doIt(new Object[]{"x"}).join());
110 | }
111 |
112 |
113 | @Test
114 | public void stringArrayParams01()
115 | {
116 | class Experiment
117 | {
118 | Task doIt(String params[])
119 | {
120 | await(Task.done());
121 | return fromValue(params[0]);
122 | }
123 | }
124 | assertEquals("x", new Experiment().doIt(new String[]{"x"}).join());
125 | }
126 |
127 | @Test
128 | public void arrayVar01()
129 | {
130 | class Experiment
131 | {
132 | Task doIt(String x)
133 | {
134 | Object arr[] = new Object[]{x};
135 | await(Task.done());
136 | return fromValue(arr[0]);
137 | }
138 | }
139 | assertEquals("x", new Experiment().doIt("x").join());
140 | }
141 |
142 |
143 | @Test
144 | public void stringVar01()
145 | {
146 | class Experiment
147 | {
148 | Task doIt(String x)
149 | {
150 | String arr[] = new String[]{x};
151 | await(Task.done());
152 | return fromValue(arr[0]);
153 | }
154 | }
155 | assertEquals("x", new Experiment().doIt("x").join());
156 | }
157 |
158 | @Test
159 | public void primitiveArray01()
160 | {
161 | class Experiment
162 | {
163 | Task doIt(int x)
164 | {
165 | int arr[] = new int[]{x};
166 | await(Task.done());
167 | return fromValue(arr[0]);
168 | }
169 | }
170 | assertEquals(10, new Experiment().doIt(10).join());
171 | }
172 |
173 | @Test
174 | public void arraysWithAwait01()
175 | {
176 | class Experiment
177 | {
178 | Task doIt(Object params[])
179 | {
180 | await(getBlockedFuture());
181 | return fromValue(params[0]);
182 | }
183 | }
184 | final Task task = new Experiment().doIt(new Object[]{"x"});
185 | completeFutures();
186 | assertEquals("x", task.join());
187 | }
188 |
189 | @Test
190 | public void arraysWithAwait02()
191 | {
192 | class Experiment
193 | {
194 | Task doIt(Object params[])
195 | {
196 | Object arr[][] = new Object[][]{params};
197 | await(getBlockedFuture());
198 | return fromValue(arr[0][0]);
199 | }
200 | }
201 | final Task task = new Experiment().doIt(new Object[]{"x"});
202 | completeFutures();
203 | assertEquals("x", task.join());
204 | }
205 |
206 |
207 | @Test
208 | public void arraysWithAwait03()
209 | {
210 | class Experiment
211 | {
212 | Task doIt(Object params[])
213 | {
214 | Object arr[][];
215 | if (params != null)
216 | {
217 | arr = new Object[][]{params};
218 | await(getBlockedFuture());
219 | }
220 | else
221 | {
222 | arr = new Object[][]{params, null};
223 | await(getBlockedFuture());
224 | }
225 | return fromValue(arr[0][0]);
226 | }
227 | }
228 | final Task task = new Experiment().doIt(new Object[]{"x"});
229 | completeFutures();
230 | assertEquals("x", task.join());
231 | }
232 |
233 | @Test
234 | public void arraysAndIfs()
235 | {
236 | class Experiment
237 | {
238 | Task doIt(int x)
239 | {
240 | Object[][] arr = new Object[][]{{x}};
241 | if (x == 11)
242 | {
243 | arr = null;
244 | }
245 | // this forces a stack frame map to be created
246 | else
247 | {
248 |
249 | await(getBlockedFuture());
250 | }
251 | return fromValue(arr[0][0]);
252 | }
253 | }
254 | final Task task = new Experiment().doIt(10);
255 | completeFutures();
256 | assertEquals(10, task.join());
257 | }
258 | }
259 |
--------------------------------------------------------------------------------
/async/src/test/java/com/ea/async/test/BaseTestTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.test;
30 |
31 |
32 | import com.ea.async.Task;
33 |
34 | import org.junit.Test;
35 | import org.objectweb.asm.MethodVisitor;
36 |
37 | import java.util.ArrayList;
38 | import java.util.List;
39 | import java.util.concurrent.Callable;
40 |
41 | import static org.junit.Assert.*;
42 | import static org.objectweb.asm.Opcodes.*;
43 |
44 |
45 | public class BaseTestTest extends BaseTest
46 | {
47 |
48 | // sanity check of the creator
49 | @Test
50 | public void testCreateClass() throws Exception
51 | {
52 | assertTrue(createClass(ArrayList.class, cv -> {
53 | }) instanceof List);
54 | assertEquals("hello", createClass(Callable.class, cv -> {
55 | MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "call", "()Ljava/lang/Object;", null, new String[]{ "java/lang/Exception" });
56 | mv.visitCode();
57 | mv.visitLdcInsn("hello");
58 | mv.visitInsn(ARETURN);
59 | mv.visitMaxs(1, 1);
60 | mv.visitEnd();
61 | }).call());
62 | }
63 |
64 |
65 | // sanity check of the creator
66 | @Test
67 | public void simpleAsyncMethod() throws Exception
68 | {
69 | final Task task = createClass(AsyncCallable.class, cw -> {
70 | MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "call", "()Lcom/ea/async/Task;", null, new String[]{ "java/lang/Exception" });
71 | mv.visitCode();
72 | mv.visitMethodInsn(INVOKESTATIC, "com/ea/async/Task", "done", "()Lcom/ea/async/Task;", false);
73 | mv.visitMethodInsn(INVOKESTATIC, ASYNC_NAME, "await", "(Ljava/util/concurrent/CompletableFuture;)Ljava/lang/Object;", false);
74 | mv.visitInsn(POP);
75 | mv.visitMethodInsn(INVOKESTATIC, "com/ea/async/Task", "done", "()Lcom/ea/async/Task;", false);
76 | mv.visitInsn(ARETURN);
77 | mv.visitMaxs(1, 1);
78 | mv.visitEnd();
79 | }).call();
80 | assertTrue(task.isDone());
81 | }
82 |
83 |
84 | // sanity check of the creator
85 | @Test
86 | @SuppressWarnings("unchecked")
87 | public void simpleBlockingAsyncMethod() throws Exception
88 | {
89 | final Task task = createClass(AsyncFunction.class, cw -> {
90 | MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "apply", "(Ljava/lang/Object;)Lcom/ea/async/Task;", null, new String[]{ "java/lang/Exception" });
91 | mv.visitCode();
92 | mv.visitVarInsn(ALOAD, 1);
93 | mv.visitTypeInsn(CHECKCAST, "com/ea/async/Task");
94 | mv.visitMethodInsn(INVOKESTATIC, ASYNC_NAME, "await", "(Ljava/util/concurrent/CompletableFuture;)Ljava/lang/Object;", false);
95 | mv.visitInsn(POP);
96 | mv.visitVarInsn(ALOAD, 1);
97 | mv.visitTypeInsn(CHECKCAST, "com/ea/async/Task");
98 | mv.visitInsn(ARETURN);
99 | mv.visitMaxs(1, 2);
100 | mv.visitEnd();
101 | }).apply(getBlockedTask("hello"));
102 | assertFalse(task.isDone());
103 | completeFutures();
104 | assertEquals("hello", task.join());
105 | }
106 |
107 | }
108 |
--------------------------------------------------------------------------------
/async/src/test/java/com/ea/async/test/BasicInstrTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.test;
30 |
31 | import org.junit.Test;
32 |
33 | import java.lang.reflect.InvocationTargetException;
34 | import java.util.concurrent.CompletableFuture;
35 |
36 | import static com.ea.async.Async.await;
37 | import static org.junit.Assert.assertEquals;
38 |
39 | public class BasicInstrTest extends BaseTest
40 | {
41 | private static class Basic
42 | {
43 |
44 | static String concat(int i, long j, float f, double d, Object obj, boolean b)
45 | {
46 | return i + ":" + j + ":" + f + ":" + d + ":" + obj + ":" + b;
47 | }
48 |
49 | public CompletableFuture doSomething(CompletableFuture blocker, int var)
50 | {
51 | return CompletableFuture.completedFuture(concat(var, 10_000_000_000L, 1.5f, 3.5d, await(blocker), true));
52 | }
53 | }
54 |
55 | @Test
56 | public void testInstrumentation() throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException
57 | {
58 | CompletableFuture blocker = new CompletableFuture<>();
59 | final CompletableFuture res = new Basic().doSomething(blocker, 5);
60 | blocker.complete("zzz");
61 | assertEquals("5:10000000000:1.5:3.5:zzz:true", res.join());
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/async/src/test/java/com/ea/async/test/BasicTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.test;
30 |
31 | import com.ea.async.Async;
32 |
33 | import org.junit.Test;
34 |
35 | import java.util.concurrent.CompletableFuture;
36 |
37 | import static com.ea.async.Async.await;
38 | import static org.junit.Assert.assertEquals;
39 |
40 | public class BasicTest extends BaseTest
41 | {
42 | public static class SomethingAsync
43 | {
44 | public CompletableFuture doSomething(CompletableFuture blocker)
45 | {
46 | String res = await(blocker);
47 | return CompletableFuture.completedFuture(":" + res);
48 | }
49 | }
50 |
51 | public static class SomethingWithDataMutation
52 | {
53 | public CompletableFuture doSomething(CompletableFuture blocker)
54 | {
55 | String op = "1";
56 | String res = "[" + await(blocker) + "]";
57 | op = op + "2";
58 | return CompletableFuture.completedFuture(":" + op + res);
59 | }
60 | }
61 |
62 | public static class SomethingWithLocalsAndStack
63 | {
64 | public CompletableFuture doSomething(CompletableFuture blocker)
65 | {
66 | int local = 7;
67 | String res = ":" + Math.max(local, await(blocker).length());
68 | return CompletableFuture.completedFuture(res);
69 | }
70 | }
71 |
72 | public static class SomethingAsyncWithEx
73 | {
74 | public CompletableFuture doSomething(CompletableFuture blocker)
75 | {
76 | try
77 | {
78 | String res = await(blocker);
79 | return CompletableFuture.completedFuture(":" + res);
80 | }
81 | catch (Exception ex)
82 | {
83 | return CompletableFuture.completedFuture(":" + ex.getCause().getMessage());
84 | }
85 | }
86 | }
87 |
88 | @Test
89 | public void testDirectPathNonBlocking() throws IllegalAccessException, InstantiationException
90 | {
91 | // test an example where the async function blocks (returns incomplete future)
92 | // this would not work without instrumentation
93 | final SomethingAsync a = new SomethingAsync();
94 |
95 | CompletableFuture blocker = CompletableFuture.completedFuture("x");
96 | final CompletableFuture res = a.doSomething(blocker);
97 | assertEquals(":x", res.join());
98 | }
99 |
100 | @Test(timeout = 2_000)
101 | public void testBlocking() throws IllegalAccessException, InstantiationException
102 | {
103 | final SomethingAsync a = new SomethingAsync();
104 | CompletableFuture blocker = new CompletableFuture<>();
105 | final CompletableFuture res = a.doSomething(blocker);
106 | blocker.complete("x");
107 | assertEquals(":x", res.join());
108 | }
109 |
110 |
111 | @Test(timeout = 2_000)
112 | public void testBlockingWithStackAndLocal() throws IllegalAccessException, InstantiationException
113 | {
114 | final SomethingWithLocalsAndStack a = new SomethingWithLocalsAndStack();
115 |
116 | CompletableFuture blocker = new CompletableFuture<>();
117 | final CompletableFuture res = a.doSomething(blocker);
118 | blocker.complete("0123456789");
119 | assertEquals(":10", res.join());
120 | }
121 |
122 | @Test(timeout = 2_000)
123 | public void testBlockingAndException() throws IllegalAccessException, InstantiationException
124 | {
125 | final SomethingAsyncWithEx a = new SomethingAsyncWithEx();
126 |
127 | CompletableFuture blocker = new CompletableFuture<>();
128 | final CompletableFuture res = a.doSomething(blocker);
129 | blocker.completeExceptionally(new RuntimeException("Exception"));
130 | assertEquals(":Exception", res.join());
131 | }
132 |
133 | @Test(timeout = 2_000)
134 | public void testDataFlow()
135 | {
136 | final SomethingWithDataMutation a = new SomethingWithDataMutation();
137 |
138 | CompletableFuture blocker = new CompletableFuture<>();
139 | final CompletableFuture res = a.doSomething(blocker);
140 | blocker.complete("x");
141 | assertEquals(":12[x]", res.join());
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/async/src/test/java/com/ea/async/test/CompletionStageTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.test;
30 |
31 | import org.junit.Test;
32 |
33 | import java.util.concurrent.CompletableFuture;
34 | import java.util.concurrent.CompletionStage;
35 |
36 | import static com.ea.async.Async.await;
37 | import static java.util.concurrent.CompletableFuture.completedFuture;
38 | import static org.junit.Assert.assertEquals;
39 |
40 | public class CompletionStageTest extends BaseTest
41 | {
42 |
43 | @Test
44 | public void outOfTheWay()
45 | {
46 | class Experiment
47 | {
48 |
49 | CompletionStage doIt(int a, int b)
50 | {
51 | await(getBlockedTask());
52 | return CompletableFuture.completedFuture(a + b);
53 | }
54 | }
55 | CompletionStage res = new Experiment().doIt(1, 2);
56 |
57 | completeFutures();
58 | assertEquals(3, (int) res.toCompletableFuture().join());
59 | }
60 |
61 |
62 | @Test
63 | public void completionStageParam()
64 | {
65 | class Experiment
66 | {
67 |
68 | CompletionStage doIt(CompletionStage stage)
69 | {
70 | String result = await(stage);
71 | return completedFuture(result);
72 | }
73 | }
74 | final CompletableFuture future = new CompletableFuture<>();
75 | CompletionStage res = new Experiment().doIt(future);
76 | future.complete("test");
77 | assertEquals("test", res.toCompletableFuture().join());
78 | }
79 |
80 | @Test
81 | public void completionStageArgument() {
82 | class Experiment
83 | {
84 |
85 | CompletionStage doIt(CompletionStage stage, int b) {
86 | int a = await(stage);
87 | return CompletableFuture.completedFuture(a + b);
88 | }
89 | }
90 | CompletionStage task = getBlockedTask(1);
91 | CompletionStage res = new Experiment().doIt(task, 2);
92 |
93 | completeFutures();
94 | assertEquals(3, (int) res.toCompletableFuture().join());
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/async/src/test/java/com/ea/async/test/ExceptionTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.test;
30 |
31 | import com.ea.async.Async;
32 | import com.ea.async.Task;
33 |
34 | import org.junit.Test;
35 |
36 | import java.lang.reflect.InvocationTargetException;
37 |
38 | import static com.ea.async.Async.await;
39 | import static junit.framework.TestCase.assertNull;
40 | import static org.junit.Assert.assertEquals;
41 | import static org.junit.Assert.assertTrue;
42 |
43 | public class ExceptionTest extends BaseTest
44 | {
45 |
46 | @Test
47 | public void testTryCatch() throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException
48 | {
49 | final Task res = doTryCatch();
50 | completeFutures();
51 | assertEquals((Integer) 10, res.join());
52 | }
53 |
54 | private Task doTryCatch()
55 | {
56 | try
57 | {
58 | if (await(getBlockedFuture(10)) == 10)
59 | {
60 | throw new IllegalArgumentException(String.valueOf(10));
61 | }
62 |
63 | }
64 | catch (IllegalArgumentException ex)
65 | {
66 | return Task.fromValue(10);
67 | }
68 | return null;
69 | }
70 |
71 | @Test
72 | public void testFinally() throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException
73 | {
74 | final Task res = doTestFinally();
75 | completeFutures();
76 | assertEquals((Integer) 1337, res.join());
77 | }
78 |
79 | private Task doTestFinally()
80 | {
81 | try
82 | {
83 | if (await(getBlockedFuture(10)) == 10)
84 | {
85 | throw new IllegalArgumentException(String.valueOf(10));
86 | }
87 |
88 | }
89 | finally
90 | {
91 | return Task.fromValue(1337);
92 | }
93 | }
94 |
95 |
96 | @Test
97 | public void testTryCatch2() throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException
98 | {
99 | final Task res = doTryCatch2();
100 | completeFutures();
101 | assertTrue(res.isDone());
102 | }
103 |
104 | private Task doTryCatch2()
105 | {
106 | int c = 1;
107 | try
108 | {
109 | await(getBlockedFuture());
110 | }
111 | catch (Exception ex)
112 | {
113 | // once this was causing a verification error, now fixed
114 | c = c + 1;
115 | }
116 | return Task.done();
117 | }
118 |
119 |
120 | @Test
121 | public void testTryCatch3() throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException
122 | {
123 | final Task res = doTryCatch3();
124 | completeFutures();
125 | assertEquals("fail", res.join());
126 | }
127 |
128 | private Task doTryCatch3()
129 | {
130 | int c = 1;
131 | try
132 | {
133 | await(getBlockedTask());
134 | await(getBlockedTask());
135 | await(getBlockedTask());
136 | await(getBlockedTask());
137 | await(Task.fromException(new Exception("fail")));
138 | }
139 | catch (Exception ex)
140 | {
141 | await(getBlockedTask());
142 | await(getBlockedTask());
143 | await(getBlockedTask());
144 | await(getBlockedTask());
145 | return Task.fromValue(ex.getCause().getMessage());
146 | }
147 | return Task.done();
148 | }
149 |
150 |
151 | @Test
152 | public void testTryCatch4() throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException
153 | {
154 | final Task res = doTryCatch4();
155 | completeFutures();
156 | assertEquals("fail", res.join());
157 | }
158 |
159 | private Task doTryCatch4()
160 | {
161 | int c = 1;
162 | try
163 | {
164 | await(getBlockedTask());
165 | await(getBlockedTask());
166 | if (await(getBlockedTask()) == null)
167 | {
168 | throw new Exception("fail");
169 | }
170 | await(getBlockedTask());
171 | }
172 | catch (Exception ex)
173 | {
174 | await(getBlockedTask());
175 | await(getBlockedTask());
176 | await(getBlockedTask());
177 | await(getBlockedTask());
178 | return Task.fromValue(ex.getMessage());
179 | }
180 | return Task.done();
181 | }
182 |
183 |
184 | private Object stackAnalysisProblem(final Exception ex)
185 | {
186 | Throwable t = ex;
187 |
188 | while (t.getCause() != null && !(t instanceof IllegalAccessException))
189 | {
190 | t = t.getCause();
191 | }
192 |
193 | if (t instanceof IllegalAccessException)
194 | {
195 | IllegalAccessException wex = (IllegalAccessException) t;
196 | }
197 |
198 | return null;
199 | }
200 |
201 |
202 | @Test
203 | public void smallTest() throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException
204 | {
205 | final Task> res = doIt(Task.done());
206 | completeFutures();
207 | assertNull(res.join());
208 | }
209 |
210 |
211 | public Task> doIt(Task> t)
212 | {
213 | try
214 | {
215 | await(t);
216 | }
217 | catch (Exception ex)
218 | {
219 | await(t);
220 | }
221 | return t;
222 | }
223 | }
224 |
--------------------------------------------------------------------------------
/async/src/test/java/com/ea/async/test/FunctionCallTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.test;
30 |
31 | import com.ea.async.Task;
32 |
33 | import org.junit.Test;
34 |
35 | import java.util.ArrayList;
36 | import java.util.List;
37 | import java.util.concurrent.CompletableFuture;
38 |
39 | import static com.ea.async.Async.await;
40 | import static org.junit.Assert.assertEquals;
41 |
42 | public class FunctionCallTest extends BaseTest
43 | {
44 | public static class TaskSomethingAsync
45 | {
46 | private List blockers = new ArrayList<>();
47 |
48 | public Task doSomething()
49 | {
50 | String res1 = await(blocker());
51 | return Task.fromValue(":" + res1);
52 | }
53 |
54 | private CompletableFuture blocker()
55 | {
56 | final CompletableFuture blocker = new CompletableFuture<>();
57 | blockers.add(blocker);
58 | return blocker;
59 | }
60 |
61 | public void completeBlockers()
62 | {
63 | for (int i = 0; i < blockers.size(); i++)
64 | {
65 | final CompletableFuture fut = blockers.get(i);
66 | fut.complete("str " + i);
67 | }
68 | }
69 | }
70 |
71 | @Test
72 | public void testBlockingAndException() throws IllegalAccessException, InstantiationException
73 | {
74 | final TaskSomethingAsync a = new TaskSomethingAsync();
75 |
76 | Task res = a.doSomething();
77 | a.completeBlockers();
78 | assertEquals(":str 0", res.join());
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/async/src/test/java/com/ea/async/test/HowItShouldWorkTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.test;
30 |
31 | import org.junit.Test;
32 |
33 | import java.util.concurrent.CompletableFuture;
34 |
35 | import static com.ea.async.Async.await;
36 | import static org.junit.Assert.assertEquals;
37 | import static org.junit.Assert.assertFalse;
38 |
39 | public class HowItShouldWorkTest
40 | {
41 | private static class WhatWillBeWritten
42 | {
43 | // @Async
44 | public CompletableFuture doSomething(CompletableFuture blocker)
45 | {
46 | String res = await(blocker);
47 | return CompletableFuture.completedFuture(":" + res);
48 | }
49 | }
50 |
51 | private static class HowItShouldBehave
52 | {
53 | public CompletableFuture doSomething(CompletableFuture blocker)
54 | {
55 | return blocker.thenApply(res -> ":" + res);
56 | }
57 | }
58 |
59 | private static class HowItShouldBeInstrumented
60 | {
61 | public CompletableFuture doSomething(CompletableFuture blocker)
62 | {
63 | if (!blocker.isDone())
64 | {
65 | return blocker.exceptionally(t -> null)
66 | .thenCompose(t -> this.async$doSomething(blocker, 1, t));
67 | }
68 | String res = (String) blocker.join();
69 | return CompletableFuture.completedFuture(":" + res);
70 | }
71 |
72 | public CompletableFuture async$doSomething(CompletableFuture blocker, int async$state, Object async$result)
73 | {
74 | String res;
75 | switch (async$state)
76 | {
77 | case 1:
78 | if (!blocker.isDone())
79 | {
80 | return blocker.exceptionally(t -> null)
81 | .thenCompose(t -> this.async$doSomething(blocker, 1, t));
82 | }
83 | res = blocker.join();
84 | return CompletableFuture.completedFuture(":" + res);
85 | default:
86 | throw new IllegalArgumentException();
87 | }
88 | }
89 | }
90 |
91 | @Test
92 | public void testMockInstrumentation()
93 | {
94 | CompletableFuture blocker = new CompletableFuture<>();
95 | final CompletableFuture res = new HowItShouldBeInstrumented().doSomething(blocker);
96 | assertFalse(blocker.isDone());
97 | assertFalse(res.isDone());
98 | blocker.complete("x");
99 | assertEquals(":x", res.join());
100 | }
101 |
102 | @Test
103 | public void testHowItShouldBehave()
104 | {
105 | CompletableFuture blocker = new CompletableFuture<>();
106 | final CompletableFuture res = new HowItShouldBehave().doSomething(blocker);
107 | assertFalse(blocker.isDone());
108 | assertFalse(res.isDone());
109 | blocker.complete("x");
110 | assertEquals(":x", res.join());
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/async/src/test/java/com/ea/async/test/JoinTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.test;
30 |
31 | import org.junit.Test;
32 |
33 | import java.util.concurrent.CompletableFuture;
34 |
35 | import static com.ea.async.Async.await;
36 | import static org.junit.Assert.assertEquals;
37 |
38 | public class JoinTest extends BaseTest
39 | {
40 | public static class OtherJoinCalls
41 | {
42 | public CompletableFuture doSomething(CompletableFuture blocker)
43 | {
44 | int local = 7;
45 | String res = ":" + Math.max(local, await(blocker).length()) + ":" + join() + ":" + join(2, 3);
46 | return CompletableFuture.completedFuture(res);
47 | }
48 |
49 | public Object join()
50 | {
51 | return 9;
52 | }
53 |
54 | public Object join(int a, int b)
55 | {
56 | return a + b;
57 | }
58 | }
59 |
60 | @Test
61 | public void testOtherJoinMethods() throws IllegalAccessException, InstantiationException
62 | {
63 | OtherJoinCalls a = new OtherJoinCalls();
64 |
65 | CompletableFuture blocker = new CompletableFuture<>();
66 | final CompletableFuture res = a.doSomething(blocker);
67 | blocker.complete("0123456789");
68 | assertEquals(":10:9:5", res.join());
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/async/src/test/java/com/ea/async/test/LambdaTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.test;
30 |
31 | import com.ea.async.Task;
32 |
33 | import org.junit.Test;
34 |
35 | import static com.ea.async.Async.await;
36 | import static com.ea.async.Task.fromValue;
37 | import static org.junit.Assert.assertEquals;
38 |
39 | public class LambdaTest extends BaseTest
40 | {
41 | @Test
42 | public void testThenCompose()
43 | {
44 | Task task = getBlockedTask(10)
45 | .thenCompose(x -> fromValue(x + await(getBlockedFuture(20))));
46 | completeFutures();
47 | assertEquals((Integer) 30, task.join());
48 | }
49 |
50 |
51 | @Test
52 | public void testLongLambda()
53 | {
54 | Task task = getBlockedTask(5)
55 | .thenCompose(x -> {
56 | await(getBlockedTask());
57 | await(getBlockedTask());
58 | await(getBlockedTask());
59 | await(getBlockedTask());
60 | return fromValue(11);
61 | });
62 | completeFutures();
63 | assertEquals((Integer) 11, task.join());
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/async/src/test/java/com/ea/async/test/LocalVarsTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.test;
30 |
31 | import com.ea.async.Task;
32 |
33 | import org.junit.Test;
34 |
35 | import java.lang.reflect.InvocationTargetException;
36 |
37 | import static com.ea.async.Async.await;
38 | import static com.ea.async.Task.done;
39 | import static com.ea.async.Task.fromValue;
40 | import static org.junit.Assert.assertEquals;
41 |
42 | public class LocalVarsTest extends BaseTest
43 | {
44 |
45 | @Test
46 | public void testRepeatedLocalVarsNames() throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException
47 | {
48 | final Task res = done().thenCompose(o -> {
49 | {
50 | String a = "a1";
51 | }
52 | await(getBlockedTask());
53 | {
54 | String a = "a2";
55 | }
56 | return fromValue(10);
57 | });
58 | completeFutures();
59 | assertEquals((Integer) 10, res.join());
60 | }
61 |
62 | @Test
63 | public void testRepeatedLocalVarsNames2() throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException
64 | {
65 | final Task res = done().thenCompose(o -> {
66 | {
67 | String a = "a1";
68 | String b = "b1";
69 | int c = 1;
70 | }
71 | await(getBlockedTask());
72 | {
73 | String a = "a2";
74 | String b = "b2";
75 | int c = 10;
76 | return fromValue((Integer)c);
77 | }
78 | });
79 | completeFutures();
80 | assertEquals((Integer) 10, res.join());
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/async/src/test/java/com/ea/async/test/LoopTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.test;
30 |
31 | import com.ea.async.Task;
32 |
33 | import org.junit.Test;
34 |
35 | import java.util.List;
36 | import java.util.concurrent.CompletableFuture;
37 | import java.util.stream.Collectors;
38 | import java.util.stream.IntStream;
39 |
40 | import static com.ea.async.Async.await;
41 | import static junit.framework.Assert.assertTrue;
42 | import static org.junit.Assert.assertEquals;
43 | import static org.junit.Assert.assertFalse;
44 |
45 | public class LoopTest extends BaseTest
46 | {
47 |
48 |
49 | @Test
50 | public void testForLoop()
51 | {
52 | int count = 5;
53 | final Task task = futureFrom(() -> {
54 | String str = "";
55 | for (int i = 0; i < count; i++)
56 | {
57 | str += ":" + await(getBlockedFuture(i));
58 | }
59 | return Task.fromValue(str);
60 | });
61 | assertFalse(task.isDone());
62 | completeFutures();
63 | assertTrue(task.isDone());
64 | assertEquals(":0:1:2:3:4", task.join());
65 | }
66 |
67 | @Test
68 | public void testWhileLoop()
69 | {
70 | int count = 5;
71 | final Task task = futureFrom(() -> {
72 | String str = "";
73 | int i = 0;
74 | while (i < count)
75 | {
76 | str += ":" + await(getBlockedFuture(i));
77 | i++;
78 | }
79 | return Task.fromValue(str);
80 | });
81 | assertFalse(task.isDone());
82 | completeFutures();
83 | assertTrue(task.isDone());
84 | assertEquals(":0:1:2:3:4", task.join());
85 | }
86 |
87 |
88 | @Test
89 | public void testDoLoop()
90 | {
91 | int count = 5;
92 | final Task task = futureFrom(() -> {
93 | String str = "";
94 | int i = 0;
95 | do
96 | {
97 | str += ":" + await(getBlockedFuture(i));
98 | i++;
99 | } while (i < count);
100 | return Task.fromValue(str);
101 | });
102 | assertFalse(task.isDone());
103 | completeFutures();
104 | assertTrue(task.isDone());
105 | assertEquals(":0:1:2:3:4", task.join());
106 | }
107 |
108 |
109 | @Test
110 | public void testForEach()
111 | {
112 | final List> blockedFuts = IntStream.range(0, 5)
113 | .mapToObj(i -> getBlockedFuture((Integer) i))
114 | .collect(Collectors.toList());
115 | final Task task = futureFrom(() -> {
116 | String str = "";
117 | for (CompletableFuture f : blockedFuts)
118 | {
119 | str += ":" + await(f);
120 | }
121 | return Task.fromValue(str);
122 | });
123 | assertFalse(task.isDone());
124 | completeFutures();
125 | assertTrue(task.isDone());
126 | assertEquals(":0:1:2:3:4", task.join());
127 | }
128 |
129 |
130 | }
131 |
--------------------------------------------------------------------------------
/async/src/test/java/com/ea/async/test/MultipleAwaitTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.test;
30 |
31 | import com.ea.async.Task;
32 |
33 | import org.junit.Test;
34 |
35 | import java.util.ArrayList;
36 | import java.util.List;
37 | import java.util.concurrent.CompletableFuture;
38 |
39 | import static com.ea.async.Async.await;
40 | import static org.junit.Assert.assertEquals;
41 |
42 | public class MultipleAwaitTest extends BaseTest
43 | {
44 | public static class TaskSomethingAsync
45 | {
46 | private List blockers = new ArrayList<>();
47 |
48 | public Task doSomething()
49 | {
50 | String res1 = await(blocker());
51 | String res2 = await(blocker());
52 | return Task.fromValue(res1 + ":" + res2);
53 | }
54 |
55 | public Task doSomething(Task blocker1, Task blocker2)
56 | {
57 | String res1 = await(blocker1);
58 | String res2 = await(blocker2);
59 | return Task.fromValue(res1 + ":" + res2);
60 | //return Task.fromValue(res1 + ":" + res2);
61 | }
62 |
63 | private CompletableFuture blocker()
64 | {
65 | final CompletableFuture blocker = new CompletableFuture<>();
66 | blockers.add(blocker);
67 | return blocker;
68 | }
69 |
70 | public void completeBlockers()
71 | {
72 | for (int i = 0; i < blockers.size(); i++)
73 | {
74 | final CompletableFuture fut = blockers.get(i);
75 | fut.complete("str " + i);
76 | }
77 | }
78 | }
79 |
80 | @Test
81 | public void testMultipleAwaitsAndMethods() throws IllegalAccessException, InstantiationException
82 | {
83 | final TaskSomethingAsync a = new TaskSomethingAsync();
84 |
85 | Task res = a.doSomething();
86 | a.completeBlockers();
87 | assertEquals("str 0:str 1", res.join());
88 | }
89 |
90 |
91 | @Test
92 | public void testMultipleAwaitsFromParams() throws IllegalAccessException, InstantiationException
93 | {
94 | final TaskSomethingAsync a = new TaskSomethingAsync();
95 | Task blocker1 = new Task<>();
96 | Task blocker2 = new Task<>();
97 | Task res = a.doSomething(blocker1, blocker2);
98 | blocker1.complete("a");
99 | blocker2.complete("b");
100 | assertEquals("a:b", res.join());
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/async/src/test/java/com/ea/async/test/NoPackageTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.test;
30 |
31 | import org.junit.Test;
32 |
33 | import java.lang.reflect.InvocationTargetException;
34 | import java.lang.reflect.Method;
35 | import java.util.concurrent.CompletableFuture;
36 |
37 | import static org.junit.Assert.assertEquals;
38 |
39 | public class NoPackageTest extends BaseTest
40 | {
41 | @Test
42 | public void testPackageLessClass() throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException
43 | {
44 |
45 | Class> newClass = Class.forName("NoPackageAsync");
46 | final Method method = newClass.getMethod("noPackageMethod", CompletableFuture.class, int.class);
47 |
48 | CompletableFuture blocker = new CompletableFuture<>();
49 | final CompletableFuture res = (CompletableFuture) method.invoke(newClass.newInstance(), blocker, 5);
50 | blocker.complete("zzz");
51 | assertEquals("5:10000000000:1.5:3.5:zzz:true", res.join());
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/async/src/test/java/com/ea/async/test/NullThenBasicValueTest.java:
--------------------------------------------------------------------------------
1 | package com.ea.async.test;
2 |
3 | import com.ea.async.Task;
4 |
5 | import org.junit.Test;
6 |
7 | import static com.ea.async.Async.await;
8 | import static org.junit.Assert.assertNull;
9 |
10 | public class NullThenBasicValueTest extends BaseTest
11 | {
12 | @Test
13 | public void nullThenBasicValueTest() throws Exception
14 | {
15 | debugTransform(NullThenBasicValueTest.class.getName() + "$NullThenBasicVal");
16 | final Task res = NullThenBasicVal.doIt(getBlockedTask());
17 | completeFutures();
18 | assertNull(res.join());
19 | }
20 |
21 | public static class NullThenBasicVal
22 | {
23 | public static Task doIt(Task task)
24 | {
25 | String nullString = null; //this variable must be a string and initialized to null
26 | int basicInt = 0; //this variable must be numeric and initialized to anything
27 |
28 | await(task);
29 | return Task.done();
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/async/src/test/java/com/ea/async/test/RuntimeInstrTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.test;
30 |
31 | import org.junit.Test;
32 |
33 | import java.lang.reflect.InvocationTargetException;
34 | import java.util.concurrent.CompletableFuture;
35 |
36 | import static com.ea.async.Async.await;
37 | import static org.junit.Assert.assertEquals;
38 |
39 | public class RuntimeInstrTest extends BaseTest
40 | {
41 |
42 | private static class Basic
43 | {
44 | static String concat(int i, long j, float f, double d, Object obj, boolean b)
45 | {
46 | return i + ":" + j + ":" + f + ":" + d + ":" + obj + ":" + b;
47 | }
48 |
49 | public CompletableFuture doSomething(CompletableFuture blocker, int var)
50 | {
51 | return CompletableFuture.completedFuture(concat(var, 10_000_000_000L, 1.5f, 3.5d, await(blocker), true));
52 | }
53 | }
54 |
55 | @Test
56 | public void testInstrumentation() throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException
57 | {
58 | CompletableFuture blocker = new CompletableFuture<>();
59 | Basic basic = new Basic();
60 | final CompletableFuture res = basic.doSomething(blocker, 5);
61 |
62 | blocker.complete("zzz");
63 | assertEquals("5:10000000000:1.5:3.5:zzz:true", res.join());
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/async/src/test/java/com/ea/async/test/SmallestExceptionTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.test;
30 |
31 | import com.ea.async.Task;
32 |
33 | import org.junit.Test;
34 |
35 | import java.lang.reflect.InvocationTargetException;
36 |
37 | import static com.ea.async.Async.await;
38 | import static org.junit.Assert.assertNull;
39 |
40 | public class SmallestExceptionTest extends BaseTest
41 | {
42 |
43 | @Test
44 | public void testRepeatedLocalVarsNames() throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException
45 | {
46 | final Task res = doIt();
47 | completeFutures();
48 | assertNull(res.join());
49 | }
50 |
51 |
52 | private Task doIt()
53 | {
54 | try
55 | {
56 | await(getBlockedTask());
57 | return Task.done();
58 | }
59 | catch (Exception ex)
60 | {
61 | return Task.done();
62 | }
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/async/src/test/java/com/ea/async/test/SmallestTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.test;
30 |
31 | import com.ea.async.Task;
32 |
33 | import org.junit.Test;
34 |
35 | import java.lang.reflect.InvocationTargetException;
36 |
37 | import static com.ea.async.Async.await;
38 | import static junit.framework.TestCase.assertNull;
39 |
40 | public class SmallestTest extends BaseTest
41 | {
42 |
43 | @Test
44 | public void smallTest() throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException
45 | {
46 | final Task> res = doIt();
47 | completeFutures();
48 | assertNull(res.join());
49 | }
50 |
51 |
52 | private Task doIt()
53 | {
54 | return Task.fromValue(await(getBlockedTask()));
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/async/src/test/java/com/ea/async/test/StaticTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.test;
30 |
31 | import com.ea.async.Async;
32 |
33 | import org.junit.Test;
34 |
35 | import java.lang.reflect.InvocationTargetException;
36 | import java.util.concurrent.CompletableFuture;
37 |
38 | import static com.ea.async.Async.await;
39 | import static org.junit.Assert.assertEquals;
40 |
41 | public class StaticTest extends BaseTest
42 | {
43 | public static class StaticUse
44 | {
45 | static String concat(int i, long j, float f, double d, Object obj, boolean b)
46 | {
47 | return i + ":" + j + ":" + f + ":" + d + ":" + obj + ":" + b;
48 | }
49 |
50 | public static CompletableFuture staticMethod(CompletableFuture blocker, int var)
51 | {
52 | return CompletableFuture.completedFuture(concat(var, 10_000_000_000L, 1.5f, 3.5d, await(blocker), true));
53 | }
54 | }
55 |
56 | @Test
57 | public void testStaticMethodWithPrimitives() throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException
58 | {
59 | CompletableFuture blocker = new CompletableFuture<>();
60 | CompletableFuture res = StaticUse.staticMethod(blocker, 5);
61 | blocker.complete("zzz");
62 | assertEquals("5:10000000000:1.5:3.5:zzz:true", res.join());
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/async/src/test/java/com/ea/async/test/TaskTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.test;
30 |
31 | import com.ea.async.Task;
32 |
33 | import org.junit.Test;
34 |
35 | import static com.ea.async.Async.await;
36 | import static org.junit.Assert.assertEquals;
37 |
38 | public class TaskTest extends BaseTest
39 | {
40 | public static class TaskSomethingAsync
41 | {
42 | public Task doSomething(Task blocker)
43 | {
44 | String res = await(blocker);
45 | return Task.fromValue(":" + res);
46 | }
47 | }
48 |
49 | public static class TaskSomethingWithLocalsAndStack
50 | {
51 | public Task doSomething(Task blocker)
52 | {
53 | int local = 7;
54 | String res = ":" + Math.max(local, await(blocker).length());
55 | return Task.fromValue(res);
56 | }
57 | }
58 |
59 | public static class TaskSomethingAsyncWithException
60 | {
61 | public Task doSomething(Task blocker)
62 | {
63 | try
64 | {
65 | String res = await(blocker);
66 | return Task.fromValue(":" + res);
67 | }
68 | catch (RuntimeException ex)
69 | {
70 | return Task.fromValue(":" + ex.getCause().getMessage());
71 | }
72 | }
73 | }
74 |
75 | @Test
76 | public void testDirectPathNonBlocking() throws IllegalAccessException, InstantiationException
77 | {
78 | // test an example where the async function blocks (returns incomplete future)
79 | // this would not work without instrumentation
80 | final TaskSomethingAsync a = new TaskSomethingAsync();
81 |
82 | Task blocker = Task.fromValue("x");
83 | final Task res = a.doSomething(blocker);
84 | assertEquals(":x", res.join());
85 | }
86 |
87 | @Test
88 | public void testBlocking() throws IllegalAccessException, InstantiationException
89 | {
90 | final TaskSomethingAsync a = new TaskSomethingAsync();
91 |
92 | Task blocker = new Task<>();
93 | final Task res = a.doSomething(blocker);
94 | blocker.complete("x");
95 | assertEquals(":x", res.join());
96 | }
97 |
98 | @Test
99 | public void testBlockingWithStackAndLocal() throws IllegalAccessException, InstantiationException
100 | {
101 | final TaskSomethingWithLocalsAndStack a = new TaskSomethingWithLocalsAndStack();
102 |
103 | Task blocker = new Task<>();
104 | final Task res = a.doSomething(blocker);
105 | blocker.complete("0123456789");
106 | assertEquals(":10", res.join());
107 | }
108 |
109 | @Test
110 | public void testBlockingAndException() throws IllegalAccessException, InstantiationException
111 | {
112 | final TaskSomethingAsyncWithException a = new TaskSomethingAsyncWithException();
113 | Task blocker = new Task<>();
114 | final Task res = a.doSomething(blocker);
115 | blocker.completeExceptionally(new RuntimeException("Exception"));
116 | assertEquals(":Exception", res.join());
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/async/src/test/java/com/ea/async/test/TryWithResourcesTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2017 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.test;
30 |
31 | import com.ea.async.Task;
32 |
33 | import org.junit.Test;
34 |
35 | import java.lang.reflect.InvocationTargetException;
36 |
37 | import static com.ea.async.Async.await;
38 | import static org.junit.Assert.assertEquals;
39 |
40 | /**
41 | * Created by joeh on 2017-04-06.
42 | */
43 | public class TryWithResourcesTest extends BaseTest
44 | {
45 | private class CloseableResource implements AutoCloseable {
46 | private boolean closed = false;
47 |
48 | @Override
49 | public void close()
50 | {
51 | closed = true;
52 | }
53 |
54 | public boolean isClosed()
55 | {
56 | return closed;
57 | }
58 | }
59 |
60 | @Test
61 | public void testTryWithResources()
62 | {
63 | final Task res = doTestTryWithResources();
64 | completeFutures();
65 | assertEquals((Integer) 3456, res.join());
66 | }
67 |
68 | private Task doTestTryWithResources()
69 | {
70 | try(CloseableResource cr = new CloseableResource())
71 | {
72 | await(getBlockedFuture());
73 | if(cr.isClosed()) {
74 | throw new RuntimeException("Closed early");
75 | }
76 | }
77 |
78 | return Task.fromValue(3456);
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/gradle-plugin/pom.xml:
--------------------------------------------------------------------------------
1 |
28 |
29 |
30 | 4.0.0
31 |
32 | com.ea.async
33 | ea-async-parent
34 | 1.2.4-SNAPSHOT
35 | ..
36 |
37 | ea-async-gradle-plugin
38 | jar
39 | EA Async-Await Gradle Plugin
40 | Pre-instruments class files to work with the async-await paradigm
41 |
42 |
43 |
44 |
45 | org.apache.maven.plugins
46 | maven-compiler-plugin
47 |
48 |
49 | maven-clean-plugin
50 | 3.0.0
51 |
52 | false
53 |
54 |
55 |
56 | maven-assembly-plugin
57 |
58 |
59 | jar-with-dependencies
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 | gradle
68 | Gradle Releases Repository
69 | https://repo.gradle.org/gradle/libs-releases-local/
70 |
71 |
72 |
73 |
74 | com.ea.async
75 | ea-async
76 | ${project.version}
77 |
78 |
79 |
80 | org.apache.maven
81 | maven-artifact
82 | 3.5.3
83 |
84 |
85 |
86 | org.apache.maven
87 | maven-core
88 | 3.5.3
89 |
90 |
91 |
92 |
93 |
94 | org.codehaus.groovy
95 | groovy
96 | 2.5.8
97 | provided
98 |
99 |
100 |
101 | org.gradle
102 | gradle-core
103 | 5.6.4
104 | provided
105 |
106 |
107 |
108 | org.gradle
109 | gradle-core-api
110 | 5.6.4
111 | provided
112 |
113 |
114 |
115 | org.gradle
116 | gradle-base-services
117 | 5.6.4
118 | provided
119 |
120 |
121 |
122 | org.gradle
123 | gradle-model-core
124 | 5.6.4
125 | provided
126 |
127 |
128 |
129 | org.gradle
130 | gradle-language-jvm
131 | 5.6.4
132 | provided
133 |
134 |
135 |
136 | org.gradle
137 | gradle-language-java
138 | 5.6.4
139 | provided
140 |
141 |
142 |
143 | org.gradle
144 | gradle-platform-jvm
145 | 5.6.4
146 | provided
147 |
148 |
149 |
150 |
--------------------------------------------------------------------------------
/gradle-plugin/src/main/java/com/ea/async/gradle/plugin/AsyncPlugin.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2020 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.gradle.plugin;
30 |
31 | import com.ea.async.instrumentation.Transformer;
32 |
33 | import org.gradle.api.Plugin;
34 | import org.gradle.api.Project;
35 | import org.gradle.api.tasks.compile.JavaCompile;
36 |
37 | import java.io.File;
38 | import java.io.FileInputStream;
39 | import java.io.IOException;
40 | import java.net.MalformedURLException;
41 | import java.net.URL;
42 | import java.net.URLClassLoader;
43 | import java.nio.file.Files;
44 | import java.nio.file.Paths;
45 | import java.util.ArrayList;
46 | import java.util.List;
47 | import java.util.Objects;
48 |
49 | /**
50 | * A plugin that allows easily integrating EA Async instrumentation into the Gradle build process.
51 | */
52 | public class AsyncPlugin implements Plugin
53 | {
54 |
55 | /**
56 | * Applies the plugin to the project. Prepares Java compilation tasks to be followed up on by instrumentation.
57 | * @param project the Gradle project to which the plugin was applied
58 | */
59 | @Override
60 | public void apply(final Project project)
61 | {
62 | project.getTasks().withType(JavaCompile.class, task ->
63 | {
64 | // This will be called for every JavaCompile task, whether already existing or added dynamically later
65 | task.doLast("EA Async instrumentation", t -> instrumentCompileResults(task));
66 | });
67 | }
68 |
69 | /**
70 | * Rewrites compiled classes output by a Java compilation task.
71 | * Called for each compilation task after it finishes.
72 | * @param task the Java compilation task whose output to instrument
73 | */
74 | private void instrumentCompileResults(final JavaCompile task)
75 | {
76 | // Set up the Transformer to explode on failure
77 | final Transformer asyncTransformer = new Transformer();
78 | asyncTransformer.setErrorListener(err ->
79 | {
80 | throw new RuntimeException("Failed to instrument the output of " + task.toString() + ": " + err);
81 | });
82 | // Create a classloader that can see the same CompletionStage subclasses as the compiler
83 | final List classpathUrls = new ArrayList<>();
84 | try
85 | {
86 | for (File f : task.getClasspath().plus(task.getOutputs().getFiles()).getFiles())
87 | {
88 | classpathUrls.add(f.toURI().toURL());
89 | }
90 | }
91 | catch (MalformedURLException e)
92 | {
93 | throw new RuntimeException("Bad URL when preparing instrumentation of " + task.toString(), e);
94 | }
95 | final ClassLoader classLoader = new URLClassLoader(classpathUrls.toArray(new URL[0]));
96 | // Rewrite the class files in the output directory
97 | instrumentFile(task.getDestinationDir(), task, asyncTransformer, classLoader);
98 | }
99 |
100 | /**
101 | * Recursively instruments the specified file system entry and its descendants.
102 | * @param fsEntry a File in the output directory of a task
103 | * @param task the JavaCompile task whose output is being instrumented
104 | * @param asyncTransformer the transformer used to instrument the classes
105 | * @param classLoader the classloader to supply to the transformer
106 | */
107 | private void instrumentFile(final File fsEntry, final JavaCompile task,
108 | final Transformer asyncTransformer, final ClassLoader classLoader)
109 | {
110 | if (fsEntry.isDirectory())
111 | {
112 | // Recurse into subdirectories and files
113 | for (File subentry : Objects.requireNonNull(fsEntry.listFiles())) {
114 | instrumentFile(subentry, task, asyncTransformer, classLoader);
115 | }
116 | }
117 | else if (fsEntry.isFile() && fsEntry.getName().endsWith(".class"))
118 | {
119 | // Instrument a class
120 | byte[] instrumentedClass;
121 | try (FileInputStream fis = new FileInputStream(fsEntry))
122 | {
123 | instrumentedClass = asyncTransformer.instrument(classLoader, fis);
124 | }
125 | catch (IOException e)
126 | {
127 | throw new RuntimeException("Failed to instrument '" + fsEntry.getPath() + "' from " + task.toString(), e);
128 | }
129 | if (instrumentedClass != null)
130 | {
131 | // Transformer#instrument returns null if no changes were needed
132 | try
133 | {
134 | Files.write(Paths.get(fsEntry.getAbsolutePath()), instrumentedClass);
135 | }
136 | catch (IOException e)
137 | {
138 | throw new RuntimeException("Failed to write '" + fsEntry.getPath() + "'", e);
139 | }
140 | }
141 | }
142 | }
143 |
144 | }
145 |
--------------------------------------------------------------------------------
/gradle-plugin/src/main/resources/META-INF/gradle-plugins/com.ea.async.gradle.plugin.properties:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (C) 2020 Electronic Arts Inc. All rights reserved.
3 | #
4 | # Redistribution and use in source and binary forms, with or without
5 | # modification, are permitted provided that the following conditions
6 | # are met:
7 | #
8 | # 1. Redistributions of source code must retain the above copyright
9 | # notice, this list of conditions and the following disclaimer.
10 | # 2. Redistributions in binary form must reproduce the above copyright
11 | # notice, this list of conditions and the following disclaimer in the
12 | # documentation and/or other materials provided with the distribution.
13 | # 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | # its contributors may be used to endorse or promote products derived
15 | # from this software without specific prior written permission.
16 | #
17 | # THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | # DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | #
28 |
29 | implementation-class=com.ea.async.gradle.plugin.AsyncPlugin
30 |
--------------------------------------------------------------------------------
/maven-plugin/README.md:
--------------------------------------------------------------------------------
1 | EA Async Maven Plugin
2 | ============
3 |
4 | EA Async implements async-await methods in the JVM. It allows programmers to write asynchronous code in a sequential fashion. It was developed by [BioWare](http://www.bioware.com), a division of [Electronic Arts](http://www.ea.com).
5 |
6 | The EA Async Maven Plugin executes compile time instrumentation of classes that use EA Async.
7 |
8 | A sample project can be found [here](src/test/project-to-test/pom.xml).
9 |
10 | Documentation
11 | =======
12 | Documentation is located [here](http://orbit.bioware.com/).
13 |
14 | License
15 | =======
16 | EA Async is licensed under the [BSD 3-Clause License](../LICENSE).
17 |
18 | Usage
19 | =======
20 |
21 | Add the EA Async dependency:
22 |
23 | ```xml
24 |
25 | com.ea.async
26 | ea-async
27 | 1.2.3
28 |
29 | ```
30 |
31 | Add the build plugin that will instrument the uses of `await`
32 |
33 | ```xml
34 |
35 |
36 |
37 | com.ea.async
38 | ea-async-maven-plugin
39 | 1.2.3
40 |
41 |
42 |
43 | instrument
44 | instrument-test
45 |
46 |
47 |
48 |
49 |
50 |
51 | ```
52 |
53 |
--------------------------------------------------------------------------------
/maven-plugin/pom.xml:
--------------------------------------------------------------------------------
1 |
28 |
29 |
30 | 4.0.0
31 |
32 | com.ea.async
33 | ea-async-parent
34 | 1.2.4-SNAPSHOT
35 | ..
36 |
37 | com.ea.async
38 | ea-async-maven-plugin
39 | maven-plugin
40 | EA Async-Await Maven Plugin
41 | Pre instruments class files to work with the async-await paradigm
42 |
43 |
44 |
45 |
46 | org.apache.maven.plugins
47 | maven-plugin-plugin
48 | 3.5.1
49 |
50 |
51 | default-descriptor
52 |
53 | descriptor
54 |
55 | process-classes
56 |
57 |
58 | help-descriptor
59 |
60 | helpmojo
61 |
62 | process-classes
63 |
64 |
65 |
66 |
67 | maven-clean-plugin
68 | 3.0.0
69 |
70 | false
71 |
72 |
73 |
74 |
75 |
76 |
77 | com.ea.async
78 | ea-async
79 | ${project.version}
80 |
81 |
82 |
83 | org.apache.maven
84 | maven-artifact
85 | 3.5.3
86 |
87 |
88 |
89 | org.apache.maven
90 | maven-plugin-api
91 | 3.5.3
92 |
93 |
94 |
95 | org.apache.maven
96 | maven-core
97 | 3.5.3
98 |
99 |
100 |
101 | org.codehaus.plexus
102 | plexus-archiver
103 | 3.7.0
104 |
105 |
106 |
107 | org.apache.maven
108 | maven-compat
109 | 3.5.3
110 | test
111 |
112 |
113 |
114 |
115 | org.apache.maven.plugin-tools
116 | maven-plugin-annotations
117 | 3.5.1
118 | provided
119 |
120 |
121 |
122 | org.apache.maven.plugin-testing
123 | maven-plugin-testing-harness
124 | 3.3.0
125 | test
126 |
127 |
128 |
129 | junit
130 | junit
131 | test
132 |
133 |
134 |
135 |
--------------------------------------------------------------------------------
/maven-plugin/src/main/java/com/ea/async/maven/plugin/AbstractAsyncMojo.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.maven.plugin;
30 |
31 | import com.ea.async.instrumentation.Transformer;
32 |
33 | import org.apache.maven.plugin.AbstractMojo;
34 | import org.apache.maven.plugin.MojoExecutionException;
35 | import org.apache.maven.plugins.annotations.Component;
36 | import org.apache.maven.plugins.annotations.Parameter;
37 | import org.apache.maven.project.MavenProject;
38 | import org.codehaus.plexus.archiver.ArchiverException;
39 | import org.codehaus.plexus.components.io.resources.PlexusIoFileResourceCollection;
40 | import org.codehaus.plexus.components.io.resources.PlexusIoResource;
41 | import org.codehaus.plexus.util.IOUtil;
42 |
43 | import java.io.File;
44 | import java.io.FileOutputStream;
45 | import java.io.IOException;
46 | import java.io.InputStream;
47 | import java.net.URLClassLoader;
48 | import java.util.Iterator;
49 |
50 |
51 | public abstract class AbstractAsyncMojo extends AbstractMojo
52 | {
53 |
54 | private static final String[] DEFAULT_EXCLUDES = new String[]{ "**/package.html" };
55 |
56 | private static final String[] DEFAULT_INCLUDES = new String[]{ "**/**" };
57 |
58 | /**
59 | * List of files to include.
60 | * Fileset patterns relative to the input directory whose contents
61 | * is being instrumented.
62 | */
63 | @Parameter
64 | private String[] includes;
65 |
66 | /**
67 | * List of files to include.
68 | * Fileset patterns relative to the input directory whose contents
69 | * is being instrumented.
70 | */
71 | @Parameter
72 | private String[] excludes;
73 |
74 | /**
75 | * Directory where the instrumented files will be written.
76 | * If not set the files will be overwritten with the new data.
77 | */
78 | @Parameter(required = false)
79 | private File outputDirectory;
80 |
81 | @Parameter(defaultValue = "${project.build.outputDirectory}", required = true)
82 | protected File classesDirectory;
83 |
84 | /**
85 | * Prints each file being instrumented
86 | */
87 | @Parameter
88 | protected boolean verbose = false;
89 |
90 | @Component
91 | protected MavenProject project;
92 |
93 |
94 | /**
95 | * Return the specific output directory to instrument.
96 | */
97 | protected abstract File getClassesDirectory();
98 |
99 | protected abstract String getType();
100 |
101 | /**
102 | * Instruments the files.
103 | */
104 | public void execute() throws MojoExecutionException
105 | {
106 | if (getClassesDirectory() == null || (!getClassesDirectory().exists() || getClassesDirectory().list().length < 1))
107 | {
108 | getLog().info("Skipping instrumentation of the " + getType());
109 | }
110 | else
111 | {
112 | instrumentFiles();
113 | }
114 | }
115 |
116 | private String[] getIncludes()
117 | {
118 | if (includes != null && includes.length > 0)
119 | {
120 | return includes;
121 | }
122 | return DEFAULT_INCLUDES;
123 | }
124 |
125 | private String[] getExcludes()
126 | {
127 | if (excludes != null && excludes.length > 0)
128 | {
129 | return excludes;
130 | }
131 | return DEFAULT_EXCLUDES;
132 | }
133 |
134 | private File getOutputDirectory()
135 | {
136 | if (outputDirectory == null)
137 | {
138 | return getClassesDirectory();
139 | }
140 | return outputDirectory;
141 | }
142 |
143 | public boolean isVerbose()
144 | {
145 | return verbose;
146 | }
147 |
148 | /**
149 | * Instrument the files that require instrumentation.
150 | */
151 | public void instrumentFiles() throws MojoExecutionException
152 | {
153 | try
154 | {
155 | File contentDirectory = getClassesDirectory();
156 | if (!contentDirectory.exists())
157 | {
158 | getLog().warn(getType() + " directory is empty! " + contentDirectory);
159 | return;
160 | }
161 | final Iterator it = getFiles(contentDirectory);
162 | final Transformer transformer = new Transformer();
163 | transformer.setErrorListener(error -> getLog().error(error));
164 | int instrumentedCount = 0;
165 | ClassLoader classLoader = createClassLoader();
166 | while (it.hasNext())
167 | {
168 | final PlexusIoResource resource = it.next();
169 | if (resource.isFile() && resource.getName().endsWith(".class"))
170 | {
171 | byte[] bytes = null;
172 | try (InputStream in = resource.getContents())
173 | {
174 | bytes = transformer.instrument(classLoader, in);
175 | }
176 | catch (Exception e)
177 | {
178 | getLog().error("Error instrumenting " + resource.getName(), e);
179 | }
180 | if (bytes != null)
181 | {
182 | if (isVerbose())
183 | {
184 | getLog().info("instrumented: " + resource.getName());
185 | }
186 | else if (getLog().isDebugEnabled())
187 | {
188 | getLog().debug("instrumented: " + resource.getName());
189 | }
190 | IOUtil.copy(bytes, new FileOutputStream(new File(getOutputDirectory(), resource.getName())));
191 | instrumentedCount++;
192 | }
193 | }
194 | }
195 | getLog().info("Orbit Async " + getType() + " instrumented: " + instrumentedCount);
196 | }
197 | catch (Exception e)
198 | {
199 | throw new MojoExecutionException("Error assembling instrumenting", e);
200 | }
201 | }
202 |
203 |
204 | private Iterator getFiles(final File contentDirectory) throws IOException
205 | {
206 | if (!contentDirectory.isDirectory())
207 | {
208 | throw new ArchiverException(contentDirectory.getAbsolutePath() + " is not a directory.");
209 | }
210 |
211 | final PlexusIoFileResourceCollection collection = new PlexusIoFileResourceCollection();
212 |
213 | collection.setIncludes(getIncludes());
214 | collection.setExcludes(getExcludes());
215 | collection.setBaseDir(contentDirectory);
216 | collection.setIncludingEmptyDirectories(false);
217 | collection.setPrefix("");
218 | collection.setUsingDefaultExcludes(true);
219 |
220 | return collection.getResources();
221 | }
222 |
223 | abstract ClassLoader createClassLoader();
224 | }
225 |
--------------------------------------------------------------------------------
/maven-plugin/src/main/java/com/ea/async/maven/plugin/MainMojo.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.maven.plugin;
30 |
31 | import org.apache.maven.artifact.Artifact;
32 | import org.apache.maven.plugin.MojoExecutionException;
33 | import org.apache.maven.plugins.annotations.Execute;
34 | import org.apache.maven.plugins.annotations.LifecyclePhase;
35 | import org.apache.maven.plugins.annotations.Mojo;
36 | import org.apache.maven.plugins.annotations.ResolutionScope;
37 |
38 | import java.io.File;
39 | import java.net.MalformedURLException;
40 | import java.net.URL;
41 | import java.net.URLClassLoader;
42 | import java.util.ArrayList;
43 | import java.util.List;
44 | import java.util.Set;
45 |
46 | @Mojo(name = "instrument",
47 | defaultPhase = LifecyclePhase.PROCESS_CLASSES,
48 | requiresProject = false,
49 | threadSafe = true,
50 | requiresDependencyResolution = ResolutionScope.RUNTIME)
51 | @Execute(goal = "instrument", phase = LifecyclePhase.PROCESS_CLASSES)
52 | public class MainMojo extends AbstractAsyncMojo
53 | {
54 |
55 |
56 | protected String getType()
57 | {
58 | return "main-classes";
59 | }
60 |
61 | /**
62 | * Return the main classes directory
63 | */
64 | protected File getClassesDirectory()
65 | {
66 | return classesDirectory;
67 | }
68 |
69 | @Override
70 | public void execute() throws MojoExecutionException
71 | {
72 | super.execute();
73 | }
74 |
75 | private List generateClassPath()
76 | {
77 | List classpath = new ArrayList<>(2 + project.getArtifacts().size());
78 |
79 | classpath.add(classesDirectory.getAbsolutePath());
80 |
81 | Set classpathArtifacts = project.getArtifacts();
82 |
83 | for (Artifact artifact : classpathArtifacts)
84 | {
85 | if (artifact.getArtifactHandler().isAddedToClasspath()
86 | && !"test".equalsIgnoreCase(artifact.getScope()))
87 | {
88 | File file = artifact.getFile();
89 | if (file != null)
90 | {
91 | classpath.add(file.getPath());
92 | }
93 | }
94 | }
95 | return classpath;
96 | }
97 |
98 | @Override
99 | protected ClassLoader createClassLoader()
100 | {
101 | final URL[] urls = generateClassPath().stream().map(f -> {
102 | try
103 | {
104 | return new File(f).toURI().toURL();
105 | }
106 | catch (MalformedURLException e)
107 | {
108 | throw new RuntimeException(e);
109 | }
110 | }).toArray(s -> new URL[s]);
111 | return new URLClassLoader(urls);
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/maven-plugin/src/main/java/com/ea/async/maven/plugin/TestMojo.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package com.ea.async.maven.plugin;
30 |
31 | import org.apache.maven.artifact.Artifact;
32 | import org.apache.maven.plugin.MojoExecutionException;
33 | import org.apache.maven.plugins.annotations.Execute;
34 | import org.apache.maven.plugins.annotations.LifecyclePhase;
35 | import org.apache.maven.plugins.annotations.Mojo;
36 | import org.apache.maven.plugins.annotations.Parameter;
37 | import org.apache.maven.plugins.annotations.ResolutionScope;
38 |
39 | import java.io.File;
40 | import java.net.MalformedURLException;
41 | import java.net.URL;
42 | import java.net.URLClassLoader;
43 | import java.util.ArrayList;
44 | import java.util.List;
45 | import java.util.Set;
46 |
47 | @Mojo(name = "instrument-test",
48 | defaultPhase = LifecyclePhase.PROCESS_TEST_CLASSES,
49 | requiresProject = false,
50 | threadSafe = true,
51 | executionStrategy = "always",
52 | requiresDirectInvocation = false,
53 | requiresDependencyResolution = ResolutionScope.TEST)
54 | @Execute(goal = "instrument-test", phase = LifecyclePhase.PROCESS_TEST_CLASSES)
55 | public class TestMojo extends AbstractAsyncMojo
56 | {
57 | /**
58 | * If set to true
it will bypass instrumenting the unit tests entirely.
59 | */
60 | @Parameter(property = "maven.test.skip")
61 | private boolean skip;
62 |
63 | /**
64 | * Directory containing the test classes files that should be instrumented
65 | */
66 | @Parameter(defaultValue = "${project.build.testOutputDirectory}", required = true)
67 | private File testClassesDirectory;
68 |
69 | protected String getType()
70 | {
71 | return "test-classes";
72 | }
73 |
74 | /**
75 | * Return the test-classes directory.
76 | */
77 | protected File getClassesDirectory()
78 | {
79 | return testClassesDirectory;
80 | }
81 |
82 | public void execute() throws MojoExecutionException
83 | {
84 | if (skip)
85 | {
86 | getLog().info("Skipping the instrumentation of the test classes");
87 | }
88 | else
89 | {
90 | super.execute();
91 | }
92 | }
93 |
94 | protected List generateTestClasspath()
95 | {
96 | List classpath = new ArrayList<>(2 + project.getArtifacts().size());
97 |
98 | classpath.add(testClassesDirectory.getAbsolutePath());
99 |
100 | classpath.add(classesDirectory.getAbsolutePath());
101 |
102 | Set classpathArtifacts = project.getArtifacts();
103 |
104 | for (Artifact artifact : classpathArtifacts)
105 | {
106 | if (artifact.getArtifactHandler().isAddedToClasspath())
107 | {
108 | File file = artifact.getFile();
109 | if (file != null)
110 | {
111 | classpath.add(file.getPath());
112 | }
113 | }
114 | }
115 | return classpath;
116 | }
117 |
118 | @Override
119 | protected ClassLoader createClassLoader()
120 | {
121 | final URL[] urls = generateTestClasspath().stream().map(f -> {
122 | try
123 | {
124 | return new File(f).toURI().toURL();
125 | }
126 | catch (MalformedURLException e)
127 | {
128 | throw new RuntimeException(e);
129 | }
130 | }).toArray(s -> new URL[s]);
131 | return new URLClassLoader(urls);
132 | }
133 | }
134 |
--------------------------------------------------------------------------------
/maven-plugin/src/test/java/MojoTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | import com.ea.async.maven.plugin.MainMojo;
30 |
31 | import org.apache.maven.plugin.testing.MojoRule;
32 | import org.junit.Ignore;
33 | import org.junit.Rule;
34 | import org.junit.Test;
35 |
36 | import java.io.File;
37 |
38 | import static org.junit.Assert.assertNotNull;
39 |
40 | public class MojoTest
41 | {
42 | @Rule
43 | public MojoRule rule = new MojoRule()
44 | {
45 | @Override
46 | protected void before() throws Throwable
47 | {
48 | }
49 |
50 | @Override
51 | protected void after()
52 | {
53 | }
54 | };
55 |
56 | @Test
57 | @Ignore
58 | public void testSomething() throws Exception
59 | {
60 | System.out.println(new File(".").getAbsoluteFile());
61 | MainMojo myMojo = (MainMojo)
62 | rule.lookupEmptyMojo("orbit-async", "src/test/project-to-test/pom.xml");
63 | assertNotNull(myMojo);
64 | myMojo.execute();
65 | }
66 |
67 | // TODO: add actual instumentation tests.
68 | }
69 |
--------------------------------------------------------------------------------
/maven-plugin/src/test/project-to-test/pom.xml:
--------------------------------------------------------------------------------
1 |
28 |
29 |
30 | 4.0.0
31 |
32 | com.ea.async
33 | ea-async-parent
34 | 1.2.4-SNAPSHOT
35 | ../../../..
36 |
37 | com.ea.async.samples
38 | ea-async-maven-plugin-sample
39 | EA Async-Await Samples: Maven Plugin Sample Usage
40 |
41 |
42 |
43 |
44 | org.apache.maven.plugins
45 | maven-compiler-plugin
46 |
47 | ${project.target.jdk}
48 | ${project.source.jdk}
49 |
50 |
51 |
52 | maven-clean-plugin
53 | 3.0.0
54 |
55 | false
56 |
57 |
58 |
59 | org.apache.maven.plugins
60 | maven-deploy-plugin
61 | 2.8.2
62 |
63 | true
64 |
65 |
66 |
67 |
68 | com.ea.async
69 | ea-async-maven-plugin
70 | 1.2.4-SNAPSHOT
71 |
72 |
73 |
74 |
75 | instrument
76 |
77 | instrument-test
78 |
79 |
80 |
81 |
82 | true
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 | com.ea.async
92 | ea-async
93 | 1.2.4-SNAPSHOT
94 |
95 |
96 |
97 | junit
98 | junit
99 | test
100 |
101 |
102 |
--------------------------------------------------------------------------------
/maven-plugin/src/test/project-to-test/src/main/java/Main.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | /*
4 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions
8 | are met:
9 |
10 | 1. Redistributions of source code must retain the above copyright
11 | notice, this list of conditions and the following disclaimer.
12 | 2. Redistributions in binary form must reproduce the above copyright
13 | notice, this list of conditions and the following disclaimer in the
14 | documentation and/or other materials provided with the distribution.
15 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
16 | its contributors may be used to endorse or promote products derived
17 | from this software without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
20 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | */
30 |
31 | import com.ea.async.Async;
32 |
33 | import java.util.concurrent.CompletableFuture;
34 |
35 | import static com.ea.async.Async.await;
36 | import static java.util.concurrent.CompletableFuture.completedFuture;
37 |
38 | public class Main
39 | {
40 | static
41 | {
42 | Async.init();
43 | }
44 |
45 |
46 | public static void main(String args[])
47 | {
48 | CompletableFuture futureA = new CompletableFuture<>();
49 | CompletableFuture futureB = new CompletableFuture<>();
50 |
51 | System.out.println("Here is the async method we are going to call");
52 | System.out.println();
53 | System.out.println(" public static CompletableFuture asyncAdd(CompletableFuture a, CompletableFuture b)");
54 | System.out.println(" {");
55 | System.out.println(" return completedFuture(await(a) + await(b));");
56 | System.out.println(" }");
57 | System.out.println();
58 |
59 | System.out.println("Calling the instrumented method, without ea async this would block");
60 | System.out.println(" result = futureA + futureB");
61 | System.out.println();
62 |
63 | CompletableFuture result = asyncAdd(futureA, futureB);
64 |
65 | System.out.println("The method returned a future that is not completed: ");
66 | System.out.println(" result.isDone = " + result.isDone());
67 | System.out.println();
68 |
69 |
70 | System.out.println("Now we complete the futures that are blocking the async method");
71 |
72 | futureA.complete(1);
73 | futureB.complete(2);
74 |
75 | System.out.println(" futureA = " + futureA.join());
76 | System.out.println(" futureB = " + futureB.join());
77 | System.out.println();
78 |
79 | System.out.println("Result is complete because we have completed futureA and futureB");
80 | System.out.println(" result.isDone =" + result.isDone());
81 | System.out.println();
82 |
83 | System.out.println("And here is the result");
84 |
85 | final Integer resultValue = result.join();
86 |
87 | System.out.println(" result = " + resultValue);
88 | System.out.println();
89 | }
90 |
91 | public static CompletableFuture asyncAdd(CompletableFuture a, CompletableFuture b)
92 | {
93 | return completedFuture(await(a) + await(b));
94 | }
95 | }
--------------------------------------------------------------------------------
/maven-plugin/src/test/project-to-test/src/test/java/test/AsyncTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (C) 2015 Electronic Arts Inc. All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14 | its contributors may be used to endorse or promote products derived
15 | from this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | package test;
30 |
31 | import com.ea.async.Async;
32 |
33 | import org.junit.Test;
34 |
35 | import java.util.concurrent.CompletableFuture;
36 |
37 | import static com.ea.async.Async.await;
38 | import static java.util.concurrent.CompletableFuture.completedFuture;
39 | import static org.junit.Assert.*;
40 |
41 | public class AsyncTest
42 | {
43 | static
44 | {
45 | Async.init();
46 | }
47 |
48 | @Test(timeout = 5_000L)
49 | public void testThenCompose()
50 | {
51 | CompletableFuture futureA = new CompletableFuture<>();
52 | CompletableFuture futureB = new CompletableFuture<>();
53 |
54 | // calling the instrumented function
55 | // without async this would block
56 | CompletableFuture result = asyncAdd(futureA, futureB);
57 |
58 | // it is not done because futureA and futureB are not completed
59 | assertFalse(result.isDone());
60 |
61 | futureA.complete(1);
62 | futureB.complete(2);
63 |
64 | // now the result is complete because we have completed futureA and futureB
65 | assertTrue(result.isDone());
66 |
67 | // and here is the result
68 | assertEquals((Integer) 3, result.join());
69 |
70 | }
71 |
72 | public CompletableFuture asyncAdd(CompletableFuture a, CompletableFuture b)
73 | {
74 | return completedFuture(await(a) + await(b));
75 | }
76 | }
--------------------------------------------------------------------------------
/updateDocs.groovy:
--------------------------------------------------------------------------------
1 | import java.nio.charset.StandardCharsets
2 | import java.nio.file.Files
3 | import java.nio.file.Paths
4 |
5 | if (args.length != 1) {
6 | System.err.println("Usage: updateDocVersions ");
7 | return;
8 | }
9 |
10 | def version = args[0]
11 |
12 | Files.walk(Paths.get(".")).forEach({ f ->
13 | def modifiedText = null;
14 | def text = null;
15 | if (f.toString().endsWith(".md")) {
16 | // examples inside .md
17 | text = new String(Files.readAllBytes(f), StandardCharsets.UTF_8);
18 | modifiedText = text.replaceAll("[^<]* ", (String) ("" + version + " "))
19 | modifiedText = modifiedText.replaceAll("ea-async-[.0-9a-zA-Z_-]+[.]jar", (String) ("ea-async-" + version + ".jar"))
20 | modifiedText = modifiedText.replaceAll("(com[.]ea[.]async[:]ea-async[:])[^']*[']", (String) ("com.ea.async:ea-async:" + version + "'"))
21 | }
22 | if (f.toString().matches(".*project-to-test[/\\\\]pom[.]xml\$")) {
23 | // sample project
24 | text = new String(Files.readAllBytes(f), StandardCharsets.UTF_8);
25 | modifiedText = text.replaceAll("(ea-async(-maven-plugin)? \\s*[^<]*( )",
26 | (String) ("\$1>" + version + "\$3"))
27 | }
28 | if (modifiedText != null && !text.equals(modifiedText)) {
29 | println f
30 | Files.write(f, modifiedText.getBytes(StandardCharsets.UTF_8));
31 | }
32 | })
33 |
34 | // this script will run during deployment
35 | //mvn versions:set -DnewVersion=newVer
36 | //mvn clean install
37 | //mvn deploy -PstageRelease -DskipTests=true <--- here
38 | //git add .
39 | //git commit -m "Version newVer"
40 | //git tag -a vnewVer -m "Version newVer"
41 | //git push master --tags
42 | //mvn versions:set -DnewVersion=newVer+1-SNAPSHOT
43 |
--------------------------------------------------------------------------------