/*
* Copyright 2010-2011 Ning, Inc.
*
* Ning licenses this file to you under the Apache License, version 2.0
* (the "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package com.ning.metrics.eventtracker;
import com.ning.metrics.serialization.event.SmileEnvelopeEvent;
import com.ning.metrics.serialization.smile.SmileEnvelopeEventSerializer;
import com.ning.metrics.serialization.writer.CallbackHandler;
import com.ning.metrics.serialization.writer.DiskSpoolEventWriter;
import com.ning.metrics.serialization.writer.EventHandler;
import com.ning.metrics.serialization.writer.NoCompressionCodec;
import com.ning.metrics.serialization.writer.SyncType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.dataformat.smile.SmileFactory;
import com.fasterxml.jackson.dataformat.smile.SmileGenerator;
import com.fasterxml.jackson.dataformat.smile.SmileParser;
import org.joda.time.DateTime;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.HashMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
public class TestInvalidPayload
{
protected static final SmileFactory smileFactory = new SmileFactory();
static {
// yes, full 'compression' by checking for repeating names, short string values:
smileFactory.configure(SmileGenerator.Feature.CHECK_SHARED_NAMES, true);
smileFactory.configure(SmileGenerator.Feature.CHECK_SHARED_STRING_VALUES, true);
// and for now let's not mandate header for input
smileFactory.configure(SmileParser.Feature.REQUIRE_HEADER, false);
}
private final ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(1);
private String spoolPath;
private File spoolDir;
private File tmpDir;
private File quarantineDir;
private File lockDir;
private class TestEventHandler implements EventHandler
{
@Override
public void handle(File file, CallbackHandler handler)
{
}
}
@BeforeMethod(alwaysRun = true)
public void setUp() throws Exception
{
spoolPath = System.getProperty("java.io.tmpdir") + "/diskspooleventwriter-" + System.currentTimeMillis();
spoolDir = new File(spoolPath);
tmpDir = new File(spoolDir, "_tmp");
quarantineDir = new File(spoolDir, "_quarantine");
lockDir = new File(spoolDir, "_lock");
prepareSpoolDirs();
}
@AfterMethod(alwaysRun = true)
public void tearDown() throws Exception
{
prepareSpoolDirs();
}
@Test(groups = "fast")
public void testWriteBadSmile() throws Exception
{
Assert.assertNull(listBinFiles(spoolDir));
final DiskSpoolEventWriter writer = new DiskSpoolEventWriter(new TestEventHandler(), spoolPath, true, 1, executor,
SyncType.NONE, 1, new NoCompressionCodec(), new SmileEnvelopeEventSerializer(false));
try {
writer.write(makeFailingEvent());
Assert.fail();
}
catch (IOException e) {
Assert.assertEquals(e.getCause().getClass(), JsonMappingException.class);
// No file is currently being written (since the file was just moved aside)
Assert.assertEquals(listBinFiles(tmpDir).length, 0);
Assert.assertEquals(listBinFiles(spoolDir).length, 1);
}
writer.write(makeValidEvent());
// One file being written (containing the valid event)
Assert.assertEquals(listBinFiles(tmpDir).length, 1);
// One file set aside (containing the invalid stream)
Assert.assertEquals(listBinFiles(spoolDir).length, 1);
// Make sure it still works
writer.write(makeValidEvent());
// One file being written (containing the valid event)
Assert.assertEquals(listBinFiles(tmpDir).length, 1);
// One file set aside (containing the invalid stream)
Assert.assertEquals(listBinFiles(spoolDir).length, 1);
}
private void prepareSpoolDirs()
{
cleanDirectory(spoolDir);
cleanDirectory(tmpDir);
cleanDirectory(quarantineDir);
cleanDirectory(lockDir);
}
private File[] listBinFiles(final File dir)
{
return dir.listFiles(new FileFilter()
{
@Override
public boolean accept(final File pathname)
{
return pathname.getName().endsWith(".bin");
}
});
}
private void cleanDirectory(final File quarantineDir)
{
if (quarantineDir.exists()) {
for (final File file : quarantineDir.listFiles()) {
if (file.isFile()) {
file.delete();
}
}
}
}
private SmileEnvelopeEvent makeFailingEvent() throws IOException
{
final HashMap<String, Object> map = new HashMap<String, Object>();
map.put("invlidUtf8", "\uD800");
map.put("theNumberFive", 5);
return new SmileEnvelopeEvent("sample", new DateTime(), map);
}
private SmileEnvelopeEvent makeValidEvent() throws IOException
{
final HashMap<String, Object> map = new HashMap<String, Object>();
map.put("theNumberFive", 5);
return new SmileEnvelopeEvent("sample", new DateTime(), map);
}
}