/* * Copyright (c) 2014 Red Hat, Inc. and/or its affiliates. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Cheng Fang - Initial API and implementation */ package org.jberet.support.io; import java.io.InputStream; import java.net.URI; import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Properties; import java.util.concurrent.TimeUnit; import javax.batch.operations.JobOperator; import javax.batch.runtime.BatchRuntime; import javax.batch.runtime.BatchStatus; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.MappingJsonFactory; import com.fasterxml.jackson.databind.node.ArrayNode; import com.mongodb.DB; import com.mongodb.DBCollection; import com.mongodb.DBCursor; import com.mongodb.DBObject; import com.mongodb.Mongo; import com.mongodb.MongoClient; import com.mongodb.MongoClientURI; import com.mongodb.util.JSON; import org.jberet.runtime.JobExecutionImpl; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; /** * A test class that reads resource from MongoDB and writes to another MongoDB collection. */ public final class MongoItemReaderTest { static MongoClient mongoClient; static DB db; static final String jobName = "org.jberet.support.io.MongoItemReaderTest"; private final JobOperator jobOperator = BatchRuntime.getJobOperator(); static final String databaseName = "testData"; static final String mongoClientUri = "mongodb://localhost/" + databaseName; static final String movieCollection = "movies"; static final String movieOutCollection = "movies.out"; static final String githubDataCollection = "githubData"; static final String githubDataOutCollection = "githubData.out"; @BeforeClass public static void beforeClass() throws Exception { mongoClient = (MongoClient) Mongo.Holder.singleton().connect(new MongoClientURI(mongoClientUri)); db = mongoClient.getDB(databaseName); } @Before public void before() throws Exception { dropCollection(movieOutCollection); addTestData(JsonItemReaderTest.movieJson, movieCollection, 100); } @Test public void testMongoGithubData() throws Exception { dropCollection(githubDataOutCollection); addTestData(JsonItemReaderTest.githubJson, githubDataCollection, 5); testReadWrite0(mongoClientUri, null, null, -1, GithubData.class, "{_id : 0}", githubDataCollection, githubDataOutCollection, null, null); } @Test public void testMongoMovieBeanTypeLimit2() throws Exception { testReadWrite0(mongoClientUri, null, "2", 2, Movie.class, null, movieCollection, movieOutCollection, MovieTest.expect1_2, MovieTest.forbid1_2); } @Test public void testMongoMovieBeanTypeLimit3Skip1() throws Exception { testReadWrite0(null, "1", "3", 3, Movie.class, null, movieCollection, movieOutCollection, MovieTest.expect2_4, MovieTest.forbid2_4); } @Test public void testMongoMovieBeanTypeFull() throws Exception { testReadWrite0(null, null, null, 100, Movie.class, null, movieCollection, movieOutCollection, MovieTest.expectFull, null); } private void testReadWrite0(final String uri, final String skip, final String limit, final int size, final Class<?> beanType, final String projection, final String collection, final String collectionOut, final String expect, final String forbid) throws Exception { final Properties params = CsvItemReaderWriterTest.createParams(CsvProperties.BEAN_TYPE_KEY, beanType.getName()); params.setProperty("collection", collection); params.setProperty("collection.out", collectionOut); if (uri != null) { params.setProperty("uri", uri); } if (projection != null) { params.setProperty("projection", projection); } if (skip != null) { params.setProperty("skip", skip); } if (limit != null) { params.setProperty("limit", limit); } final long jobExecutionId = jobOperator.start(jobName, params); final JobExecutionImpl jobExecution = (JobExecutionImpl) jobOperator.getJobExecution(jobExecutionId); jobExecution.awaitTermination(CsvItemReaderWriterTest.waitTimeoutMinutes, TimeUnit.MINUTES); Assert.assertEquals(BatchStatus.COMPLETED, jobExecution.getBatchStatus()); validate(size, expect, forbid); } static void dropCollection(final String coll) throws Exception { final DBCollection collection = db.getCollection(coll); collection.drop(); } static void addTestData(final String dataResource, final String mongoCollection, final int minSizeIfExists) throws Exception { final DBCollection collection = db.getCollection(mongoCollection); if (collection.find().count() >= minSizeIfExists) { System.out.printf("The readCollection %s already contains 100 items, skip adding test data.%n", mongoCollection); return; } InputStream inputStream = MongoItemReaderTest.class.getClassLoader().getResourceAsStream(dataResource); if (inputStream == null) { try { final URL url = new URI(dataResource).toURL(); inputStream = url.openStream(); } catch (final Exception e) { System.out.printf("Failed to convert dataResource %s to URL: %s%n", dataResource, e); } } if (inputStream == null) { throw new IllegalStateException("The inputStream for the test data is null"); } final JsonFactory jsonFactory = new MappingJsonFactory(); final JsonParser parser = jsonFactory.createParser(inputStream); final JsonNode arrayNode = parser.readValueAs(ArrayNode.class); final Iterator<JsonNode> elements = arrayNode.elements(); final List<DBObject> dbObjects = new ArrayList<DBObject>(); while (elements.hasNext()) { final DBObject dbObject = (DBObject) JSON.parse(elements.next().toString()); dbObjects.add(dbObject); } collection.insert(dbObjects); } static void validate(final int size, final String expect, final String forbid) { final DBCollection collection = db.getCollection(movieOutCollection); final DBCursor cursor = collection.find(); try { //if size is negative number, it means the size is unknown and so skip the size check. if (size >= 0) { Assert.assertEquals(size, cursor.size()); } final List<String> expects = new ArrayList<String>(); String[] forbids = CellProcessorConfig.EMPTY_STRING_ARRAY; if (expect != null && !expect.isEmpty()) { Collections.addAll(expects, expect.split(",")); } if (forbid != null && !forbid.isEmpty()) { forbids = forbid.split(","); } if (expects.size() == 0 && forbids.length == 0) { return; } while (cursor.hasNext()) { final DBObject next = cursor.next(); final String stringValue = next.toString(); for (final String s : forbids) { if (stringValue.contains(s.trim())) { throw new IllegalStateException("Forbidden string found: " + s); } } for (final Iterator<String> it = expects.iterator(); it.hasNext(); ) { final String s = it.next(); if (stringValue.contains(s.trim())) { System.out.printf("Found expected string: %s%n", s); it.remove(); } } } if (expects.size() > 0) { throw new IllegalStateException("Some expected strings are still not found: " + expects); } } finally { cursor.close(); } } }