/**
* Licensed to The Apereo Foundation under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
*
* The Apereo Foundation licenses this file to you under the Educational
* Community 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://opensource.org/licenses/ecl2.txt
*
* 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 org.opencastproject.workflow.handler.composer;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.opencastproject.util.UrlSupport.uri;
import static org.opencastproject.workflow.handler.composer.ImageWorkflowOperationHandler.limit;
import static org.opencastproject.workflow.handler.composer.ImageWorkflowOperationHandler.toSeconds;
import static org.opencastproject.workflow.handler.composer.ImageWorkflowOperationHandler.validateTargetBaseNameFormat;
import org.opencastproject.composer.api.EncodingProfile;
import org.opencastproject.mediapackage.MediaPackageElementFlavor;
import org.opencastproject.mediapackage.Track;
import org.opencastproject.workflow.handler.composer.ImageWorkflowOperationHandler.Cfg;
import org.opencastproject.workflow.handler.composer.ImageWorkflowOperationHandler.Extractor;
import org.opencastproject.workflow.handler.composer.ImageWorkflowOperationHandler.MediaPosition;
import org.opencastproject.workflow.handler.composer.ImageWorkflowOperationHandler.MediaPositionParser;
import org.opencastproject.workflow.handler.composer.ImageWorkflowOperationHandler.PositionType;
import com.entwinemedia.fn.data.ListBuilder;
import com.entwinemedia.fn.data.ListBuilders;
import com.entwinemedia.fn.data.Opt;
import com.entwinemedia.fn.parser.Result;
import org.easymock.EasyMock;
import org.junit.Test;
import java.util.List;
public class ImageWorkflowOperationHandlerTest {
private static final ListBuilder l = ListBuilders.strictImmutableArray;
@Test
public void testMediaPositionParserSuccess() {
test("75900000000001", sec(75900000000001d));
test("10, 20.3", sec(10), sec(20.3));
test("10 20.3", sec(10), sec(20.3));
test("1020.3", sec(1020.3));
test("10 , 20.3", sec(10), sec(20.3));
test("10 20.3", sec(10), sec(20.3));
test("15", sec(15));
test("11%", percent(11));
test(" 19.70% , 20.3", percent(19.7), sec(20.3));
test(" 10.62% 20.3 14.2 ", percent(10.62), sec(20.3), sec(14.2));
test("10.62% 20.3 ,14.213%", percent(10.62), sec(20.3), percent(14.213));
}
@Test
public void testMediaPositionParserFailure() {
assertFalse(testSuccess(" ") || testSuccess(" ") || testSuccess(",, ,") || testSuccess("")
|| testSuccess("10a,10b"));
}
@Test
public void testFileNameGeneration() {
final ImageWorkflowOperationHandler dummy = new ImageWorkflowOperationHandler();
assertEquals("thumbnail_12_5p_small.jpg",
new Extractor(dummy, cfg(Opt.<String> none(), Opt.some("thumbnail_%.1fp%s"))).createFileName("_small.jpg",
uri("http://localhost/path/filename.mp4"), new MediaPosition(PositionType.Percentage, 12.5)));
assertEquals("thumbnail_0p.jpg",
new Extractor(dummy, cfg(Opt.<String> none(), Opt.some("thumbnail_%.0fp%s"))).createFileName(".jpg",
uri("http://localhost/path/filename.mp4"), new MediaPosition(PositionType.Percentage, 0)));
assertEquals("video_14_200s.jpg",
new Extractor(dummy, cfg(Opt.<String> none(), Opt.<String> none())).createFileName(".jpg",
uri("http://localhost/path/video.mp4"), new MediaPosition(PositionType.Seconds, 14.2)));
assertEquals("video_15_110s_medium.jpg",
new Extractor(dummy, cfg(Opt.<String> none(), Opt.<String> none())).createFileName("_medium.jpg",
uri("http://localhost/path/video.mp4"), new MediaPosition(PositionType.Seconds, 15.1099)));
assertEquals("thumbnail_15_110s_large.jpg",
new Extractor(dummy, cfg(Opt.some("thumbnail_%.3fs%s"), Opt.<String> none())).createFileName("_large.jpg",
uri("http://localhost/path/video.mp4"), new MediaPosition(PositionType.Seconds, 15.1099)));
assertEquals("thumbnail", new Extractor(dummy, cfg(Opt.some("thumbnail"), Opt.<String> none())).createFileName(
"_large.jpg", uri("http://localhost/path/video.mp4"), new MediaPosition(PositionType.Seconds, 15.1099)));
assertEquals("thumbnail_large.jpg",
new Extractor(dummy, cfg(Opt.some("thumbnail%2$s"), Opt.<String> none())).createFileName("_large.jpg",
uri("http://localhost/path/video.mp4"), new MediaPosition(PositionType.Seconds, 15.1099)));
}
@Test
public void testValidateTargetBaseNameFormat() {
validateTargetBaseNameFormat("format-a").apply("thumbnail_%.1fs%s");
validateTargetBaseNameFormat("format-a").apply("thumbnail_%1$.1fs%2$s");
validateTargetBaseNameFormat("format-a").apply("%2$s_thumbnail_%1$.1fs%1$.1fs%2$s");
try {
validateTargetBaseNameFormat("format-a").apply("thumbnail_%.1fs%.3f");
fail("Invalid format passed check. Suffix format %s is missing.");
} catch (Exception ignore) {
}
try {
validateTargetBaseNameFormat("format-a").apply("thumbnail_%.3f");
fail("Invalid format passed check. Suffix format %s is missing.");
} catch (Exception ignore) {
}
try {
validateTargetBaseNameFormat("format-a").apply("thumbnail_%s");
fail("Invalid format passed check. Suffix is missing since %s does not have a positional parameter.");
} catch (Exception ignore) {
}
// omitting the position should pass
validateTargetBaseNameFormat("format-a").apply("thumbnail_%2$s");
}
@Test
public void testLimit() {
assertTrue(limit(track(1511), l.mk(sec(-1), sec(1511), sec(1512))).isEmpty());
assertTrue(limit(track(1511), l.mk(percent(-0.2), percent(101))).isEmpty());
assertEquals(4, limit(track(1511), l.mk(percent(0), percent(100), sec(0), sec(1510))).size());
assertEquals(4, limit(track(1511), l.mk(percent(0), percent(10), sec(10), sec(1500), percent(200))).size());
}
@Test
public void testToSeconds() {
assertEquals(0.985, toSeconds(track(1970), percent(50), 0), 0);
assertEquals(0, toSeconds(track(1970), percent(0), 0), 0);
assertEquals(1.87, toSeconds(track(1970), percent(100), 100), 0);
assertEquals(0, toSeconds(track(100), percent(100), 200), 0);
assertEquals(1.77, toSeconds(track(1970), sec(1.970), 200), 0);
assertEquals(1.77, toSeconds(track(1970), sec(1.870), 200), 0);
assertEquals(1.77, toSeconds(track(1970), sec(1.770), 200), 0);
assertEquals(1.769, toSeconds(track(1970), sec(1.769), 200), 0);
}
// ** ** **
private Cfg cfg(Opt<String> targetBaseNamePatternSecond, Opt<String> targetBaseNamePatternPercent) {
return new Cfg(l.<Track> nil(), l.<MediaPosition> nil(), l.<EncodingProfile> nil(),
Opt.<MediaPackageElementFlavor> none(), l.<String> nil(), targetBaseNamePatternSecond,
targetBaseNamePatternPercent, 0);
}
private MediaPosition sec(double a) {
return new MediaPosition(PositionType.Seconds, a);
}
private MediaPosition percent(double a) {
return new MediaPosition(PositionType.Percentage, a);
}
private Track track(long duration) {
final Track t = EasyMock.createNiceMock(Track.class);
EasyMock.expect(t.getDuration()).andReturn(duration).anyTimes();
EasyMock.replay(t);
return t;
}
private void test(String expr, MediaPosition... expected) {
final Result<List<MediaPosition>> r = MediaPositionParser.positions.parse(expr);
assertTrue(r.isDefined());
assertTrue("Rest:\"" + r.getRest() + "\"", r.getRest().isEmpty());
assertEquals(l.mk(expected), r.getResult());
}
private boolean testSuccess(String expr) {
final Result<List<MediaPosition>> r = MediaPositionParser.positions.parse(expr);
return r.isDefined() && r.getRest().isEmpty();
}
}