Skip to content

Commit 89eafab

Browse files
committed
merge from upstream
2 parents 4889d7d + b1655b4 commit 89eafab

File tree

98 files changed

+4005
-6
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

98 files changed

+4005
-6
lines changed

src/main/java/org/teachingkidsprogramming/section05recursion/SpiderWeb.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,17 @@ public static void main(String[] args)
1919
//
2020
// ------------- Recipe for drawTriangle --#4.2
2121
// Do the following 3 times --#3
22-
// Move the tortoise the length of a line --#1.1
22+
// Move the tortoise the current length (of the line) --#1.1
2323
// Turn the tortoise 1/3rd of 360 degrees --#2
2424
// Repeat
2525
// ------------- End of drawTriangle recipe --#4.3
2626
//
2727
// Turn the tortoise 1/6th of 360 degrees to the right --#7
28-
// Increase the length of the line by the current zoom --#8.1
28+
// Increase the current length (of the line) by the current zoom --#8.1
2929
// Repeat --#5.2
30-
// ------------- End of weaveOneLayer recipe --#9.2
30+
// ------------- End of weaveOneLayer recipe --#9.3
3131
//
32-
// Change the zoom so it is multiplied by 1.3 --#11
32+
// Change the current zoom so it is multiplied by 1.3 --#11
3333
// Repeat
3434
}
3535
}

