Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions extractor/src/test/java/org/schabi/newpipe/NewPipeTestRunner.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package org.schabi.newpipe;

import org.junit.Ignore;
import org.junit.internal.AssumptionViolatedException;
import org.junit.runner.Description;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class NewPipeTestRunner extends BlockJUnit4ClassRunner {
private final NewPipeTestRunnerOptions options;

private List<String> methodsNotFailing;
private int currentRetry;

public NewPipeTestRunner(Class testClass) throws InitializationError {
super(testClass);

if (testClass.isAnnotationPresent(NewPipeTestRunnerOptions.class)) {
options = (NewPipeTestRunnerOptions) testClass.getAnnotation(NewPipeTestRunnerOptions.class);
validateOptions(testClass);
} else {
throw new InitializationError("Test class " + testClass.getCanonicalName() +
" running with " + NewPipeTestRunner.class.getSimpleName() + " should have the @" +
NewPipeTestRunnerOptions.class.getSimpleName() + " annotation");
}
}

private void validateOptions(Class testClass) throws InitializationError {
if (options.classDelayMs() < 0) {
throw new InitializationError("classDelayMs value should not be negative in annotation @" +
NewPipeTestRunnerOptions.class.getSimpleName() + " in class " + testClass.getCanonicalName());
}
if (options.methodDelayMs() < 0) {
throw new InitializationError("methodDelayMs value should not be negative in annotation @" +
NewPipeTestRunnerOptions.class.getSimpleName() + " in class " + testClass.getCanonicalName());
}
if (options.retry() < 1) {
throw new InitializationError("retry value should be bigger than 0 in annotation @" +
NewPipeTestRunnerOptions.class.getSimpleName() + " in class " + testClass.getCanonicalName());
}
}


private void sleep(int milliseconds) {
if (milliseconds > 0) {
try {
TimeUnit.MILLISECONDS.sleep(milliseconds);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}

@Override
public void run(RunNotifier notifier) {
sleep(options.classDelayMs()); // @see NewPipeTestRunnerOptions.classDelayMs

methodsNotFailing = new ArrayList<>();
for (currentRetry = 1; currentRetry <= options.retry(); ++currentRetry) {
if (getChildren().size() == methodsNotFailing.size()) {
break;
}
super.run(notifier);
}
}

@Override
protected void runChild(FrameworkMethod method, RunNotifier notifier) {
if (isMethodAlreadyNotFailing(method)) return;
Description description = describeChild(method);

if (isIgnored(method)) {
notifier.fireTestIgnored(description);
markMethodAsNotFailing(method);

String ignoreReason = method.getAnnotation(Ignore.class).value();
System.out.println(method.getName() + "() ignored because of @Ignore" +
(ignoreReason.isEmpty() ? "" : ": " + ignoreReason));

} else {
sleep(options.methodDelayMs()); // @see NewPipeTestRunnerOptions.methodDelayMs
Statement statement = methodBlock(method);
notifier.fireTestStarted(description);

try {
statement.evaluate();
markMethodAsNotFailing(method);

} catch (Throwable e) {
if (currentRetry < options.retry() || e instanceof AssumptionViolatedException) {
notifier.fireTestAssumptionFailed(new Failure(description, e));
} else {
notifier.fireTestFailure(new Failure(description, e)); // test is not going to be retried anymore
}

} finally {
notifier.fireTestFinished(description);
}
}
}


private void markMethodAsNotFailing(FrameworkMethod method) {
methodsNotFailing.add(method.getName());
}

private boolean isMethodAlreadyNotFailing(FrameworkMethod method) {
return methodsNotFailing.contains(method.getName());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.schabi.newpipe;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface NewPipeTestRunnerOptions {
/**
* This tells the Runner to wait the specified time before
* running the tests in the annotated class.
* @return milliseconds to sleep before testing the class
*/
int classDelayMs() default 0;

/**
* This tells the Runner to wait the specified time before
* invoking each test method in the annotated class.
* @return milliseconds to sleep before invoking each test method
*/
int methodDelayMs() default 0;

/**
* This tells the Runner to retry at most the specified number of
* times running the tests in the annotated class. As soon as the
* maximum number of retries is hit or all test methods succeed,
* the Runner completes, respectively with the last errors or
* with success.
* @return the number of times the class should be tested before
* declaring one of its test methods as failed.
*/
int retry() default 1;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
Expand All @@ -20,6 +23,7 @@ public static void assertEmptyErrors(String message, List<Throwable> errors) {
}
}


@Nonnull
private static URL urlFromString(String url) {
try {
Expand All @@ -38,6 +42,14 @@ public static void assertIsSecureUrl(String urlToCheck) {
assertEquals("Protocol of URL is not secure", "https", url.getProtocol());
}

public static void assertResponseCodeOk(String url) throws IOException {
HttpURLConnection connection = (HttpURLConnection) urlFromString(url).openConnection();
int responseCode = connection.getResponseCode();
assertTrue("Url returned error code " + responseCode + ": " + url, responseCode < 400);
}



public static void assertNotEmpty(String stringToCheck) {
assertNotEmpty(null, stringToCheck);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public static void setUpClass() throws Exception {
@Test
public void testViewCount() {
ChannelInfoItem ci = (ChannelInfoItem) itemsPage.getItems().get(0);
assertTrue("Count does not fit: " + Long.toString(ci.getSubscriberCount()),
assertTrue("Count does not fit: " + ci.getSubscriberCount(),
69043316 < ci.getSubscriberCount() && ci.getSubscriberCount() < 103043316);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,17 @@
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeStreamExtractor;
import org.schabi.newpipe.extractor.services.youtube.linkHandler.YoutubeStreamLinkHandlerFactory;
import org.schabi.newpipe.extractor.stream.StreamExtractor;
import org.schabi.newpipe.extractor.stream.VideoStream;
import org.schabi.newpipe.extractor.utils.Localization;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import static org.junit.Assert.*;
import static org.schabi.newpipe.extractor.ExtractorAsserts.assertIsSecureUrl;
import static org.schabi.newpipe.extractor.ServiceList.YouTube;

/**
* Test for {@link YoutubeStreamLinkHandlerFactory}
*/
public class YoutubeStreamExtractorAgeRestrictedTest {
public static final String HTTPS = "https://";
private static YoutubeStreamExtractor extractor;
public class YoutubeStreamExtractorAgeRestrictedTest extends YoutubeStreamExtractorBaseTest {

@BeforeClass
public static void setUp() throws Exception {
Expand All @@ -37,97 +30,39 @@ public static void setUp() throws Exception {
extractor.fetchPage();
}

@Test
public void testGetInvalidTimeStamp() throws ParsingException {
assertTrue(extractor.getTimeStamp() + "", extractor.getTimeStamp() <= 0);
}

@Test
public void testGetValidTimeStamp() throws IOException, ExtractionException {
StreamExtractor extractor = YouTube.getStreamExtractor("https://youtu.be/FmG385_uUys?t=174");
assertEquals(extractor.getTimeStamp() + "", "174");
}

@Test
public void testGetAgeLimit() throws ParsingException {
assertEquals(18, extractor.getAgeLimit());
}

@Test
public void testGetName() throws ParsingException {
assertNotNull("name is null", extractor.getName());
assertFalse("name is empty", extractor.getName().isEmpty());
}

@Test
public void testGetDescription() throws ParsingException {
assertNotNull(extractor.getDescription());
assertFalse(extractor.getDescription().isEmpty());
}

@Test
public void testGetUploaderName() throws ParsingException {
assertNotNull(extractor.getUploaderName());
assertFalse(extractor.getUploaderName().isEmpty());
}

@Test
public void testGetLength() throws ParsingException {
assertEquals(1789, extractor.getLength());
}

@Test
public void testGetViews() throws ParsingException {
assertTrue(extractor.getViewCount() > 0);
}

@Test
public void testGetUploadDate() throws ParsingException {
assertTrue(extractor.getUploadDate().length() > 0);
}

@Test
public void testGetThumbnailUrl() throws ParsingException {
assertIsSecureUrl(extractor.getThumbnailUrl());
}

@Test
public void testGetUploaderAvatarUrl() throws ParsingException {
assertIsSecureUrl(extractor.getUploaderAvatarUrl());
}

@Test
public void testGetAudioStreams() throws IOException, ExtractionException {
super.testGetAudioStreams();
// audio streams are not always necessary
assertFalse(extractor.getAudioStreams().isEmpty());
}

@Test
public void testGetVideoStreams() throws IOException, ExtractionException {
List<VideoStream> streams = new ArrayList<>();
streams.addAll(extractor.getVideoStreams());
streams.addAll(extractor.getVideoOnlyStreams());

assertTrue(Integer.toString(streams.size()),streams.size() > 0);
for (VideoStream s : streams) {
assertTrue(s.getUrl(),
s.getUrl().contains(HTTPS));
assertTrue(s.resolution.length() > 0);
assertTrue(Integer.toString(s.getFormatId()),
0 <= s.getFormatId() && s.getFormatId() <= 0x100);
}
@Ignore("Apparently age restricted videos have no related videos")
@Override
public void testGetRelatedVideos() throws IOException, ExtractionException {
super.testGetRelatedVideos();
}


@Test
public void testGetSubtitlesListDefault() throws IOException, ExtractionException {
// Video (/view?v=YQHsXMglC9A) set in the setUp() method has no captions => null
// Video (/view?v=MmBeUZqv1QA) set in the setUp() method has no captions => null
assertTrue(extractor.getSubtitlesDefault().isEmpty());
}

@Test
public void testGetSubtitlesList() throws IOException, ExtractionException {
// Video (/view?v=YQHsXMglC9A) set in the setUp() method has no captions => null
// Video (/view?v=MmBeUZqv1QA) set in the setUp() method has no captions => null
assertTrue(extractor.getSubtitles(MediaFormat.TTML).isEmpty());
}
}
Loading