Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into append-last-error-…
Browse files Browse the repository at this point in the history
…log-to-scenario-description

# Conflicts:
#	build.gradle
  • Loading branch information
vitaliirymar committed Mar 4, 2024
2 parents 129ef24 + b0fcfde commit 6b57ff0
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 10 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@
### Changed
- Karate dependency marked as `compileOnly` to force users specify their own version of Karate, by @HardNorth
- Client version updated on [5.2.5](https://github.com/reportportal/client-java/releases/tag/5.2.5), by @HardNorth
### Fixed
- Issue [#23](https://github.com/reportportal/agent-java-karate/issues/23) scenarios outside features in parallel execution, by @HardNorth

## [5.0.1]
### Changed
- Karate dependency marked as `compileOnly` to force users specify their own version of Karate, by @HardNorth
- Client version updated on [5.2.5](https://github.com/reportportal/client-java/releases/tag/5.2.5), by @HardNorth
### Fixed
- Issue [#23](https://github.com/reportportal/agent-java-karate/issues/23) scenarios outside features in parallel execution, by @HardNorth

## [5.1.0]
### Added
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=agent-java-karate
version=5.0.1-SNAPSHOT
version=5.0.2-SNAPSHOT
description=EPAM ReportPortal. Karate test framework [1.3.1, ) adapter
gradle_version=8.2
karate_version=1.4.1
Expand Down
15 changes: 6 additions & 9 deletions src/main/java/com/epam/reportportal/karate/ReportPortalHook.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.epam.reportportal.karate;

import com.epam.reportportal.karate.utils.BlockingConcurrentHashMap;
import com.epam.reportportal.listeners.ItemStatus;
import com.epam.reportportal.listeners.ListenerParameters;
import com.epam.reportportal.listeners.LogLevel;
Expand Down Expand Up @@ -55,7 +56,7 @@
public class ReportPortalHook implements RuntimeHook {
private static final Logger LOGGER = LoggerFactory.getLogger(ReportPortalHook.class);
protected final MemoizingSupplier<Launch> launch;
private final Map<String, Maybe<String>> featureIdMap = new ConcurrentHashMap<>();
private final BlockingConcurrentHashMap<String, Maybe<String>> featureIdMap = new BlockingConcurrentHashMap<>();
private final Map<String, Maybe<String>> scenarioIdMap = new ConcurrentHashMap<>();
private final Map<String, Maybe<String>> backgroundIdMap = new ConcurrentHashMap<>();
private final Map<String, Maybe<String>> stepIdMap = new ConcurrentHashMap<>();
Expand Down Expand Up @@ -160,9 +161,7 @@ protected StartTestItemRQ buildStartFeatureRq(@Nonnull FeatureRuntime fr) {

@Override
public boolean beforeFeature(FeatureRuntime fr) {
Maybe<String> featureId = launch.get().startTestItem(buildStartFeatureRq(fr));
Feature feature = fr.featureCall.feature;
featureIdMap.put(feature.getNameForReport(), featureId);
featureIdMap.computeIfAbsent(fr.featureCall.feature.getNameForReport(), f -> launch.get().startTestItem(buildStartFeatureRq(fr)));
return true;
}

Expand All @@ -179,8 +178,7 @@ protected FinishTestItemRQ buildFinishFeatureRq(@Nonnull FeatureRuntime fr) {

@Override
public void afterFeature(FeatureRuntime fr) {
Feature feature = fr.featureCall.feature;
Maybe<String> featureId = featureIdMap.remove(feature.getNameForReport());
Maybe<String> featureId = featureIdMap.remove(fr.featureCall.feature.getNameForReport());
if (featureId == null) {
LOGGER.error("ERROR: Trying to finish unspecified feature.");
}
Expand All @@ -202,10 +200,9 @@ protected StartTestItemRQ buildStartScenarioRq(@Nonnull ScenarioRuntime sr) {

@Override
public boolean beforeScenario(ScenarioRuntime sr) {
Maybe<String> featureId = featureIdMap.get(sr.featureRuntime.featureCall.feature.getNameForReport());
StartTestItemRQ rq = buildStartScenarioRq(sr);

Maybe<String> scenarioId = launch.get()
.startTestItem(featureIdMap.get(sr.featureRuntime.featureCall.feature.getNameForReport()), rq);
Maybe<String> scenarioId = launch.get().startTestItem(featureId, rq);
scenarioIdMap.put(sr.scenario.getUniqueId(), scenarioId);
return true;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Copyright 2024 EPAM Systems
*
* Licensed under the Apache 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
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* 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 com.epam.reportportal.karate.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;

public class BlockingConcurrentHashMap<K, V> {
private static final Logger LOGGER = LoggerFactory.getLogger(BlockingConcurrentHashMap.class);

private static final class BlockingReference<T> {
private final BlockingQueue<T> lock = new ArrayBlockingQueue<>(1);
private volatile boolean set = false;
private volatile T value;

public void set(Function<?, T> supplier) {
lock.clear();
set = false;
try {
value = supplier.apply(null);
set = true;
try {
//noinspection StatementWithEmptyBody
while (lock.offer(value)) {
// Put while waiting Threads take values
}
} catch (IllegalStateException ignore) {
}
} catch (Exception e) {
LOGGER.warn("Unable to get result value from passed supplier.", e);
throw e;
}
}

public T get(long timeout, TimeUnit unit) throws InterruptedException {
if (!set) {
return lock.poll(timeout, unit);
} else {
return value;
}
}
}

private static final int TIMEOUT = 1;
private static final TimeUnit TIMEOUT_UNIT = TimeUnit.MINUTES;

private final Map<K, BlockingReference<V>> map = new ConcurrentHashMap<>();

public void computeIfAbsent(@Nonnull K key, Function<?, V> mappingFunction) {
map.computeIfAbsent(key, k -> new BlockingReference<>()).set(mappingFunction);
}

@Nullable
public V get(@Nonnull K key) {
try {
return map.computeIfAbsent(key, k -> new BlockingReference<>()).get(TIMEOUT, TIMEOUT_UNIT);
} catch (InterruptedException e) {
LOGGER.warn("Wait for value was interrupted", e);
}
return null;
}

@Nullable
public V remove(@Nonnull K key) {
try {
return map.remove(key).get(TIMEOUT, TIMEOUT_UNIT);
} catch (InterruptedException e) {
LOGGER.warn("Wait for value was interrupted", e);
}
return null;
}
}

0 comments on commit 6b57ff0

Please sign in to comment.