2 * Copyright (C) 2014, United States Government, as represented by the
3 * Administrator of the National Aeronautics and Space Administration.
6 * The Java Pathfinder core (jpf-core) platform is licensed under the
7 * Apache License, Version 2.0 (the "License"); you may not use this file except
8 * in compliance with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0.
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
19 package gov.nasa.jpf.vm;
21 import gov.nasa.jpf.Config;
22 import gov.nasa.jpf.JPF;
23 import gov.nasa.jpf.annotation.MJI;
24 import gov.nasa.jpf.util.JPFLogger;
25 import gov.nasa.jpf.util.event.CheckEvent;
26 import gov.nasa.jpf.util.event.EventContext;
27 import gov.nasa.jpf.util.event.Event;
28 import gov.nasa.jpf.util.event.EventChoiceGenerator;
29 import gov.nasa.jpf.util.event.EventTree;
30 import gov.nasa.jpf.util.event.NoEvent;
33 * native peer for EventProducer
35 public class JPF_gov_nasa_jpf_EventProducer extends NativePeer {
37 static final String CG_NAME = "processNextEvent";
39 public static JPFLogger log = JPF.getLogger("event");
41 protected EventTree eventTree;
42 protected Event event;
44 protected EventContext ctx; // optional
46 public JPF_gov_nasa_jpf_EventProducer (Config config){
47 eventTree = config.getEssentialInstance(EventTree.CONFIG_KEY, EventTree.class);
48 ctx = config.getInstance("event.context.class", EventContext.class);
50 logger.info("event tree generated by: ", eventTree.getClass().getName());
52 logger.info("using context event: ", ctx.getClass().getName());
56 //--- those can be used by subclasses to add additional processing steps during processNextEvent
59 * override this if the event processing results in direct calls, i.e. there is no change in the model method calling
62 protected boolean hasReturnedFormDirectCall (MJIEnv env, int objRef){
67 * nothing here, to be overridden in case processing has to happen in the native peer
68 * this is only called from within generateNextEvent()
70 protected void processEvent (MJIEnv env, int objRef){
74 * evaluate a pseudo event that checks properties
76 protected boolean checkEvent (MJIEnv env, int objRef){
77 return ((CheckEvent)event).check(env, objRef);
81 * nothing here, to be overridden by subclasses that have to force states, modify the CG on the fly etc.
83 protected EventChoiceGenerator processNextCG (MJIEnv env, int objRef, EventChoiceGenerator cg){
88 * this is our main purpose in life - processing events
90 * @return true if there was another event, false if there isn't any event left on this path
93 public boolean processNextEvent____Z (MJIEnv env, int objRef){
94 ThreadInfo ti = env.getThreadInfo();
96 if (hasReturnedFormDirectCall( env, objRef)){
100 SystemState ss = env.getSystemState();
101 EventChoiceGenerator cg;
105 if (!ti.isFirstStepInsn()){
106 EventChoiceGenerator cgPrev = ss.getLastChoiceGeneratorOfType(EventChoiceGenerator.class);
108 cg = cgPrev.getSuccessor(CG_NAME, ctx);
110 cg = new EventChoiceGenerator( CG_NAME, eventTree.getRoot(), ctx);
113 if ((cg = processNextCG(env, objRef, cg)) != null){
114 if (log.isInfoLogged()){
115 log.info("next event generator: ", cg.toString());
117 ss.setNextChoiceGenerator(cg);
118 env.repeatInvocation();
119 return true; // does not matter
122 log.info("no more events");
126 } else { // re-execution
127 cg = ss.getCurrentChoiceGenerator(CG_NAME, EventChoiceGenerator.class);
128 event = cg.getNextChoice();
131 if (!(event instanceof NoEvent)) {
132 if (event instanceof CheckEvent) {
133 CheckEvent ce = (CheckEvent) event;
134 if (log.isInfoLogged()) {
135 log.info("checking: ", ce.getExpression());
137 if (!checkEvent(env, objRef)) {
138 env.throwAssertion("checking " + ce.getExpression() + " failed");
142 if (log.isInfoLogged()) {
143 log.info("processing event: ", event.toString());
145 processEvent(env, objRef);
157 @MJI(noOrphanWarning=true)
158 public int getEventName____Ljava_lang_String_2 (MJIEnv env, int objRef){
159 if (event != null && !(event instanceof NoEvent)){
160 return env.newString( event.getName());
166 //--- for testing and debugging purposes (requires special EventTree implementations e.g. derived from TestEventTree)
167 // <2do> should be moved to subclass
169 @MJI(noOrphanWarning=true)
170 public boolean checkPath____Z (MJIEnv env, int objRef){
171 SystemState ss = env.getSystemState();
172 EventChoiceGenerator cg = ss.getLastChoiceGeneratorOfType(EventChoiceGenerator.class);
175 Event lastEvent = cg.getNextChoice();
176 if (eventTree.checkPath(lastEvent)){
179 log.warning("trace check for event ", lastEvent.toString(), " failed");
184 return false; // there should have been one
188 @MJI(noOrphanWarning=true)
189 public boolean isCompletelyCovered____Z (MJIEnv env, int objRef){
190 return eventTree.isCompletelyCovered();