00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "P_EventSystem.h"
00025 #include "RegressionSM.h"
00026
00027 #define REGRESSION_SM_RETRY (100*HRTIME_MSECOND)
00028
00029 void RegressionSM::set_status(int astatus)
00030 {
00031 ink_assert(astatus != REGRESSION_TEST_INPROGRESS);
00032
00033 if (status != REGRESSION_TEST_FAILED) {
00034 if (status == REGRESSION_TEST_PASSED) {
00035 if (astatus != REGRESSION_TEST_NOT_RUN)
00036 status = astatus;
00037 } else {
00038
00039 status = astatus;
00040 }
00041 }
00042 }
00043
00044 void RegressionSM::done(int astatus)
00045 {
00046 if (pending_action) {
00047 pending_action->cancel();
00048 pending_action = 0;
00049 }
00050 set_status(astatus);
00051 if (pstatus) *pstatus = status;
00052 if (parent) parent->child_done(status);
00053 }
00054
00055 void RegressionSM::run(int *apstatus)
00056 {
00057 pstatus = apstatus;
00058 run();
00059 }
00060
00061 void RegressionSM::xrun(RegressionSM *aparent)
00062 {
00063 parent = aparent;
00064 parent->nwaiting++;
00065 run();
00066 }
00067
00068 void RegressionSM::run_in(int *apstatus, ink_hrtime t)
00069 {
00070 pstatus = apstatus;
00071 SET_HANDLER(&RegressionSM::regression_sm_start);
00072 eventProcessor.schedule_in(this, t);
00073 }
00074
00075 void RegressionSM::child_done(int astatus)
00076 {
00077 MUTEX_LOCK(l, mutex, this_ethread());
00078 ink_assert(nwaiting > 0);
00079 --nwaiting;
00080 set_status(astatus);
00081 }
00082
00083 int RegressionSM::regression_sm_waiting(int , void *data)
00084 {
00085 if (!nwaiting) {
00086 done(REGRESSION_TEST_NOT_RUN);
00087 delete this;
00088 return EVENT_DONE;
00089 }
00090 if (par || nwaiting > 1) {
00091 ((Event*)data)->schedule_in(REGRESSION_SM_RETRY);
00092 return EVENT_CONT;
00093 }
00094 run();
00095 return EVENT_DONE;
00096 }
00097
00098 int RegressionSM::regression_sm_start(int , void * )
00099 {
00100 run();
00101 return EVENT_CONT;
00102 }
00103
00104 RegressionSM *r_sequential(RegressionTest *t, RegressionSM* sm, ...)
00105 {
00106 RegressionSM *new_sm = new RegressionSM(t);
00107 va_list ap;
00108 va_start(ap, sm);
00109 new_sm->par = false;
00110 new_sm->rep = false;
00111 new_sm->ichild = 0;
00112 new_sm->nchildren = 0;
00113 new_sm->nwaiting = 0;
00114 while (0 != sm) {
00115 new_sm->children(new_sm->nchildren++) = sm;
00116 sm = va_arg(ap, RegressionSM*);
00117 }
00118 new_sm->n = new_sm->nchildren;
00119 va_end(ap);
00120 return new_sm;
00121 }
00122
00123 RegressionSM *r_sequential(RegressionTest *t, int an, RegressionSM *sm)
00124 {
00125 RegressionSM *new_sm = new RegressionSM(t);
00126 new_sm->par = false;
00127 new_sm->rep = true;
00128 new_sm->ichild = 0;
00129 new_sm->nchildren = 1;
00130 new_sm->children(0) = sm;
00131 new_sm->nwaiting = 0;
00132 new_sm->n = an;
00133 return new_sm;
00134 }
00135
00136 RegressionSM *r_parallel(RegressionTest *t, RegressionSM *sm, ...)
00137 {
00138 RegressionSM *new_sm = new RegressionSM(t);
00139 va_list ap;
00140 va_start(ap, sm);
00141 new_sm->par = true;
00142 new_sm->rep = false;
00143 new_sm->ichild = 0;
00144 new_sm->nchildren = 0;
00145 new_sm->nwaiting = 0;
00146 while (sm) {
00147 new_sm->children(new_sm->nchildren++) = sm;
00148 sm = va_arg(ap, RegressionSM*);
00149 }
00150 new_sm->n = new_sm->nchildren;
00151 va_end(ap);
00152 return new_sm;
00153 }
00154
00155 RegressionSM *r_parallel(RegressionTest *t, int an, RegressionSM *sm)
00156 {
00157 RegressionSM *new_sm = new RegressionSM(t);
00158 new_sm->par = true;
00159 new_sm->rep = true;
00160 new_sm->ichild = 0;
00161 new_sm->nchildren = 1;
00162 new_sm->children(0) = sm;
00163 new_sm->nwaiting = 0;
00164 new_sm->n = an;
00165 return new_sm;
00166 }
00167
00168 void RegressionSM::run()
00169 {
00170
00171 {
00172 MUTEX_TRY_LOCK(l, mutex, this_ethread());
00173 if (!l || nwaiting > 1)
00174 goto Lretry;
00175 RegressionSM *x = 0;
00176 while (ichild < n) {
00177 if (!rep)
00178 x = children[ichild];
00179 else {
00180 if (ichild != n-1)
00181 x = children[(intptr_t)0]->clone();
00182 else
00183 x = children[(intptr_t)0];
00184 }
00185 if (!ichild) nwaiting++;
00186 x->xrun(this);
00187 ichild++;
00188 if (!par && nwaiting > 1)
00189 goto Lretry;
00190 }
00191 }
00192 nwaiting--;
00193 if (!nwaiting) {
00194 done(REGRESSION_TEST_NOT_RUN);
00195 delete this;
00196 return;
00197 }
00198 Lretry:
00199 SET_HANDLER(&RegressionSM::regression_sm_waiting);
00200 pending_action = eventProcessor.schedule_in(this, REGRESSION_SM_RETRY);
00201 }
00202
00203 RegressionSM::RegressionSM(const RegressionSM &ao)
00204 {
00205 RegressionSM &o = *(RegressionSM*)&ao;
00206 t = o.t;
00207 status = o.status;
00208 pstatus = o.pstatus;
00209 parent = &o;
00210 nwaiting = o.nwaiting;
00211 nchildren = o.nchildren;
00212 for (intptr_t i = 0; i < nchildren; i++)
00213 children(i) = o.children[i]->clone();
00214 n = o.n;
00215 ichild = o.ichild;
00216 par = o.par;
00217 rep = o.rep;
00218 pending_action = o.pending_action;
00219 ink_assert(status == REGRESSION_TEST_INPROGRESS);
00220 ink_assert(nwaiting == 0);
00221 ink_assert(ichild == 0);
00222 mutex = new_ProxyMutex();
00223 }
00224
00225 struct ReRegressionSM: public RegressionSM
00226 {
00227 virtual void run() {
00228 if (time(NULL) < 1) {
00229 rprintf(t,"impossible");
00230 done(REGRESSION_TEST_FAILED);
00231 } else
00232 done(REGRESSION_TEST_PASSED);
00233 }
00234 ReRegressionSM(RegressionTest *at) : RegressionSM(at) {}
00235 virtual RegressionSM *clone() { return new ReRegressionSM(*this); }
00236 ReRegressionSM(const ReRegressionSM &o) {
00237 t = o.t;
00238 }
00239 };
00240
00241 REGRESSION_TEST(RegressionSM)(RegressionTest *t, int , int *pstatus)
00242 {
00243 RegressionSM *top_sm = r_sequential(t, r_parallel(t, new ReRegressionSM(t), new ReRegressionSM(t), NULL_PTR),
00244 r_sequential(t, new ReRegressionSM(t), new ReRegressionSM(t), NULL_PTR),
00245 r_parallel(t, 3, new ReRegressionSM(t)), r_sequential(t, 3, new ReRegressionSM(t)),
00246 r_parallel(t, r_sequential(t, 2, new ReRegressionSM(t)),
00247 r_parallel(t, 2, new ReRegressionSM(t)), NULL_PTR),
00248 NULL_PTR);
00249 top_sm->run(pstatus);
00250 }