Merge branch 'master' into data_structures

This commit is contained in:
Piotr Dec 2024-03-15 22:43:17 +01:00
commit 2164672729
Signed by: stawros
GPG key ID: F89F27AD8F881A91
7 changed files with 49 additions and 28 deletions

View file

@ -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

View 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
View file

@ -0,0 +1,5 @@
steps:
- name: test
image: maven:3.9.6-eclipse-temurin-17-alpine
commands:
- mvn -B verify

View file

@ -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;

View file

@ -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) {

View file

@ -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())

View file

@ -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) {