package com.limegroup.gnutella.messages.vendor;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.zip.Inflater;
import org.hamcrest.Matchers;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.limewire.inspection.Inspector;
import org.limewire.io.GGEP;
import org.limewire.io.GUID;
import org.limewire.util.CommonUtils;
import junit.framework.Test;
import com.google.inject.AbstractModule;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.limegroup.bittorrent.bencoding.Token;
import com.limegroup.gnutella.LimeTestUtils;
import com.limegroup.gnutella.util.FECUtils;
import com.limegroup.gnutella.util.LimeTestCase;
public class InspectionResponseFactoryImplTest extends LimeTestCase {
public InspectionResponseFactoryImplTest(String name) {
super(name);
}
public static Test suite() {
return buildTestSuite(InspectionResponseFactoryImplTest.class);
}
private Mockery mockery;
private Inspector inspector;
private Injector injector;
private FECUtils fecUtils;
@Override
public void setUp() throws Exception {
mockery = new Mockery();
inspector = mockery.mock(Inspector.class);
fecUtils = mockery.mock(FECUtils.class);
Module m = new AbstractModule() {
@Override
public void configure() {
bind(Inspector.class).toInstance(inspector);
bind(FECUtils.class).toInstance(fecUtils);
}
};
injector = LimeTestUtils.createInjector(m);
}
public void testLoadsProperties() throws Exception {
final File props = new File(CommonUtils.getCurrentDirectory(),"inspection.props");
mockery.checking(new Expectations() {{
one(inspector).load(props);
}});
injector.getInstance(InspectionResponseFactoryImpl.class); // loads the props
mockery.assertIsSatisfied();
}
private Expectations createExpectations(InspectionRequest request,
final boolean supported,
final Object inspectedValue) throws Exception {
return createExpectations(request, supported, inspectedValue, (new GUID()).bytes());
}
private Expectations createExpectations(final InspectionRequest request,
final boolean supported,
final Object inspectedValue,
final byte[] guid)
throws Exception {
return new Expectations() {{
allowing(inspector).load(with(Matchers.any(File.class)));
one(request).getRequestedFields();
will(returnValue(new String[]{"asdf"}));
one(request).requestsTimeStamp();
will(returnValue(Boolean.TRUE));
allowing(request).supportsEncoding();
will(returnValue(supported));
allowing(request).getGUID();
will(returnValue(guid));
one(inspector).inspect("asdf");
will(returnValue(inspectedValue));
}};
}
@SuppressWarnings("unchecked")
public void testRespondsToRequest() throws Exception {
final InspectionRequest request = mockery.mock(InspectionRequest.class);
mockery.checking(createExpectations(request, false, "inspected"));
InspectionResponseFactory factory = injector.getInstance(InspectionResponseFactoryImpl.class);
InspectionResponse[] resp = factory.createResponses(request);
mockery.assertIsSatisfied();
assertEquals(1, resp.length);
assertNotNull(resp[0]);
byte [] payload = resp[0].getPayload();
Inflater i = new Inflater();
i.setInput(payload);
i.finished();
byte [] uncompressed = new byte[1024];
i.inflate(uncompressed);
Map<String,Object> o = (Map<String,Object>) Token.parse(uncompressed);
assertTrue(o.containsKey("-1"));
assertTrue(Arrays.equals("inspected".getBytes(),(byte[])o.get("0")));
}
@SuppressWarnings("unchecked")
public void testTooSmallNotEncoded() throws Exception {
final InspectionRequest request = mockery.mock(InspectionRequest.class);
mockery.checking(createExpectations(request, true, "inspected"));
InspectionResponseFactory factory = injector.getInstance(InspectionResponseFactoryImpl.class);
InspectionResponse[] resp = factory.createResponses(request);
mockery.assertIsSatisfied();
assertEquals(1, resp.length);
assertNotNull(resp[0]);
byte [] payload = resp[0].getPayload();
Inflater i = new Inflater();
i.setInput(payload);
i.finished();
byte [] uncompressed = new byte[1024];
i.inflate(uncompressed);
Map<String,Object> o = (Map<String,Object>) Token.parse(uncompressed);
assertTrue(o.containsKey("-1"));
assertTrue(Arrays.equals("inspected".getBytes(),(byte[])o.get("0")));
}
@SuppressWarnings("unchecked")
public void testNotSupported() throws Exception {
final InspectionRequest request = mockery.mock(InspectionRequest.class);
byte [] data = new byte[10000];
Random r = new Random();
r.nextBytes(data);
mockery.checking(createExpectations(request, false, data));
InspectionResponseFactory factory = injector.getInstance(InspectionResponseFactoryImpl.class);
InspectionResponse[] resp = factory.createResponses(request);
mockery.assertIsSatisfied();
assertEquals(1, resp.length);
assertNotNull(resp[0]);
byte [] payload = resp[0].getPayload();
Inflater i = new Inflater();
i.setInput(payload);
i.finished();
byte [] uncompressed = new byte[1024 * 20];
i.inflate(uncompressed);
Map<String,Object> o = (Map<String,Object>) Token.parse(uncompressed);
assertTrue(o.containsKey("-1"));
assertTrue(Arrays.equals(data,(byte[])o.get("0")));
}
public void testEncoded() throws Exception {
final InspectionRequest request = mockery.mock(InspectionRequest.class);
final byte [] data = new byte[3000];
Random r = new Random();
r.nextBytes(data);
byte [] guid = new byte[16];
r.nextBytes(guid);
mockery.checking(createExpectations(request, true, data, guid));
final List<byte []> chunks= new ArrayList<byte[]> ();
for (int i = 0; i < 5; i++) {
byte [] b = new byte[1];
b[0] = (byte)i;
chunks.add(b);
}
mockery.checking(new Expectations() {{
one(fecUtils).encode(with(Matchers.any(byte[].class)), // this is the bencoded & compressed data
with(Matchers.equalTo(1300)),
with(Matchers.equalTo(1.2f)));
will(returnValue(chunks));
}});
InspectionResponseFactory factory = injector.getInstance(InspectionResponseFactoryImpl.class);
InspectionResponse[] resp = factory.createResponses(request);
mockery.assertIsSatisfied();
assertEquals(5, resp.length);
for (int i = 0; i < resp.length; i++) {
InspectionResponse response = resp[i];
// make sure its definitely smaller than the fragmentation limit
assertLessThan(1400, response.getTotalLength());
assertEquals(2, response.getVersion());
assertTrue(Arrays.equals(guid, response.getGUID()));
GGEP g = new GGEP(response.getPayload(),0);
assertEquals(i, g.getInt("I")); // chunk id
assertEquals(5, g.getInt("T")); // total chunks
assertGreaterThan(3000, g.getInt("L")); // length = 3000 bytes+ overhead
assertLessThan(3200, g.getInt("L"));
byte [] chunk = g.get("D");
assertEquals(1, chunk.length);
assertEquals(i, chunk[0]);
}
}
}