Merge branch 'master' into data_structures
This commit is contained in:
commit
2164672729
7 changed files with 49 additions and 28 deletions
26
.github/workflows/maven.yml
vendored
26
.github/workflows/maven.yml
vendored
|
@ -1,26 +0,0 @@
|
||||||
# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time
|
|
||||||
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven
|
|
||||||
|
|
||||||
name: Java CI with Maven
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ "*" ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ "master", "dev" ]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- name: Set up JDK 17
|
|
||||||
uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
java-version: '17'
|
|
||||||
distribution: 'temurin'
|
|
||||||
cache: maven
|
|
||||||
- name: Build with Maven
|
|
||||||
run: mvn -B package --file pom.xml
|
|
13
.woodpecker/main-mirror.yml
Normal file
13
.woodpecker/main-mirror.yml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
skip_clone: true
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: mirror
|
||||||
|
image: bitnami/git:2.44.0
|
||||||
|
commands:
|
||||||
|
- git clone $CI_REPO_CLONE_URL repository
|
||||||
|
- cd repository
|
||||||
|
- git push https://Administrator:$GIT_PAT@git.ztsh.eu/Administrator/hackerrank.git
|
||||||
|
secrets: [git_pat]
|
||||||
|
|
||||||
|
when:
|
||||||
|
branch: master
|
5
.woodpecker/maven.yml
Normal file
5
.woodpecker/maven.yml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
steps:
|
||||||
|
- name: test
|
||||||
|
image: maven:3.9.6-eclipse-temurin-17-alpine
|
||||||
|
commands:
|
||||||
|
- mvn -B verify
|
|
@ -5,6 +5,7 @@ import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
|
|
||||||
import eu.ztsh.training.hackerrank.SolutionClassDescription.FieldModifier;
|
import eu.ztsh.training.hackerrank.SolutionClassDescription.FieldModifier;
|
||||||
import org.junit.jupiter.api.Disabled;
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.jupiter.api.DisplayName;
|
import org.junit.jupiter.api.DisplayName;
|
||||||
|
|
|
@ -7,15 +7,20 @@ import java.io.PrintStream;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common class with all the necessary logic
|
||||||
|
*/
|
||||||
public abstract class HackerRankTest {
|
public abstract class HackerRankTest {
|
||||||
|
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
public static void setUpStreams() {
|
public static void setUpStreams() {
|
||||||
|
// Redirect stdout & stderr to own streams
|
||||||
System.setOut(new PrintStream(outContent));
|
System.setOut(new PrintStream(outContent));
|
||||||
System.setErr(new PrintStream(errContent));
|
System.setErr(new PrintStream(errContent));
|
||||||
}
|
}
|
||||||
|
@ -34,14 +39,19 @@ public abstract class HackerRankTest {
|
||||||
|
|
||||||
protected List<String> invoke(List<String> input) {
|
protected List<String> invoke(List<String> input) {
|
||||||
try {
|
try {
|
||||||
|
// reset our stdout as check is based on it
|
||||||
outContent.reset();
|
outContent.reset();
|
||||||
|
// write content to args of Solution#main
|
||||||
writeLines(input);
|
writeLines(input);
|
||||||
|
// check if scanner has other name than "scanner"
|
||||||
if (getSolutionClassDescription().fieldName() != null) {
|
if (getSolutionClassDescription().fieldName() != null) {
|
||||||
ReflectionHelper.reloadScanner(getSolutionClassDescription());
|
ReflectionHelper.reloadScanner(getSolutionClassDescription());
|
||||||
}
|
}
|
||||||
|
// run Solution#main
|
||||||
getSolutionClassDescription().targetClass()
|
getSolutionClassDescription().targetClass()
|
||||||
.getMethod("main", String[].class)
|
.getMethod("main", String[].class)
|
||||||
.invoke(null, (Object) new String[]{});
|
.invoke(null, (Object) new String[]{});
|
||||||
|
// return intercepted output
|
||||||
return readLines();
|
return readLines();
|
||||||
} catch (final NoSuchMethodException | InvocationTargetException | IllegalAccessException |
|
} catch (final NoSuchMethodException | InvocationTargetException | IllegalAccessException |
|
||||||
NoSuchFieldException e) {
|
NoSuchFieldException e) {
|
||||||
|
|
|
@ -5,9 +5,12 @@ import java.lang.invoke.VarHandle;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
|
|
||||||
import eu.ztsh.training.hackerrank.SolutionClassDescription.FieldModifier;
|
import eu.ztsh.training.hackerrank.SolutionClassDescription.FieldModifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Util that helps with scanner declared outside Solution#main
|
||||||
|
*/
|
||||||
public class ReflectionHelper {
|
public class ReflectionHelper {
|
||||||
|
|
||||||
// https://stackoverflow.com/a/56043252
|
// https://stackoverflow.com/a/56043252
|
||||||
|
@ -21,7 +24,15 @@ public class ReflectionHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void reloadScanner(SolutionClassDescription description) throws NoSuchFieldException, IllegalAccessException {
|
/**
|
||||||
|
* Modify scanner field to substitute it with custom readable one
|
||||||
|
*
|
||||||
|
* @param description Solution class parameters
|
||||||
|
* @throws NoSuchFieldException when there description.fieldName points to incorrect name
|
||||||
|
* @throws IllegalAccessException on scanner substitution error
|
||||||
|
*/
|
||||||
|
static void reloadScanner(SolutionClassDescription description)
|
||||||
|
throws NoSuchFieldException, IllegalAccessException {
|
||||||
// https://stackoverflow.com/a/3301720
|
// https://stackoverflow.com/a/3301720
|
||||||
var scannerField = description.hasModifier(FieldModifier.STATIC)
|
var scannerField = description.hasModifier(FieldModifier.STATIC)
|
||||||
? description.targetClass().getDeclaredField(description.fieldName())
|
? description.targetClass().getDeclaredField(description.fieldName())
|
||||||
|
|
|
@ -2,6 +2,13 @@ package eu.ztsh.training.hackerrank;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Solution params definition
|
||||||
|
*
|
||||||
|
* @param targetClass Solution
|
||||||
|
* @param fieldName scanner field name
|
||||||
|
* @param modifiers scanner field modifiers
|
||||||
|
*/
|
||||||
public record SolutionClassDescription(Class<?> targetClass, String fieldName, FieldModifier[] modifiers) {
|
public record SolutionClassDescription(Class<?> targetClass, String fieldName, FieldModifier[] modifiers) {
|
||||||
|
|
||||||
public SolutionClassDescription(Class<?> targetClass) {
|
public SolutionClassDescription(Class<?> targetClass) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue