8303702: Provide ThreadFactory to create platform/virtual threads for com/sun/jdi tests
Reviewed-by: cjplummer, sspitsyn
This commit is contained in:
parent
4655b790d0
commit
cdcf5c1ed8
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -50,34 +50,27 @@ class ClassesByName2Targ {
|
||||
System.out.println("Howdy!");
|
||||
try {
|
||||
|
||||
Thread zero = new Thread ("ZERO") {
|
||||
public void run () {
|
||||
Thread zero = TestScaffold.newThread (() -> {
|
||||
System.setProperty("java.awt.headless", "true");
|
||||
java.awt.Toolkit tk = java.awt.Toolkit.getDefaultToolkit();
|
||||
}, "ZERO");
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
Thread one = new Thread ("ONE") {
|
||||
public void run () {
|
||||
Thread one = TestScaffold.newThread (() -> {
|
||||
try {
|
||||
java.security.KeyPairGenerator keyGen =
|
||||
java.security.KeyPairGenerator.getInstance("DSA", "SUN");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
};
|
||||
}, "ONE");
|
||||
|
||||
Thread two = new Thread ("TWO") {
|
||||
public void run () {
|
||||
Thread two = TestScaffold.newThread (() -> {
|
||||
try {
|
||||
String s = String.format("%02x", 0xff);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
};
|
||||
}, "TWO");
|
||||
|
||||
two.start();
|
||||
one.start();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -74,8 +74,8 @@ class DeferredStepTestTarg {
|
||||
|
||||
jj1 obj1 = new jj1();
|
||||
jj2 obj2 = new jj2();
|
||||
new Thread(obj1, "jj1").start();
|
||||
new Thread(obj2, "jj2").start();
|
||||
TestScaffold.newThread(obj1, "jj1").start();
|
||||
TestScaffold.newThread(obj2, "jj2").start();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -843,21 +843,18 @@ abstract class EATestCaseBaseTarget extends EATestCaseBaseShared implements Runn
|
||||
public static void staticSetUp() {
|
||||
inflatedLock = new XYVal(1, 1);
|
||||
synchronized (inflatedLock) {
|
||||
inflatorThread = new Thread("Lock Inflator (test thread)") {
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (inflatedLock) {
|
||||
inflatedLockIsPermanentlyInflated = true;
|
||||
inflatedLock.notify(); // main thread
|
||||
while (true) {
|
||||
try {
|
||||
// calling wait() on a monitor will cause inflation into a heavy monitor
|
||||
inflatedLock.wait();
|
||||
} catch (InterruptedException e) { /* ignored */ }
|
||||
}
|
||||
inflatorThread = TestScaffold.newThread(() -> {
|
||||
synchronized (inflatedLock) {
|
||||
inflatedLockIsPermanentlyInflated = true;
|
||||
inflatedLock.notify(); // main thread
|
||||
while (true) {
|
||||
try {
|
||||
// calling wait() on a monitor will cause inflation into a heavy monitor
|
||||
inflatedLock.wait();
|
||||
} catch (InterruptedException e) { /* ignored */ }
|
||||
}
|
||||
}
|
||||
};
|
||||
}, "Lock Inflator (test thread)");
|
||||
inflatorThread.setDaemon(true);
|
||||
inflatorThread.start();
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2006, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -47,7 +47,7 @@ class InterruptHangTarg {
|
||||
public static void main(String[] args){
|
||||
int answer = 0;
|
||||
System.out.println("Howdy!");
|
||||
Interruptor interruptorThread = new Interruptor(Thread.currentThread());
|
||||
Thread interruptorThread = TestScaffold.newThread(new Interruptor(Thread.currentThread()));
|
||||
|
||||
synchronized(sync) {
|
||||
interruptorThread.start();
|
||||
@ -75,7 +75,7 @@ class InterruptHangTarg {
|
||||
}
|
||||
}
|
||||
|
||||
class Interruptor extends Thread {
|
||||
class Interruptor implements Runnable {
|
||||
Thread interruptee;
|
||||
Interruptor(Thread interruptee) {
|
||||
this.interruptee = interruptee;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2006, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -46,7 +46,7 @@ import java.util.*;
|
||||
* which loop, hitting a bkpt in each iteration.
|
||||
*
|
||||
*/
|
||||
class InvokeHangTarg extends Thread {
|
||||
class InvokeHangTarg implements Runnable {
|
||||
static boolean one = false;
|
||||
static String name1 = "Thread 1";
|
||||
static String name2 = "Thread 2";
|
||||
@ -54,8 +54,8 @@ class InvokeHangTarg extends Thread {
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Howdy!");
|
||||
InvokeHangTarg t1 = new InvokeHangTarg(name1);
|
||||
InvokeHangTarg t2 = new InvokeHangTarg(name2);
|
||||
Thread t1 = TestScaffold.newThread(new InvokeHangTarg(), name1);
|
||||
Thread t2 = TestScaffold.newThread(new InvokeHangTarg(), name2);
|
||||
|
||||
t1.start();
|
||||
t2.start();
|
||||
@ -81,12 +81,8 @@ class InvokeHangTarg extends Thread {
|
||||
return s;
|
||||
}
|
||||
|
||||
public InvokeHangTarg(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
if (getName().equals(name1)) {
|
||||
if (Thread.currentThread().getName().equals(name1)) {
|
||||
run1();
|
||||
} else {
|
||||
run2();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -39,11 +39,11 @@ class JdbLockTestTarg {
|
||||
static String jj = "jj";
|
||||
public static void main(String args[]) {
|
||||
synchronized(jj) {
|
||||
sleeper xx = new sleeper();
|
||||
Thread xx = TestScaffold.newThread(new Sleeper());
|
||||
xx.start();
|
||||
// Give the sleeper a chance to run and get to
|
||||
// the synchronized statement.
|
||||
while(sleeper.started == 0) {
|
||||
while(Sleeper.started == 0) {
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch(InterruptedException ee) {
|
||||
@ -55,7 +55,7 @@ class JdbLockTestTarg {
|
||||
}
|
||||
}
|
||||
|
||||
class sleeper extends Thread {
|
||||
class Sleeper implements Runnable {
|
||||
public static int started = 0;
|
||||
public void run() {
|
||||
started = 1;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -48,16 +48,19 @@ class JdbStopThreadidTestTarg {
|
||||
|
||||
private static void test() {
|
||||
JdbStopThreadidTestTarg test = new JdbStopThreadidTestTarg();
|
||||
MyThread myThread1 = test.new MyThread("MYTHREAD-1");
|
||||
MyThread myThread2 = test.new MyThread("MYTHREAD-2");
|
||||
MyThread myThread3 = test.new MyThread("MYTHREAD-3");
|
||||
MyTask myTask1 = test.new MyTask();
|
||||
MyTask myTask2 = test.new MyTask();
|
||||
MyTask myTask3 = test.new MyTask();
|
||||
Thread myThread1 = TestScaffold.newThread(myTask1, "MYTHREAD-1");
|
||||
Thread myThread2 = TestScaffold.newThread(myTask2, "MYTHREAD-2");
|
||||
Thread myThread3 = TestScaffold.newThread(myTask3, "MYTHREAD-3");
|
||||
|
||||
synchronized (lockObj) {
|
||||
myThread1.start();
|
||||
myThread2.start();
|
||||
myThread3.start();
|
||||
// Wait for all threads to have started. Note they all block on lockObj after starting.
|
||||
while (!myThread1.started || !myThread2.started || !myThread3.started) {
|
||||
while (!myTask1.started || !myTask2.started || ! myTask3.started) {
|
||||
try {
|
||||
Thread.sleep(50);
|
||||
} catch (InterruptedException e) {
|
||||
@ -83,13 +86,9 @@ class JdbStopThreadidTestTarg {
|
||||
System.out.println(obj);
|
||||
}
|
||||
|
||||
class MyThread extends Thread {
|
||||
class MyTask implements Runnable {
|
||||
volatile boolean started = false;
|
||||
|
||||
public MyThread(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
started = true;
|
||||
synchronized (JdbStopThreadidTestTarg.lockObj) {
|
||||
@ -112,8 +111,8 @@ public class JdbStopThreadidTest extends JdbTest {
|
||||
}
|
||||
|
||||
private static final String DEBUGGEE_CLASS = JdbStopThreadidTestTarg.class.getName();
|
||||
private static final String DEBUGGEE_THREAD_CLASS = JdbStopThreadidTestTarg.class.getName() + "$MyThread";
|
||||
private static Pattern threadidPattern = Pattern.compile("MyThread\\)(\\S+)\\s+MYTHREAD-2");
|
||||
private static final String DEBUGGEE_THREAD_CLASS = JdbStopThreadidTestTarg.class.getName() + "$MyTask";
|
||||
private static Pattern threadidPattern = Pattern.compile("Thread\\)(\\S+)\\s+MYTHREAD-2");
|
||||
|
||||
@Override
|
||||
protected void runCases() {
|
||||
@ -136,7 +135,7 @@ public class JdbStopThreadidTest extends JdbTest {
|
||||
|
||||
// Continue until MYTHREAD-2 breakpoint is hit. If we hit any other breakpoint before
|
||||
// then (we aren't suppose to), then this test will fail.
|
||||
jdb.command(JdbCommand.cont().waitForPrompt("Breakpoint hit: \"thread=MYTHREAD-2\", \\S+MyThread.brkMethod", true));
|
||||
jdb.command(JdbCommand.cont().waitForPrompt("Breakpoint hit: \"thread=MYTHREAD-2\", \\S+MyTask.brkMethod", true));
|
||||
// Continue until the application exits. Once again, hitting a breakpoint will cause
|
||||
// a failure because we are not suppose to hit one.
|
||||
jdb.contToExit(1);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -61,7 +61,7 @@ class MonitorEventTestTarg {
|
||||
endingMonitor = new Object();
|
||||
startingMonitor = new Object();
|
||||
|
||||
myThread t1 = new myThread();
|
||||
Thread t1 = TestScaffold.newThread(new MyTask());
|
||||
foo();
|
||||
aboutEnterLock = false;
|
||||
|
||||
@ -96,7 +96,7 @@ class MonitorEventTestTarg {
|
||||
}
|
||||
}
|
||||
|
||||
class myThread extends Thread {
|
||||
class MyTask implements Runnable {
|
||||
public void run() {
|
||||
synchronized(MonitorEventTestTarg.startingMonitor) {
|
||||
MonitorEventTestTarg.startingMonitor.notify();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -101,7 +101,7 @@ public class PopAsynchronousTest extends TestScaffold {
|
||||
/********** test assist **********/
|
||||
|
||||
|
||||
class HarassThread extends Thread {
|
||||
class HarassThread implements Runnable {
|
||||
public void run() {
|
||||
int harassCount = 0;
|
||||
try {
|
||||
@ -186,7 +186,7 @@ public class PopAsynchronousTest extends TestScaffold {
|
||||
/*
|
||||
* start popping wildly away
|
||||
*/
|
||||
(new HarassThread()).start();
|
||||
TestScaffold.newThread(new HarassThread()).start();
|
||||
|
||||
/*
|
||||
* resume the target listening for events
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -37,18 +37,14 @@ import com.sun.jdi.request.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
class ResumeOneThreadTarg extends Thread {
|
||||
class ResumeOneThreadTarg implements Runnable {
|
||||
static String name1 = "Thread 1";
|
||||
static String name2 = "Thread 2";
|
||||
|
||||
public ResumeOneThreadTarg(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(" Debuggee: Howdy!");
|
||||
ResumeOneThreadTarg t1 = new ResumeOneThreadTarg(name1);
|
||||
ResumeOneThreadTarg t2 = new ResumeOneThreadTarg(name2);
|
||||
Thread t1 = TestScaffold.newThread(new ResumeOneThreadTarg(), name1);
|
||||
Thread t2 = TestScaffold.newThread(new ResumeOneThreadTarg(), name2);
|
||||
// Force these threads to be non-daemon threads, even when the debuggee
|
||||
// is being run as a vthread. See JDK-8283796.
|
||||
t1.setDaemon(false);
|
||||
@ -59,7 +55,7 @@ class ResumeOneThreadTarg extends Thread {
|
||||
|
||||
// This just starts two threads. Each runs to a bkpt.
|
||||
public void run() {
|
||||
if (getName().equals(name1)) {
|
||||
if (Thread.currentThread().getName().equals(name1)) {
|
||||
run1();
|
||||
} else {
|
||||
run2();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -43,26 +43,22 @@ import java.util.*;
|
||||
* which loop, hitting a bkpt in each iteration.
|
||||
*
|
||||
*/
|
||||
class SimulResumerTarg extends Thread {
|
||||
class SimulResumerTarg implements Runnable {
|
||||
static boolean one = false;
|
||||
static String name1 = "Thread 1";
|
||||
static String name2 = "Thread 2";
|
||||
static int count = 10000;
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Howdy!");
|
||||
SimulResumerTarg t1 = new SimulResumerTarg(name1);
|
||||
SimulResumerTarg t2 = new SimulResumerTarg(name2);
|
||||
Thread t1 = TestScaffold.newThread(new SimulResumerTarg(), name1);
|
||||
Thread t2 = TestScaffold.newThread(new SimulResumerTarg(), name2);
|
||||
|
||||
t1.start();
|
||||
t2.start();
|
||||
}
|
||||
|
||||
public SimulResumerTarg(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
if (getName().equals(name1)) {
|
||||
if (Thread.currentThread().getName().equals(name1)) {
|
||||
run1();
|
||||
} else {
|
||||
run2();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -27,6 +27,7 @@ import com.sun.jdi.event.*;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
|
||||
/**
|
||||
* Framework used by all JDI regression tests
|
||||
@ -964,6 +965,8 @@ abstract public class TestScaffold extends TargetAdapter {
|
||||
vmDisconnected = true;
|
||||
}
|
||||
|
||||
private static ThreadFactory threadFactory = r -> new Thread(r);
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
String wrapper = args[0];
|
||||
String className = args[1];
|
||||
@ -974,9 +977,10 @@ abstract public class TestScaffold extends TargetAdapter {
|
||||
mainMethod.setAccessible(true);
|
||||
|
||||
if (wrapper.equals("Virtual")) {
|
||||
threadFactory = r -> newVirtualThread(r);
|
||||
MainThreadGroup tg = new MainThreadGroup();
|
||||
// TODO fix to set virtual scheduler group when become available
|
||||
Thread vthread = startVirtualThread(() -> {
|
||||
Thread vthread = newVirtualThread(() -> {
|
||||
try {
|
||||
mainMethod.invoke(null, new Object[] { classArgs });
|
||||
} catch (InvocationTargetException e) {
|
||||
@ -987,6 +991,7 @@ abstract public class TestScaffold extends TargetAdapter {
|
||||
});
|
||||
Thread.currentThread().setName(OLD_MAIN_THREAD_NAME);
|
||||
vthread.setName("main");
|
||||
vthread.start();
|
||||
vthread.join();
|
||||
} else if (wrapper.equals("Kernel")) {
|
||||
MainThreadGroup tg = new MainThreadGroup();
|
||||
@ -1024,16 +1029,27 @@ abstract public class TestScaffold extends TargetAdapter {
|
||||
Throwable uncaughtThrowable = null;
|
||||
}
|
||||
|
||||
static Thread startVirtualThread(Runnable task) {
|
||||
// Need to use reflection while virtual threads --enable-preview feature
|
||||
private static Thread newVirtualThread(Runnable task) {
|
||||
try {
|
||||
Object builder = Thread.class.getMethod("ofVirtual").invoke(null);
|
||||
Class<?> clazz = Class.forName("java.lang.Thread$Builder");
|
||||
java.lang.reflect.Method start = clazz.getMethod("start", Runnable.class);
|
||||
return (Thread) start.invoke(builder, task);
|
||||
java.lang.reflect.Method unstarted = clazz.getMethod("unstarted", Runnable.class);
|
||||
return (Thread) unstarted.invoke(builder, task);
|
||||
} catch (RuntimeException | Error e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static Thread newThread(Runnable task) {
|
||||
return threadFactory.newThread(task);
|
||||
}
|
||||
|
||||
public static Thread newThread(Runnable task, String name) {
|
||||
Thread t = newThread(task);
|
||||
t.setName(name);
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -42,7 +42,7 @@ import java.util.*;
|
||||
* which loop, hitting a bkpt in each iteration.
|
||||
*
|
||||
*/
|
||||
class TwoThreadsTarg extends Thread {
|
||||
class TwoThreadsTarg implements Runnable {
|
||||
static boolean one = false;
|
||||
static String name1 = "Thread 1";
|
||||
static String name2 = "Thread 2";
|
||||
@ -50,19 +50,16 @@ class TwoThreadsTarg extends Thread {
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Howdy!");
|
||||
TwoThreadsTarg t1 = new TwoThreadsTarg(name1);
|
||||
TwoThreadsTarg t2 = new TwoThreadsTarg(name2);
|
||||
Thread t1 = TestScaffold.newThread(new TwoThreadsTarg(), name1);
|
||||
Thread t2 = TestScaffold.newThread(new TwoThreadsTarg(), name2);
|
||||
|
||||
t1.start();
|
||||
t2.start();
|
||||
}
|
||||
|
||||
public TwoThreadsTarg(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
if (getName().equals(name1)) {
|
||||
if (Thread.currentThread().getName().equals(name1)) {
|
||||
run1();
|
||||
} else {
|
||||
run2();
|
||||
|
Loading…
Reference in New Issue
Block a user