The following issues were found
src/main/java/io/reactivex/rxjava3/subjects/SingleSubject.java
17 issues
Line: 96
* @param <T> the value type received and emitted
* @since 2.1
*/
public final class SingleSubject<T> extends Single<T> implements SingleObserver<T> {
final AtomicReference<SingleDisposable<T>[]> observers;
@SuppressWarnings("rawtypes")
static final SingleDisposable[] EMPTY = new SingleDisposable[0];
Reported by PMD.
Line: 98
*/
public final class SingleSubject<T> extends Single<T> implements SingleObserver<T> {
final AtomicReference<SingleDisposable<T>[]> observers;
@SuppressWarnings("rawtypes")
static final SingleDisposable[] EMPTY = new SingleDisposable[0];
@SuppressWarnings("rawtypes")
Reported by PMD.
Line: 106
@SuppressWarnings("rawtypes")
static final SingleDisposable[] TERMINATED = new SingleDisposable[0];
final AtomicBoolean once;
T value;
Throwable error;
/**
* Creates a fresh SingleSubject.
Reported by PMD.
Line: 107
static final SingleDisposable[] TERMINATED = new SingleDisposable[0];
final AtomicBoolean once;
T value;
Throwable error;
/**
* Creates a fresh SingleSubject.
* @param <T> the value type received and emitted
Reported by PMD.
Line: 108
final AtomicBoolean once;
T value;
Throwable error;
/**
* Creates a fresh SingleSubject.
* @param <T> the value type received and emitted
* @return the new SingleSubject instance
Reported by PMD.
Line: 121
return new SingleSubject<>();
}
@SuppressWarnings("unchecked")
SingleSubject() {
once = new AtomicBoolean();
observers = new AtomicReference<>(EMPTY);
}
Reported by PMD.
Line: 141
if (once.compareAndSet(false, true)) {
this.value = value;
for (SingleDisposable<T> md : observers.getAndSet(TERMINATED)) {
md.downstream.onSuccess(value);
}
}
}
@SuppressWarnings("unchecked")
Reported by PMD.
Line: 153
if (once.compareAndSet(false, true)) {
this.error = e;
for (SingleDisposable<T> md : observers.getAndSet(TERMINATED)) {
md.downstream.onError(e);
}
} else {
RxJavaPlugins.onError(e);
}
}
Reported by PMD.
Line: 187
int n = a.length;
@SuppressWarnings("unchecked")
SingleDisposable<T>[] b = new SingleDisposable[n + 1];
System.arraycopy(a, 0, b, 0, n);
b[n] = inner;
if (observers.compareAndSet(a, b)) {
return true;
}
Reported by PMD.
Line: 218
return;
}
SingleDisposable<T>[] b;
if (n == 1) {
b = EMPTY;
} else {
b = new SingleDisposable[n - 1];
System.arraycopy(a, 0, b, 0, j);
System.arraycopy(a, j + 1, b, j, n - j - 1);
Reported by PMD.
src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableOnBackpressureErrorTest.java
17 issues
Line: 31
public class FlowableOnBackpressureErrorTest extends RxJavaTest {
@Test
public void dispose() {
TestHelper.checkDisposed(Observable.just(1).toFlowable(BackpressureStrategy.ERROR));
}
@Test
public void badRequest() {
Reported by PMD.
Line: 32
@Test
public void dispose() {
TestHelper.checkDisposed(Observable.just(1).toFlowable(BackpressureStrategy.ERROR));
}
@Test
public void badRequest() {
TestHelper.assertBadRequestReported(Observable.just(1).toFlowable(BackpressureStrategy.ERROR));
Reported by PMD.
Line: 36
}
@Test
public void badRequest() {
TestHelper.assertBadRequestReported(Observable.just(1).toFlowable(BackpressureStrategy.ERROR));
}
@Test
public void doubleOnSubscribe() {
Reported by PMD.
Line: 37
@Test
public void badRequest() {
TestHelper.assertBadRequestReported(Observable.just(1).toFlowable(BackpressureStrategy.ERROR));
}
@Test
public void doubleOnSubscribe() {
TestHelper.checkDoubleOnSubscribeFlowable(new Function<Flowable<Object>, Publisher<Object>>() {
Reported by PMD.
Line: 41
}
@Test
public void doubleOnSubscribe() {
TestHelper.checkDoubleOnSubscribeFlowable(new Function<Flowable<Object>, Publisher<Object>>() {
@Override
public Publisher<Object> apply(Flowable<Object> f) throws Exception {
return new FlowableOnBackpressureError<>(f);
}
Reported by PMD.
Line: 51
}
@Test
public void badSource() {
TestHelper.<Integer>checkBadSourceFlowable(new Function<Flowable<Integer>, Object>() {
@Override
public Object apply(Flowable<Integer> f) throws Exception {
return new FlowableOnBackpressureError<>(f);
}
Reported by PMD.
Line: 61
}
@Test
public void overflowCancels() {
PublishSubject<Integer> ps = PublishSubject.create();
TestSubscriber<Integer> ts = ps.toFlowable(BackpressureStrategy.ERROR)
.test(0L);
Reported by PMD.
Line: 64
public void overflowCancels() {
PublishSubject<Integer> ps = PublishSubject.create();
TestSubscriber<Integer> ts = ps.toFlowable(BackpressureStrategy.ERROR)
.test(0L);
assertTrue(ps.hasObservers());
ps.onNext(1);
Reported by PMD.
Line: 64
public void overflowCancels() {
PublishSubject<Integer> ps = PublishSubject.create();
TestSubscriber<Integer> ts = ps.toFlowable(BackpressureStrategy.ERROR)
.test(0L);
assertTrue(ps.hasObservers());
ps.onNext(1);
Reported by PMD.
Line: 67
TestSubscriber<Integer> ts = ps.toFlowable(BackpressureStrategy.ERROR)
.test(0L);
assertTrue(ps.hasObservers());
ps.onNext(1);
assertFalse(ps.hasObservers());
Reported by PMD.
src/test/java/io/reactivex/rxjava3/internal/observers/QueueDrainObserverTest.java
17 issues
Line: 81
}
@Test
public void unorderedSlowPath() {
TestObserver<Integer> to = new TestObserver<>();
Disposable d = Disposable.empty();
QueueDrainObserver<Integer, Integer, Integer> qd = createUnordered(to, d);
to.onSubscribe(Disposable.empty());
Reported by PMD.
Line: 87
QueueDrainObserver<Integer, Integer, Integer> qd = createUnordered(to, d);
to.onSubscribe(Disposable.empty());
qd.enter();
qd.onNext(1);
to.assertEmpty();
}
Reported by PMD.
Line: 88
to.onSubscribe(Disposable.empty());
qd.enter();
qd.onNext(1);
to.assertEmpty();
}
@Test
Reported by PMD.
Line: 94
}
@Test
public void orderedSlowPath() {
TestObserver<Integer> to = new TestObserver<>();
Disposable d = Disposable.empty();
QueueDrainObserver<Integer, Integer, Integer> qd = createOrdered(to, d);
to.onSubscribe(Disposable.empty());
Reported by PMD.
Line: 100
QueueDrainObserver<Integer, Integer, Integer> qd = createOrdered(to, d);
to.onSubscribe(Disposable.empty());
qd.enter();
qd.onNext(1);
to.assertEmpty();
}
Reported by PMD.
Line: 101
to.onSubscribe(Disposable.empty());
qd.enter();
qd.onNext(1);
to.assertEmpty();
}
@Test
Reported by PMD.
Line: 107
}
@Test
public void orderedSlowPathNonEmptyQueue() {
TestObserver<Integer> to = new TestObserver<>();
Disposable d = Disposable.empty();
QueueDrainObserver<Integer, Integer, Integer> qd = createOrdered(to, d);
to.onSubscribe(Disposable.empty());
Reported by PMD.
Line: 113
QueueDrainObserver<Integer, Integer, Integer> qd = createOrdered(to, d);
to.onSubscribe(Disposable.empty());
qd.queue.offer(0);
qd.onNext(1);
to.assertValuesOnly(0, 1);
}
Reported by PMD.
Line: 114
to.onSubscribe(Disposable.empty());
qd.queue.offer(0);
qd.onNext(1);
to.assertValuesOnly(0, 1);
}
@Test
Reported by PMD.
Line: 120
}
@Test
public void unorderedOnNextRace() {
for (int i = 0; i < TestHelper.RACE_LONG_LOOPS; i++) {
TestObserver<Integer> to = new TestObserver<>();
Disposable d = Disposable.empty();
final QueueDrainObserver<Integer, Integer, Integer> qd = createUnordered(to, d);
Reported by PMD.
src/test/java/io/reactivex/rxjava3/internal/operators/flowable/FlowableAsObservableTest.java
16 issues
Line: 34
public void hiding() {
PublishProcessor<Integer> src = PublishProcessor.create();
Flowable<Integer> dst = src.hide();
assertFalse(dst instanceof PublishProcessor);
Subscriber<Object> subscriber = TestHelper.mockSubscriber();
Reported by PMD.
Line: 36
Flowable<Integer> dst = src.hide();
assertFalse(dst instanceof PublishProcessor);
Subscriber<Object> subscriber = TestHelper.mockSubscriber();
dst.subscribe(subscriber);
Reported by PMD.
Line: 40
Subscriber<Object> subscriber = TestHelper.mockSubscriber();
dst.subscribe(subscriber);
src.onNext(1);
src.onComplete();
verify(subscriber).onNext(1);
Reported by PMD.
Line: 42
dst.subscribe(subscriber);
src.onNext(1);
src.onComplete();
verify(subscriber).onNext(1);
verify(subscriber).onComplete();
verify(subscriber, never()).onError(any(Throwable.class));
Reported by PMD.
Line: 43
dst.subscribe(subscriber);
src.onNext(1);
src.onComplete();
verify(subscriber).onNext(1);
verify(subscriber).onComplete();
verify(subscriber, never()).onError(any(Throwable.class));
}
Reported by PMD.
Line: 45
src.onNext(1);
src.onComplete();
verify(subscriber).onNext(1);
verify(subscriber).onComplete();
verify(subscriber, never()).onError(any(Throwable.class));
}
@Test
Reported by PMD.
Line: 46
src.onComplete();
verify(subscriber).onNext(1);
verify(subscriber).onComplete();
verify(subscriber, never()).onError(any(Throwable.class));
}
@Test
public void hidingError() {
Reported by PMD.
Line: 47
verify(subscriber).onNext(1);
verify(subscriber).onComplete();
verify(subscriber, never()).onError(any(Throwable.class));
}
@Test
public void hidingError() {
PublishProcessor<Integer> src = PublishProcessor.create();
Reported by PMD.
Line: 54
public void hidingError() {
PublishProcessor<Integer> src = PublishProcessor.create();
Flowable<Integer> dst = src.hide();
assertFalse(dst instanceof PublishProcessor);
Subscriber<Integer> subscriber = TestHelper.mockSubscriber();
Reported by PMD.
Line: 56
Flowable<Integer> dst = src.hide();
assertFalse(dst instanceof PublishProcessor);
Subscriber<Integer> subscriber = TestHelper.mockSubscriber();
dst.subscribe(subscriber);
Reported by PMD.
src/test/java/io/reactivex/rxjava3/internal/disposables/CancellableDisposableTest.java
16 issues
Line: 32
public class CancellableDisposableTest extends RxJavaTest {
@Test
public void normal() {
final AtomicInteger count = new AtomicInteger();
Cancellable c = new Cancellable() {
@Override
public void cancel() throws Exception {
Reported by PMD.
Line: 44
CancellableDisposable cd = new CancellableDisposable(c);
assertFalse(cd.isDisposed());
cd.dispose();
cd.dispose();
assertTrue(cd.isDisposed());
Reported by PMD.
Line: 49
cd.dispose();
cd.dispose();
assertTrue(cd.isDisposed());
assertEquals(1, count.get());
}
@Test
Reported by PMD.
Line: 51
assertTrue(cd.isDisposed());
assertEquals(1, count.get());
}
@Test
public void cancelThrows() {
final AtomicInteger count = new AtomicInteger();
Reported by PMD.
Line: 55
}
@Test
public void cancelThrows() {
final AtomicInteger count = new AtomicInteger();
Cancellable c = new Cancellable() {
@Override
public void cancel() throws Exception {
Reported by PMD.
Line: 68
CancellableDisposable cd = new CancellableDisposable(c);
assertFalse(cd.isDisposed());
List<Throwable> list = TestHelper.trackPluginErrors();
try {
cd.dispose();
cd.dispose();
Reported by PMD.
Line: 79
} finally {
RxJavaPlugins.reset();
}
assertTrue(cd.isDisposed());
assertEquals(1, count.get());
}
@Test
Reported by PMD.
Line: 81
}
assertTrue(cd.isDisposed());
assertEquals(1, count.get());
}
@Test
public void disposeRace() {
Reported by PMD.
Line: 88
public void disposeRace() {
for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) {
final AtomicInteger count = new AtomicInteger();
Cancellable c = new Cancellable() {
@Override
public void cancel() throws Exception {
count.getAndIncrement();
Reported by PMD.
Line: 90
for (int i = 0; i < TestHelper.RACE_DEFAULT_LOOPS; i++) {
final AtomicInteger count = new AtomicInteger();
Cancellable c = new Cancellable() {
@Override
public void cancel() throws Exception {
count.getAndIncrement();
}
};
Reported by PMD.
src/test/java/io/reactivex/rxjava3/internal/operators/maybe/MaybeMaterializeTest.java
16 issues
Line: 27
public class MaybeMaterializeTest extends RxJavaTest {
@Test
public void success() {
Maybe.just(1)
.materialize()
.test()
.assertResult(Notification.createOnNext(1));
}
Reported by PMD.
Line: 28
@Test
public void success() {
Maybe.just(1)
.materialize()
.test()
.assertResult(Notification.createOnNext(1));
}
Reported by PMD.
Line: 28
@Test
public void success() {
Maybe.just(1)
.materialize()
.test()
.assertResult(Notification.createOnNext(1));
}
Reported by PMD.
Line: 28
@Test
public void success() {
Maybe.just(1)
.materialize()
.test()
.assertResult(Notification.createOnNext(1));
}
Reported by PMD.
Line: 35
}
@Test
public void error() {
TestException ex = new TestException();
Maybe.error(ex)
.materialize()
.test()
.assertResult(Notification.createOnError(ex));
Reported by PMD.
Line: 37
@Test
public void error() {
TestException ex = new TestException();
Maybe.error(ex)
.materialize()
.test()
.assertResult(Notification.createOnError(ex));
}
Reported by PMD.
Line: 37
@Test
public void error() {
TestException ex = new TestException();
Maybe.error(ex)
.materialize()
.test()
.assertResult(Notification.createOnError(ex));
}
Reported by PMD.
Line: 37
@Test
public void error() {
TestException ex = new TestException();
Maybe.error(ex)
.materialize()
.test()
.assertResult(Notification.createOnError(ex));
}
Reported by PMD.
Line: 44
}
@Test
public void empty() {
Maybe.empty()
.materialize()
.test()
.assertResult(Notification.createOnComplete());
}
Reported by PMD.
Line: 45
@Test
public void empty() {
Maybe.empty()
.materialize()
.test()
.assertResult(Notification.createOnComplete());
}
Reported by PMD.
src/test/java/io/reactivex/rxjava3/internal/jdk8/MaybeFromCompletionStageTest.java
16 issues
Line: 28
public class MaybeFromCompletionStageTest extends RxJavaTest {
@Test
public void syncSuccess() {
Maybe.fromCompletionStage(CompletableFuture.completedFuture(1))
.test()
.assertResult(1);
}
Reported by PMD.
Line: 29
@Test
public void syncSuccess() {
Maybe.fromCompletionStage(CompletableFuture.completedFuture(1))
.test()
.assertResult(1);
}
@Test
Reported by PMD.
Line: 29
@Test
public void syncSuccess() {
Maybe.fromCompletionStage(CompletableFuture.completedFuture(1))
.test()
.assertResult(1);
}
@Test
Reported by PMD.
Line: 35
}
@Test
public void syncFailure() {
CompletableFuture<Integer> cf = new CompletableFuture<>();
cf.completeExceptionally(new TestException());
Maybe.fromCompletionStage(cf)
.test()
Reported by PMD.
Line: 39
CompletableFuture<Integer> cf = new CompletableFuture<>();
cf.completeExceptionally(new TestException());
Maybe.fromCompletionStage(cf)
.test()
.assertFailure(TestException.class);
}
@Test
Reported by PMD.
Line: 39
CompletableFuture<Integer> cf = new CompletableFuture<>();
cf.completeExceptionally(new TestException());
Maybe.fromCompletionStage(cf)
.test()
.assertFailure(TestException.class);
}
@Test
Reported by PMD.
Line: 45
}
@Test
public void syncNull() {
Maybe.fromCompletionStage(CompletableFuture.<Integer>completedFuture(null))
.test()
.assertResult();
}
Reported by PMD.
Line: 46
@Test
public void syncNull() {
Maybe.fromCompletionStage(CompletableFuture.<Integer>completedFuture(null))
.test()
.assertResult();
}
@Test
Reported by PMD.
Line: 46
@Test
public void syncNull() {
Maybe.fromCompletionStage(CompletableFuture.<Integer>completedFuture(null))
.test()
.assertResult();
}
@Test
Reported by PMD.
Line: 52
}
@Test
public void dispose() {
CompletableFuture<Integer> cf = new CompletableFuture<>();
TestObserver<Integer> to = Maybe.fromCompletionStage(cf)
.test();
Reported by PMD.
src/test/java/io/reactivex/rxjava3/internal/operators/completable/CompletableStartWithTest.java
16 issues
Line: 26
public class CompletableStartWithTest {
@Test
public void singleNormal() {
Completable.complete().startWith(Single.just(1))
.test()
.assertResult(1);
}
Reported by PMD.
Line: 27
@Test
public void singleNormal() {
Completable.complete().startWith(Single.just(1))
.test()
.assertResult(1);
}
@Test
Reported by PMD.
Line: 27
@Test
public void singleNormal() {
Completable.complete().startWith(Single.just(1))
.test()
.assertResult(1);
}
@Test
Reported by PMD.
Line: 27
@Test
public void singleNormal() {
Completable.complete().startWith(Single.just(1))
.test()
.assertResult(1);
}
@Test
Reported by PMD.
Line: 40
.test()
.assertFailure(TestException.class);
verify(run, never()).run();
}
@Test
public void maybeNormal() {
Completable.complete().startWith(Maybe.just(1))
Reported by PMD.
Line: 44
}
@Test
public void maybeNormal() {
Completable.complete().startWith(Maybe.just(1))
.test()
.assertResult(1);
}
Reported by PMD.
Line: 45
@Test
public void maybeNormal() {
Completable.complete().startWith(Maybe.just(1))
.test()
.assertResult(1);
}
@Test
Reported by PMD.
Line: 45
@Test
public void maybeNormal() {
Completable.complete().startWith(Maybe.just(1))
.test()
.assertResult(1);
}
@Test
Reported by PMD.
Line: 45
@Test
public void maybeNormal() {
Completable.complete().startWith(Maybe.just(1))
.test()
.assertResult(1);
}
@Test
Reported by PMD.
Line: 51
}
@Test
public void maybeEmptyNormal() {
Completable.complete().startWith(Maybe.empty())
.test()
.assertResult();
}
Reported by PMD.
src/test/java/io/reactivex/rxjava3/internal/operators/observable/ObservableDelaySubscriptionOtherTest.java
16 issues
Line: 53
to.assertNoErrors();
to.assertNoValues();
Assert.assertEquals("Premature subscription", 0, subscribed.get());
other.onNext(1);
Assert.assertEquals("No subscription", 1, subscribed.get());
Reported by PMD.
Line: 55
Assert.assertEquals("Premature subscription", 0, subscribed.get());
other.onNext(1);
Assert.assertEquals("No subscription", 1, subscribed.get());
to.assertValue(1);
to.assertNoErrors();
Reported by PMD.
Line: 57
other.onNext(1);
Assert.assertEquals("No subscription", 1, subscribed.get());
to.assertValue(1);
to.assertNoErrors();
to.assertComplete();
}
Reported by PMD.
Line: 88
Assert.assertEquals("Premature subscription", 0, subscribed.get());
other.onNext(1);
other.onNext(2);
Assert.assertEquals("No subscription", 1, subscribed.get());
to.assertValue(1);
Reported by PMD.
Line: 89
Assert.assertEquals("Premature subscription", 0, subscribed.get());
other.onNext(1);
other.onNext(2);
Assert.assertEquals("No subscription", 1, subscribed.get());
to.assertValue(1);
to.assertNoErrors();
Reported by PMD.
Line: 122
Assert.assertEquals("Premature subscription", 0, subscribed.get());
other.onComplete();
Assert.assertEquals("No subscription", 1, subscribed.get());
to.assertValue(1);
to.assertNoErrors();
Reported by PMD.
Line: 155
Assert.assertEquals("Premature subscription", 0, subscribed.get());
other.onComplete();
Assert.assertEquals("No subscription", 1, subscribed.get());
to.assertNoValues();
to.assertNotComplete();
Reported by PMD.
Line: 202
TestHelper.checkBadSourceObservable(new Function<Observable<Integer>, Object>() {
@Override
public Object apply(Observable<Integer> o) throws Exception {
return Observable.just(1).delaySubscription(o);
}
}, false, 1, 1, 1);
}
@Test
Reported by PMD.
Line: 213
try {
for (Scheduler s : new Scheduler[] { Schedulers.single(), Schedulers.computation(), Schedulers.newThread(), Schedulers.io(), Schedulers.from(exec) }) {
final TestObserver<Boolean> observer = TestObserver.create();
observer.withTag(s.getClass().getSimpleName());
Observable.<Boolean>create(new ObservableOnSubscribe<Boolean>() {
@Override
public void subscribe(ObservableEmitter<Boolean> emitter) throws Exception {
emitter.onNext(Thread.interrupted());
Reported by PMD.
Line: 213
try {
for (Scheduler s : new Scheduler[] { Schedulers.single(), Schedulers.computation(), Schedulers.newThread(), Schedulers.io(), Schedulers.from(exec) }) {
final TestObserver<Boolean> observer = TestObserver.create();
observer.withTag(s.getClass().getSimpleName());
Observable.<Boolean>create(new ObservableOnSubscribe<Boolean>() {
@Override
public void subscribe(ObservableEmitter<Boolean> emitter) throws Exception {
emitter.onNext(Thread.interrupted());
Reported by PMD.
src/test/java/io/reactivex/rxjava3/internal/jdk8/SingleFromCompletionStageTest.java
16 issues
Line: 28
public class SingleFromCompletionStageTest extends RxJavaTest {
@Test
public void syncSuccess() {
Single.fromCompletionStage(CompletableFuture.completedFuture(1))
.test()
.assertResult(1);
}
Reported by PMD.
Line: 29
@Test
public void syncSuccess() {
Single.fromCompletionStage(CompletableFuture.completedFuture(1))
.test()
.assertResult(1);
}
@Test
Reported by PMD.
Line: 29
@Test
public void syncSuccess() {
Single.fromCompletionStage(CompletableFuture.completedFuture(1))
.test()
.assertResult(1);
}
@Test
Reported by PMD.
Line: 35
}
@Test
public void syncFailure() {
CompletableFuture<Integer> cf = new CompletableFuture<>();
cf.completeExceptionally(new TestException());
Single.fromCompletionStage(cf)
.test()
Reported by PMD.
Line: 39
CompletableFuture<Integer> cf = new CompletableFuture<>();
cf.completeExceptionally(new TestException());
Single.fromCompletionStage(cf)
.test()
.assertFailure(TestException.class);
}
@Test
Reported by PMD.
Line: 39
CompletableFuture<Integer> cf = new CompletableFuture<>();
cf.completeExceptionally(new TestException());
Single.fromCompletionStage(cf)
.test()
.assertFailure(TestException.class);
}
@Test
Reported by PMD.
Line: 45
}
@Test
public void syncNull() {
Single.fromCompletionStage(CompletableFuture.<Integer>completedFuture(null))
.test()
.assertFailure(NullPointerException.class);
}
Reported by PMD.
Line: 46
@Test
public void syncNull() {
Single.fromCompletionStage(CompletableFuture.<Integer>completedFuture(null))
.test()
.assertFailure(NullPointerException.class);
}
@Test
Reported by PMD.
Line: 46
@Test
public void syncNull() {
Single.fromCompletionStage(CompletableFuture.<Integer>completedFuture(null))
.test()
.assertFailure(NullPointerException.class);
}
@Test
Reported by PMD.
Line: 52
}
@Test
public void dispose() {
CompletableFuture<Integer> cf = new CompletableFuture<>();
TestObserver<Integer> to = Single.fromCompletionStage(cf)
.test();
Reported by PMD.