src/main/java/org/teachingkidsprogramming/section05recursion/TreeQuiz.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public void questions1To4()
2222
// Question 3
2323
// setNinety (recipe below)
2424
// ------------- Recipe for setNinety
25-
// set the current turn angle to 90, HINT: Use angles
25+
// set the current turn angle to 90, HINT: Use angles.put(key,value);
2626
// ------------- End of setNinety recipe
2727
//
2828
// Question 4
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package org.teachingextensions.approvals.lite;
2+
3+
public interface ApprovalApprover {
4+
boolean approve() throws Exception;
5+
6+
public void cleanUpAfterSuccess(ApprovalFailureReporter reporter) throws Exception;
7+
8+
void fail();
9+
10+
void reportFailure(ApprovalFailureReporter reporter) throws Exception;
11+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package org.teachingextensions.approvals.lite;
2+
3+
4+
public interface ApprovalFailureOverrider extends ApprovalFailureReporter {
5+
public boolean askToChangeReceivedToApproved(String received, String approved) throws Exception;
6+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package org.teachingextensions.approvals.lite;
2+
3+
public interface ApprovalFailureReporter {
4+
public void report(String received, String approved) throws Exception;
5+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package org.teachingextensions.approvals.lite;
2+
3+
public interface ApprovalReporterWithCleanUp {
4+
public void cleanUp(String received, String approved) throws Exception;
5+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package org.teachingextensions.approvals.lite;
2+
3+
4+
public interface ApprovalWriter {
5+
public String writeReceivedFile(String received) throws Exception;
6+
7+
public String getReceivedFilename(String base);
8+
9+
public String getApprovalFilename(String base);
10+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package org.teachingextensions.approvals.lite;
2+
3+
import org.teachingextensions.approvals.lite.ReporterFactory.FileTypes;
4+
import org.teachingextensions.approvals.lite.namer.ApprovalNamer;
5+
import org.teachingextensions.approvals.lite.namer.JUnitStackTraceNamer;
6+
import org.teachingextensions.approvals.lite.util.ArrayUtils;
7+
import org.teachingextensions.approvals.lite.util.ObjectUtils;
8+
import org.teachingextensions.approvals.lite.util.StringUtils;
9+
import org.teachingextensions.approvals.lite.util.lambda.Function1;
10+
import org.teachingextensions.approvals.lite.writers.ApprovalTextWriter;
11+
import org.teachingextensions.approvals.lite.writers.ComponentApprovalWriter;
12+
import org.teachingextensions.approvals.lite.writers.ImageApprovalWriter;
13+
14+
import java.awt.*;
15+
import java.awt.image.BufferedImage;
16+
import java.util.Arrays;
17+
18+
public class Approvals {
19+
public static void verify(String response) throws Exception {
20+
verify(new ApprovalTextWriter(response, "txt"), FileTypes.Text);
21+
}
22+
23+
public static <T> void verifyAll(String header, T[] values) {
24+
Approvals.verifyAll(header, Arrays.asList(values));
25+
}
26+
27+
public static <T> void verifyAll(String header, Iterable<T> values) {
28+
Approvals.verifyAll(header, values, new Function1<T, String>() {
29+
@Override
30+
public String call(T i) {
31+
return i + "";
32+
}
33+
});
34+
35+
}
36+
37+
public static <T> void verifyAll(String header, T[] values,
38+
Function1<T, String> f1) {
39+
verifyAll(header, Arrays.asList(values), f1);
40+
}
41+
42+
public static <T> void verifyAll(String header, Iterable<T> array,
43+
Function1<T, String> f1) {
44+
String text = formatHeader(header) + ArrayUtils.toString(array, f1);
45+
verify(new ApprovalTextWriter(text, "txt"), FileTypes.Text);
46+
}
47+
48+
private static String formatHeader(String header) {
49+
return StringUtils.isEmpty(header) ? "" : header + "\r\n\r\n\r\n";
50+
}
51+
52+
public static void verifyHtml(String response) throws Exception {
53+
verify(new ApprovalTextWriter(response, "html"), FileTypes.Html);
54+
}
55+
56+
public static void verify(Component component) {
57+
BufferedImage image = ComponentApprovalWriter.drawComponent(component);
58+
Approvals.verify(image);
59+
}
60+
61+
public static void verify(BufferedImage bufferedImage) {
62+
verify(new ImageApprovalWriter(bufferedImage), FileTypes.Image);
63+
}
64+
65+
public static void verify(ApprovalWriter writer, ApprovalNamer namer,
66+
ApprovalFailureReporter reporter) {
67+
verify(new FileApprover(writer, namer), reporter);
68+
}
69+
70+
public static void verify(ApprovalWriter writer, String fileType) {
71+
verify(writer, createApprovalNamer(), ReporterFactory.get(fileType));
72+
}
73+
74+
public static void verify(FileApprover approver,
75+
ApprovalFailureReporter reporter) {
76+
try {
77+
if (!approver.approve()) {
78+
boolean passed = false;
79+
if (reporter instanceof ApprovalFailureOverrider) {
80+
passed = approver
81+
.askToChangeReceivedToApproved((ApprovalFailureOverrider) reporter);
82+
}
83+
if (!passed) {
84+
approver.reportFailure(reporter);
85+
approver.fail();
86+
} else {
87+
approver.cleanUpAfterSuccess(reporter);
88+
}
89+
} else {
90+
approver.cleanUpAfterSuccess(reporter);
91+
}
92+
} catch (Exception e) {
93+
throw ObjectUtils.throwAsError(e);
94+
}
95+
}
96+
97+
public static ApprovalNamer createApprovalNamer() {
98+
return new JUnitStackTraceNamer();
99+
}
100+
101+
public static void verify(Object o) throws Exception {
102+
Approvals.verify(o + "");
103+
}
104+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package org.teachingextensions.approvals.lite;
2+
3+
import junit.framework.TestCase;
4+
import org.teachingextensions.approvals.lite.namer.ApprovalNamer;
5+
import org.teachingextensions.approvals.lite.namer.NamerFactory;
6+
import org.teachingextensions.approvals.lite.util.ObjectUtils;
7+
import org.teachingextensions.approvals.lite.util.io.FileUtils;
8+
9+
import java.io.File;
10+
import java.io.IOException;
11+
12+
public class FileApprover implements ApprovalApprover {
13+
private File received;
14+
private File approved;
15+
private final ApprovalWriter writter;
16+
17+
public FileApprover(ApprovalWriter writter, ApprovalNamer namer) {
18+
this.writter = writter;
19+
String base = String.format("%s%s%s", namer.getSourceFilePath(), namer.getApprovalName(),
20+
NamerFactory.getAndClearAdditionalInformation());
21+
received = new File(writter.getReceivedFilename(base));
22+
approved = new File(writter.getApprovalFilename(base));
23+
}
24+
25+
public boolean approve() throws Exception {
26+
received = new File(writter.writeReceivedFile(received.getAbsolutePath()));
27+
return approveTextFile(received, approved);
28+
}
29+
30+
public void cleanUpAfterSuccess(ApprovalFailureReporter reporter) throws Exception {
31+
received.delete();
32+
if (reporter instanceof ApprovalReporterWithCleanUp) {
33+
((ApprovalReporterWithCleanUp) reporter).cleanUp(received.getAbsolutePath(), approved.getAbsolutePath());
34+
}
35+
}
36+
37+
public void reportFailure(ApprovalFailureReporter reporter) throws Exception {
38+
reporter.report(received.getAbsolutePath(), approved.getAbsolutePath());
39+
}
40+
41+
public void fail() {
42+
TestCase.assertEquals("Failed Approval", approved.getAbsolutePath(), received.getAbsolutePath());
43+
}
44+
45+
public static boolean approveTextFile(File expected, File actual) throws IOException {
46+
if (!expected.exists() || !actual.exists()) {
47+
return false;
48+
}
49+
String t1 = FileUtils.readFile(expected);
50+
String t2 = FileUtils.readFile(actual);
51+
return ObjectUtils.isEqual(t1, t2);
52+
}
53+
54+
public boolean askToChangeReceivedToApproved(ApprovalFailureOverrider reporter) throws Exception {
55+
return reporter.askToChangeReceivedToApproved(received.getAbsolutePath(), approved.getAbsolutePath());
56+
}
57+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package org.teachingextensions.approvals.lite;
2+
3+
import org.teachingextensions.approvals.lite.reporters.*;
4+
import org.teachingextensions.approvals.lite.util.ClassUtils;
5+
6+
import java.lang.annotation.Annotation;
7+
import java.lang.reflect.Method;
8+
import java.util.ArrayList;
9+
import java.util.HashMap;
10+
import java.util.List;
11+
12+
public class ReporterFactory {
13+
private static HashMap<String, Class<? extends ApprovalFailureReporter>> reporters = new HashMap<>();
14+
15+
public static class FileTypes {
16+
public static final String Text = "txt";
17+
public static final String Html = "html";
18+
public static final String Excel = "csv";
19+
public static final String File = "file";
20+
public static final String Image = "png";
21+
private static final String Default = "default";
22+
}
23+
24+
static {
25+
setupReporters();
26+
}
27+
28+
public static ApprovalFailureReporter get(String string) {
29+
ApprovalFailureReporter returned = getFromAnnotation();
30+
returned = tryFor(returned, reporters.get(string));
31+
returned = tryFor(returned, reporters.get(FileTypes.Default));
32+
return returned;
33+
}
34+
35+
public static ApprovalFailureReporter getFromAnnotation() {
36+
UseReporter reporter = getAnnotationFromStackTrace(UseReporter.class);
37+
return reporter == null ? null : getReporter(reporter);
38+
}
39+
40+
private static ApprovalFailureReporter getReporter(UseReporter reporter) {
41+
Class<? extends ApprovalFailureReporter>[] classes = reporter.value();
42+
List<ApprovalFailureReporter> reporters = new ArrayList<>();
43+
for (Class<? extends ApprovalFailureReporter> clazz : classes) {
44+
ApprovalFailureReporter instance = ClassUtils.create(clazz);
45+
reporters.add(instance);
46+
}
47+
return reporters.size() == 1 ? reporters.get(0) : new MultiReporter(reporters);
48+
}
49+
50+
private static <T extends Annotation> T getAnnotationFromStackTrace(Class<T> annotationClass) {
51+
StackTraceElement[] trace = Thread.currentThread().getStackTrace();
52+
for (StackTraceElement stack : trace) {
53+
Method method = null;
54+
Class<?> clazz = null;
55+
try {
56+
String methodName = stack.getMethodName();
57+
clazz = Class.forName(stack.getClassName());
58+
method = clazz.getMethod(methodName, (Class<?>[]) null);
59+
} catch (Exception e) {
60+
//ignore
61+
}
62+
T annotation = null;
63+
if (method != null) {
64+
annotation = method.getAnnotation(annotationClass);
65+
}
66+
if (annotation != null) {
67+
return annotation;
68+
}
69+
annotation = clazz != null ? clazz.getAnnotation(annotationClass) : null;
70+
if (annotation != null) {
71+
return annotation;
72+
}
73+
}
74+
return null;
75+
}
76+
77+
private static ApprovalFailureReporter tryFor(ApprovalFailureReporter returned,
78+
Class<? extends ApprovalFailureReporter> trying) {
79+
if (returned == null && trying != null) {
80+
return ClassUtils.create(trying);
81+
}
82+
return returned;
83+
}
84+
85+
private static void setupReporters() {
86+
reporters.put(FileTypes.Text, DiffReporter.class);
87+
reporters.put(FileTypes.Html, DiffReporter.class);
88+
reporters.put(FileTypes.Excel, FileLauncherReporter.class);
89+
reporters.put(FileTypes.File, FileLauncherReporter.class);
90+
reporters.put(FileTypes.Image, ImageReporter.class);
91+
reporters.put(FileTypes.Default, QuietReporter.class);
92+
}
93+
}

0 commit comments

Comments
 (0)