Skip to content

Commit

Permalink
Refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
tmurakami committed May 26, 2017
1 parent 2c1f856 commit 0624919
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 103 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@
public class MainActivityTest implements ActivityLifecycleCallback {

@Rule
public final ActivityTestRule<MainActivity> rule = new ActivityTestRule<>(MainActivity.class, true, false);
public final ActivityTestRule<MainActivity> rule =
new ActivityTestRule<>(MainActivity.class, true, false);

@Mock
MainService service;
private MainService service;

private MockitoSession session;

Expand All @@ -48,7 +49,7 @@ public void onActivityLifecycleChanged(Activity activity, Stage stage) {
}

@Test
public void the_title_of_the_MainActivity_should_be_replaced_by_the_given_mock() throws Exception {
public void the_title_of_MainActivity_should_be_replaced_by_the_given_mock() throws Exception {
String s = "test";
given(service.getString(isA(MainActivity.class))).willReturn(s);
assertEquals(s, rule.launchActivity(null).getTitle());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@

import org.junit.Test;

import java.lang.reflect.Modifier;

import static java.lang.reflect.Modifier.isFinal;
import static org.junit.Assert.assertFalse;

public class FinalClassTest {

@Test
public void DexOpener_should_remove_all_final_modifiers() throws Exception {
assertFalse(Modifier.isFinal(FinalClass.class.getModifiers()));
assertFalse(Modifier.isFinal(FinalClass.class.getDeclaredMethod("doIt").getModifiers()));
assertFalse(isFinal(FinalClass.class.getModifiers()));
assertFalse(isFinal(FinalClass.class.getDeclaredMethod("doIt").getModifiers()));
}

private static final class FinalClass {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@
import com.github.tmurakami.classinjector.ClassSources;
import com.github.tmurakami.dexopener.repackaged.org.ow2.asmdex.ApplicationReader;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
Expand Down Expand Up @@ -56,7 +54,7 @@ private ClassSource newDelegate() throws IOException {
for (ZipEntry e; (e = in.getNextEntry()) != null; ) {
String name = e.getName();
if (name.startsWith("classes") && name.endsWith(".dex")) {
byte[] byteCode = readByteCode(in);
byte[] byteCode = IOUtils.readBytes(in);
ApplicationReader ar = new ApplicationReader(ASM4, byteCode);
Set<String> classNames = r.readClassNames(ar);
if (!classNames.isEmpty()) {
Expand All @@ -70,13 +68,4 @@ private ClassSource newDelegate() throws IOException {
return new ClassSources(sources);
}

private static byte[] readByteCode(InputStream in) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buffer = new byte[16384];
for (int l; (l = in.read(buffer)) != -1; ) {
out.write(buffer, 0, l);
}
return out.toByteArray();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.github.tmurakami.dexopener;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

final class IOUtils {

private IOUtils() {
throw new AssertionError("Do not instantiate");
}

static byte[] readBytes(InputStream in) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buffer = new byte[16384];
for (int l; (l = in.read(buffer)) != -1; ) {
out.write(buffer, 0, l);
}
return out.toByteArray();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -32,48 +32,60 @@ public class AndroidClassSourceTest {
public final TemporaryFolder folder = new TemporaryFolder();

@Mock
ClassNameFilter classNameFilter;
private ClassNameFilter classNameFilter;
@Mock
DexClassSourceFactory dexClassSourceFactory;
private DexClassSourceFactory dexClassSourceFactory;
@Mock
ClassSource classSource;
private ClassSource classSource;
@Mock
ClassFile classFile;
private ClassFile classFile;

@Captor
ArgumentCaptor<byte[]> byteCodeCaptor;
private ArgumentCaptor<byte[]> byteCodeCaptor;
@Captor
ArgumentCaptor<Set<String>> classNamesCaptor;
private ArgumentCaptor<Set<String>> classNamesCaptor;

@SuppressWarnings("TryFinallyCanBeTryWithResources")
@Test
public void the_getClassFile_method_should_return_the_ClassFile_with_the_given_name() throws Exception {
public void getClassFile_should_return_the_ClassFile_with_the_given_name() throws Exception {
ApplicationWriter aw = new ApplicationWriter();
aw.visitClass(0, "Lfoo/Bar;", null, "Ljava/lang/Object;", null);
aw.visitClass(0,
"Lfoo/Bar;",
null,
"Ljava/lang/Object;",
null);
aw.visitEnd();
byte[] bytes = aw.toByteArray();
byte[] byteCode = aw.toByteArray();
File apk = folder.newFile();
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(apk));
try {
out.putNextEntry(new ZipEntry("classes.dex"));
out.write(bytes);
out.write(byteCode);
} finally {
out.close();
}
given(classNameFilter.accept("foo.Bar")).willReturn(true);
given(dexClassSourceFactory.newClassSource(byteCodeCaptor.capture(), classNamesCaptor.capture())).willReturn(classSource);
given(dexClassSourceFactory.newClassSource(byteCodeCaptor.capture(),
classNamesCaptor.capture()))
.willReturn(classSource);
given(classSource.getClassFile("foo.Bar")).willReturn(classFile);
AndroidClassSource testTarget = new AndroidClassSource(apk.getCanonicalPath(), classNameFilter, dexClassSourceFactory);
AndroidClassSource testTarget = new AndroidClassSource(apk.getCanonicalPath(),
classNameFilter,
dexClassSourceFactory);
assertSame(classFile, testTarget.getClassFile("foo.Bar"));
assertArrayEquals(bytes, byteCodeCaptor.getValue());
assertArrayEquals(byteCode, byteCodeCaptor.getValue());
Set<String> classNames = classNamesCaptor.getValue();
assertEquals(1, classNames.size());
assertEquals("foo.Bar", classNames.iterator().next());
}

@Test
public void the_getClassFile_method_should_return_null_if_the_class_name_does_not_pass_the_ClassNameFilter() throws Exception {
assertNull(new AndroidClassSource("", classNameFilter, dexClassSourceFactory).getClassFile("foo.Bar"));
public void getClassFile_should_return_null_if_the_given_name_does_not_pass_through_the_filter()
throws Exception {
AndroidClassSource classSource = new AndroidClassSource("",
classNameFilter,
dexClassSourceFactory);
assertNull(classSource.getClassFile("foo.Bar"));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public static Iterable<Object[]> parameters() {
}

@Test
public void the_accept_method_should_return_a_value_equal_to_the_expected_value() throws Exception {
public void accept_should_return_a_value_equal_to_the_expected_value() throws Exception {
assertSame(expected, testTarget.accept(className));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,37 +13,37 @@

import static com.github.tmurakami.dexopener.repackaged.org.ow2.asmdex.Opcodes.ASM4;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.BDDMockito.given;

@RunWith(MockitoJUnitRunner.StrictStubs.class)
public class ClassNameReaderTest {

@InjectMocks
ClassNameReader testTarget;
private ClassNameReader testTarget;

@Mock
ClassNameFilter filter;
private ClassNameFilter filter;

@Test
public void the_readClassNames_method_should_read_class_names_that_pass_the_ClassNameFilter() throws Exception {
public void readClassNames_should_return_only_class_names_that_passed_through_the_filter()
throws Exception {
given(filter.accept("foo.Bar")).willReturn(true);
ApplicationWriter aw = new ApplicationWriter();
aw.visitClass(0, "Lfoo/Bar;", null, "Ljava/lang/Object;", null);
aw.visitClass(0,
"Lfoo/Bar;",
null,
"Ljava/lang/Object;",
null);
aw.visitClass(0,
"Lfoo/bar/Baz;",
null,
"Ljava/lang/Object;",
null);
aw.visitEnd();
byte[] bytes = aw.toByteArray();
Set<String> classNames = testTarget.readClassNames(new ApplicationReader(ASM4, bytes));
byte[] byteCode = aw.toByteArray();
Set<String> classNames = testTarget.readClassNames(new ApplicationReader(ASM4, byteCode));
assertEquals(1, classNames.size());
assertEquals("foo.Bar", classNames.iterator().next());
}

@Test
public void the_readClassNames_method_should_not_read_class_names_that_do_not_pass_the_ClassNameFilter() throws Exception {
ApplicationWriter aw = new ApplicationWriter();
aw.visitClass(0, "Lfoo/Bar;", null, "Ljava/lang/Object;", null);
aw.visitEnd();
byte[] bytes = aw.toByteArray();
assertTrue(testTarget.readClassNames(new ApplicationReader(ASM4, bytes)).isEmpty());
}

}
Loading

0 comments on commit 0624919

Please sign in to comment.