diff options
336 files changed, 14071 insertions, 11591 deletions
diff --git a/Makefile.in b/Makefile.in index 0b1f0930ca..b3327b5c65 100644 --- a/Makefile.in +++ b/Makefile.in @@ -121,7 +121,7 @@ BINDIR = $(DESTDIR)$(EXTRA_PREFIX)$(bindir) # # Erlang base public files # -ERL_BASE_PUB_FILES=erl erlc epmd run_erl to_erl dialyzer typer escript run_test +ERL_BASE_PUB_FILES=erl erlc epmd run_erl to_erl dialyzer typer escript ct_run run_test # ERLANG_INST_LIBDIR is the top directory where the Erlang installation # will be located when running. @@ -157,6 +157,14 @@ ERLANG_LIBDIR = $(DESTDIR)$(ERLANG_INST_LIBDIR) # Must be GNU make! MAKE = @MAKE_PROG@ +NATIVE_LIBS_ENABLED = @NATIVE_LIBS_ENABLED@ + +ifeq ($(NATIVE_LIBS_ENABLED),yes) +HIPE_BOOTSTRAP_EBIN = boot_ebin +else +HIPE_BOOTSTRAP_EBIN = ebin +endif + # This should be set to the target "arch-vendor-os" TARGET := @TARGET@ include $(ERL_TOP)/make/target.mk @@ -527,7 +535,7 @@ secondary_bootstrap_build: secondary_bootstrap_copy: if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/hipe ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/hipe ; fi if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/hipe/ebin ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/hipe/ebin ; fi - for x in lib/hipe/ebin/*.beam; do \ + for x in lib/hipe/$(HIPE_BOOTSTRAP_EBIN)/*.beam; do \ BN=`basename $$x`; \ TF=$(BOOTSTRAP_ROOT)/bootstrap/lib/hipe/ebin/$$BN; \ test -f $$TF && \ @@ -537,7 +545,6 @@ secondary_bootstrap_copy: cp $$x $$TF; \ true; \ done -# if test -f lib/hipe/ebin/hipe.beam ; then cp lib/hipe/ebin/*.beam $(BOOTSTRAP_ROOT)/bootstrap/lib/hipe/ebin; fi if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/parsetools ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/parsetools ; fi if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/parsetools/ebin ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/parsetools/ebin ; fi if test ! -d $(BOOTSTRAP_ROOT)/bootstrap/lib/parsetools/include ; then mkdir $(BOOTSTRAP_ROOT)/bootstrap/lib/parsetools/include ; fi diff --git a/bootstrap/lib/compiler/ebin/beam_disasm.beam b/bootstrap/lib/compiler/ebin/beam_disasm.beam Binary files differindex f90b5c9ae7..ec48b89de7 100644 --- a/bootstrap/lib/compiler/ebin/beam_disasm.beam +++ b/bootstrap/lib/compiler/ebin/beam_disasm.beam diff --git a/bootstrap/lib/compiler/ebin/sys_core_fold.beam b/bootstrap/lib/compiler/ebin/sys_core_fold.beam Binary files differindex 046a358910..c878868598 100644 --- a/bootstrap/lib/compiler/ebin/sys_core_fold.beam +++ b/bootstrap/lib/compiler/ebin/sys_core_fold.beam diff --git a/bootstrap/lib/compiler/ebin/v3_codegen.beam b/bootstrap/lib/compiler/ebin/v3_codegen.beam Binary files differindex a053c54295..12026564d9 100644 --- a/bootstrap/lib/compiler/ebin/v3_codegen.beam +++ b/bootstrap/lib/compiler/ebin/v3_codegen.beam diff --git a/bootstrap/lib/compiler/ebin/v3_core.beam b/bootstrap/lib/compiler/ebin/v3_core.beam Binary files differindex ba92ff6fb0..84c005edc9 100644 --- a/bootstrap/lib/compiler/ebin/v3_core.beam +++ b/bootstrap/lib/compiler/ebin/v3_core.beam diff --git a/bootstrap/lib/compiler/ebin/v3_kernel.beam b/bootstrap/lib/compiler/ebin/v3_kernel.beam Binary files differindex 0c2e54032a..cd4bf48540 100644 --- a/bootstrap/lib/compiler/ebin/v3_kernel.beam +++ b/bootstrap/lib/compiler/ebin/v3_kernel.beam diff --git a/bootstrap/lib/compiler/ebin/v3_life.beam b/bootstrap/lib/compiler/ebin/v3_life.beam Binary files differindex ec8fcda8ee..aa8b6b227b 100644 --- a/bootstrap/lib/compiler/ebin/v3_life.beam +++ b/bootstrap/lib/compiler/ebin/v3_life.beam diff --git a/bootstrap/lib/kernel/ebin/auth.beam b/bootstrap/lib/kernel/ebin/auth.beam Binary files differindex 3796221d6b..33f1ab875b 100644 --- a/bootstrap/lib/kernel/ebin/auth.beam +++ b/bootstrap/lib/kernel/ebin/auth.beam diff --git a/bootstrap/lib/stdlib/ebin/digraph_utils.beam b/bootstrap/lib/stdlib/ebin/digraph_utils.beam Binary files differindex a578c67e00..39cb9d90da 100644 --- a/bootstrap/lib/stdlib/ebin/digraph_utils.beam +++ b/bootstrap/lib/stdlib/ebin/digraph_utils.beam diff --git a/bootstrap/lib/stdlib/ebin/gen.beam b/bootstrap/lib/stdlib/ebin/gen.beam Binary files differindex bd08292a87..0a39dc1c7e 100644 --- a/bootstrap/lib/stdlib/ebin/gen.beam +++ b/bootstrap/lib/stdlib/ebin/gen.beam diff --git a/bootstrap/lib/stdlib/ebin/gen_event.beam b/bootstrap/lib/stdlib/ebin/gen_event.beam Binary files differindex c381a17787..23c4f53c30 100644 --- a/bootstrap/lib/stdlib/ebin/gen_event.beam +++ b/bootstrap/lib/stdlib/ebin/gen_event.beam diff --git a/bootstrap/lib/stdlib/ebin/gen_fsm.beam b/bootstrap/lib/stdlib/ebin/gen_fsm.beam Binary files differindex 99410275e2..c2713544ff 100644 --- a/bootstrap/lib/stdlib/ebin/gen_fsm.beam +++ b/bootstrap/lib/stdlib/ebin/gen_fsm.beam diff --git a/bootstrap/lib/stdlib/ebin/gen_server.beam b/bootstrap/lib/stdlib/ebin/gen_server.beam Binary files differindex 7698131678..3fa7d89db4 100644 --- a/bootstrap/lib/stdlib/ebin/gen_server.beam +++ b/bootstrap/lib/stdlib/ebin/gen_server.beam diff --git a/bootstrap/lib/stdlib/ebin/supervisor.beam b/bootstrap/lib/stdlib/ebin/supervisor.beam Binary files differindex 98c8f6d42e..837027e93a 100644 --- a/bootstrap/lib/stdlib/ebin/supervisor.beam +++ b/bootstrap/lib/stdlib/ebin/supervisor.beam diff --git a/configure.in b/configure.in index c8d4561a44..2c3ee1cb57 100644 --- a/configure.in +++ b/configure.in @@ -361,6 +361,12 @@ if test X${enable_m32_build} = Xyes; then export LDFLAGS fi +NATIVE_LIBS_ENABLED= +if test X${enable_native_libs} = Xyes -a X${enable_hipe} != Xno; then + NATIVE_LIBS_ENABLED=yes +fi +AC_SUBST(NATIVE_LIBS_ENABLED) + export ERL_TOP AC_CONFIG_SUBDIRS(lib erts) diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index fbe7b36163..8c438b0bd7 100644 --- a/erts/doc/src/erlang.xml +++ b/erts/doc/src/erlang.xml @@ -4881,6 +4881,7 @@ true</pre> <v>Type, Res -- see below</v> </type> <desc> + <p>All times are in milliseconds unless otherwise specified.</p> <p>Returns information about the system as specified by <c>Type</c>:</p> <taglist> @@ -4894,15 +4895,20 @@ true</pre> <item> <p>Returns <c>{Total_Exact_Reductions, Exact_Reductions_Since_Last_Call}</c>.</p> - <p><em>NOTE:</em><c>statistics(exact_reductions)</c> is - a more expensive operation than - <seealso marker="#statistics_reductions">statistics(reductions)</seealso> - especially on an Erlang machine with SMP support.</p> + <note><p><c>statistics(exact_reductions)</c> is + a more expensive operation than + <seealso marker="#statistics_reductions">statistics(reductions)</seealso> + especially on an Erlang machine with SMP support.</p> + </note> </item> <tag><c>garbage_collection</c></tag> <item> <p>Returns <c>{Number_of_GCs, Words_Reclaimed, 0}</c>. This information may not be valid for all implementations.</p> + <pre> +> <input>statistics(garbage_collection).</input> +{85,23961,0} +</pre> </item> <tag><c>io</c></tag> <item> @@ -4914,12 +4920,18 @@ true</pre> <tag><marker id="statistics_reductions"><c>reductions</c></marker></tag> <item> <p>Returns - <c>{Total_Reductions, Reductions_Since_Last_Call}</c>.</p> - <p><em>NOTE:</em> From erts version 5.5 (OTP release R11B) - this value does not include reductions performed in current - time slices of currently scheduled processes. If an - exact value is wanted, use - <seealso marker="#statistics_exact_reductions">statistics(exact_reductions)</seealso>.</p> + <c>{Total_Reductions, Reductions_Since_Last_Call}</c>.</p> + <note> + <p>From erts version 5.5 (OTP release R11B) + this value does not include reductions performed in current + time slices of currently scheduled processes. If an + exact value is wanted, use + <seealso marker="#statistics_exact_reductions">statistics(exact_reductions)</seealso>.</p> + </note> + <pre> +> <input>statistics(reductions).</input> +{2046,11} +</pre> </item> <tag><c>run_queue</c></tag> <item> @@ -4932,20 +4944,72 @@ true</pre> Note that the run-time is the sum of the run-time for all threads in the Erlang run-time system and may therefore be greater than the wall-clock time.</p> + <pre> +> <input>statistics(runtime).</input> +{1690,1620} +</pre> </item> <tag><marker id="statistics_scheduler_wall_time"><c>scheduler_wall_time</c></marker></tag> <item> - <p>Returns - <c>[{Scheduler_Id, Scheduler_Worked_Time, Scheduler_Total_Time}]</c>, time lapses are since the - the system flag <seealso marker="#system_flag_scheduler_wall_time">scheduler_wall_time</seealso> - was set to true. + <p>Returns a list of tuples with + <c>{SchedulerId, ActiveTime, TotalTime}</c>, where <c>SchedulerId</c> is an integer id of the scheduler, <c>ActiveTime</c> is + the duration the scheduler has been busy, <c>TotalTime</c> is the total time duration since + <seealso marker="#system_flag_scheduler_wall_time">scheduler_wall_time</seealso> + activation. The time unit is not defined and may be subject to change + between releases, operating systems and system restarts. + <c>scheduler_wall_time</c> should only be used to calculate relative + values for scheduler-utilization. <c>ActiveTime</c> can never exceed <c>TotalTime</c>. + </p> + + <p>The definition of a busy scheduler is when it is not idle or not + scheduling (selecting) a process or port, meaning; executing process + code, executing linked-in-driver or NIF code, executing + built-in-functions or any other runtime handling, garbage collecting + or handling any other memory management. Note, a scheduler may also be + busy even if the operating system has scheduled out the scheduler + thread. + </p> + + <p> Returns <c>undefined</c> if the system flag <seealso marker="#system_flag_scheduler_wall_time"> - scheduler_wall_time</seealso> is set to false. + scheduler_wall_time</seealso> is turned off. </p> - <p>The list of scheduler information is unsorted and may come in different order - between calls. The time unit is undefined and may be changed and should only be used - to calculate relative utilization. + + <p>The list of scheduler information is unsorted and may appear in different order + between calls. </p> + <p>Using <c>scheduler_wall_time</c> to calculate scheduler utilization.</p> +<pre> +> <input>erlang:system_flag(scheduler_wall_time, true).</input> +false +> <input>Ts0 = lists:sort(erlang:statistics(scheduler_wall_time)), ok.</input> +ok +</pre> + <p>Some time later we will take another snapshot and calculate scheduler-utilization per scheduler.</p> +<pre> +> <input>Ts1 = lists:sort(erlang:statistics(scheduler_wall_time)), ok.</input> +ok +> <input>lists:map(fun({{I, A0, T0}, {I, A1, T1}}) -> + {I, (A1 - A0)/(T1 - T0)} end, lists:zip(Ts0,Ts1)).</input> +[{1,0.9743474730177548}, + {2,0.9744843782751444}, + {3,0.9995902361669045}, + {4,0.9738012596572161}, + {5,0.9717956667018103}, + {6,0.9739235846420741}, + {7,0.973237033077876}, + {8,0.9741297293248656}] +</pre> + <p>Using the same snapshots to calculate a total scheduler-utilization.</p> +<pre> +> <input>{A, T} = lists:foldl(fun({{_, A0, T0}, {_, A1, T1}}, {Ai,Ti}) -> + {Ai + (A1 - A0), Ti + (T1 - T0)} end, {0, 0}, lists:zip(Ts0,Ts1)), A/T.</input> +0.9769136803764825 +</pre> + + <note> + <p><c>scheduler_wall_time</c> is by default disabled. Use <c>erlang:system_flag(scheduler_wall_time, true)</c> to enable it. </p> + </note> </item> <tag><c>wall_clock</c></tag> @@ -4957,14 +5021,6 @@ true</pre> opposed to runtime or CPU time.</p> </item> </taglist> - <p>All times are in milliseconds.</p> - <pre> -> <input>statistics(runtime).</input> -{1690,1620} -> <input>statistics(reductions).</input> -{2046,11} -> <input>statistics(garbage_collection).</input> -{85,23961,0}</pre> </desc> </func> <func> diff --git a/erts/emulator/Makefile.in b/erts/emulator/Makefile.in index 2bd7297231..279844adb2 100644 --- a/erts/emulator/Makefile.in +++ b/erts/emulator/Makefile.in @@ -546,12 +546,17 @@ $(TTF_DIR)/driver_tab.c: Makefile.in LANG=C $(PERL) utils/make_driver_tab -o $@ $(DRV_OBJS) GENERATE += $(TTF_DIR)/driver_tab.c + + # Preloaded code. # # This list must be consistent with PRE_LOADED_MODULES in # lib/kernel/src/Makefile. ifeq ($(TARGET),win32) -$(TARGET)/beams.rc: $(ERL_TOP)/erts/preloaded/ebin/otp_ring0.beam \ +# On windows the preloaded objects are in a resource object. +PRELOAD_OBJ = $(OBJDIR)/beams.$(RES_EXT) +PRELOAD_SRC = $(TARGET)/beams.rc +$(PRELOAD_SRC): $(ERL_TOP)/erts/preloaded/ebin/otp_ring0.beam \ $(ERL_TOP)/erts/preloaded/ebin/init.beam \ $(ERL_TOP)/erts/preloaded/ebin/prim_inet.beam \ $(ERL_TOP)/erts/preloaded/ebin/prim_file.beam \ @@ -560,9 +565,10 @@ $(TARGET)/beams.rc: $(ERL_TOP)/erts/preloaded/ebin/otp_ring0.beam \ $(ERL_TOP)/erts/preloaded/ebin/erl_prim_loader.beam \ $(ERL_TOP)/erts/preloaded/ebin/erlang.beam LANG=C $(PERL) utils/make_preload $(MAKE_PRELOAD_EXTRA) -rc $^ > $@ -GENERATE += $(TARGET)/beams.rc else -$(TARGET)/preload.c: $(ERL_TOP)/erts/preloaded/ebin/otp_ring0.beam \ +PRELOAD_OBJ = $(OBJDIR)/preload.o +PRELOAD_SRC = $(TARGET)/preload.c +$(PRELOAD_SRC): $(ERL_TOP)/erts/preloaded/ebin/otp_ring0.beam \ $(ERL_TOP)/erts/preloaded/ebin/init.beam \ $(ERL_TOP)/erts/preloaded/ebin/prim_inet.beam \ $(ERL_TOP)/erts/preloaded/ebin/prim_file.beam \ @@ -571,7 +577,6 @@ $(TARGET)/preload.c: $(ERL_TOP)/erts/preloaded/ebin/otp_ring0.beam \ $(ERL_TOP)/erts/preloaded/ebin/erl_prim_loader.beam \ $(ERL_TOP)/erts/preloaded/ebin/erlang.beam LANG=C $(PERL) utils/make_preload -old $^ > $@ -GENERATE += $(TARGET)/preload.c endif .PHONY : generate @@ -579,7 +584,8 @@ ifdef VOID_EMULATOR generate: @echo $(VOID_EMULATOR)' - omitted target generate' else -generate: $(TTF_DIR)/GENERATED +generate: $(TTF_DIR)/GENERATED $(PRELOAD_SRC) + $(TTF_DIR)/GENERATED: $(GENERATE) echo $? >$(TTF_DIR)/GENERATED endif @@ -660,7 +666,7 @@ endif # CS_SRC = sys/$(ERLANG_OSTYPE)/erl_child_setup.c -$(BINDIR)/$(CS_EXECUTABLE): $(TTF_DIR)/GENERATED $(CS_SRC) $(ERTS_LIB) +$(BINDIR)/$(CS_EXECUTABLE): $(TTF_DIR)/GENERATED $(PRELOAD_SRC) $(CS_SRC) $(ERTS_LIB) $(CS_PURIFY) $(CC) $(CS_LDFLAGS) -o $(BINDIR)/$(CS_EXECUTABLE) \ $(CS_CFLAGS) $(COMMON_INCLUDES) $(CS_SRC) $(CS_LIBS) @@ -689,16 +695,7 @@ $(ERL_TOP)/lib/%.beam: # Object files # -# On windows the preloaded objects are in a resource object. - -ifeq ($(TARGET),win32) -PRELOAD = $(OBJDIR)/beams.$(RES_EXT) -else -PRELOAD = $(OBJDIR)/preload.o -endif - - -INIT_OBJS = $(OBJDIR)/erl_main.o $(PRELOAD) +INIT_OBJS = $(OBJDIR)/erl_main.o $(PRELOAD_OBJ) EMU_OBJS = \ $(OBJDIR)/beam_emu.o $(OBJDIR)/beam_opcodes.o \ @@ -1035,7 +1032,7 @@ depend: @echo $(VOID_EMULATOR)' - omitted target depend' else depend: $(TTF_DIR)/depend.mk -$(TTF_DIR)/depend.mk: $(TTF_DIR)/GENERATED +$(TTF_DIR)/depend.mk: $(TTF_DIR)/GENERATED $(PRELOAD_SRC) $(DEP_CC) $(DEP_FLAGS) $(BEAM_SRC) \ | $(SED_DEPEND) > $(TTF_DIR)/depend.mk $(DEP_CC) $(DEP_FLAGS) -DLIBSCTP=$(LIBSCTP) $(DRV_COMMON_SRC) \ diff --git a/erts/emulator/beam/erl_thr_progress.h b/erts/emulator/beam/erl_thr_progress.h index 1bbc49993e..a71724b813 100644 --- a/erts/emulator/beam/erl_thr_progress.h +++ b/erts/emulator/beam/erl_thr_progress.h @@ -138,6 +138,7 @@ ERTS_GLB_INLINE ErtsThrPrgrVal erts_thr_prgr_read_acqb__(ERTS_THR_PRGR_ATOMIC *a ERTS_GLB_INLINE ErtsThrPrgrVal erts_thr_prgr_read_mb__(ERTS_THR_PRGR_ATOMIC *atmc); ERTS_GLB_INLINE int erts_thr_progress_is_managed_thread(void); +ERTS_GLB_INLINE ErtsThrPrgrVal erts_thr_progress_current_to_later__(ErtsThrPrgrVal val); ERTS_GLB_INLINE ErtsThrPrgrVal erts_thr_progress_later_than(ErtsThrPrgrVal val); ERTS_GLB_INLINE ErtsThrPrgrVal erts_thr_progress_later(void); ERTS_GLB_INLINE ErtsThrPrgrVal erts_thr_progress_current(void); @@ -218,9 +219,8 @@ erts_thr_progress_is_managed_thread(void) } ERTS_GLB_INLINE ErtsThrPrgrVal -erts_thr_progress_later_than(ErtsThrPrgrVal val) +erts_thr_progress_current_to_later__(ErtsThrPrgrVal val) { - ERTS_THR_MEMORY_BARRIER; if (val == (ERTS_THR_PRGR_VAL_WAITING-((ErtsThrPrgrVal)2))) return ((ErtsThrPrgrVal) 0); else if (val == (ERTS_THR_PRGR_VAL_WAITING-((ErtsThrPrgrVal)1))) @@ -230,10 +230,17 @@ erts_thr_progress_later_than(ErtsThrPrgrVal val) } ERTS_GLB_INLINE ErtsThrPrgrVal +erts_thr_progress_later_than(ErtsThrPrgrVal val) +{ + ERTS_THR_MEMORY_BARRIER; + return erts_thr_progress_current_to_later__(val); +} + +ERTS_GLB_INLINE ErtsThrPrgrVal erts_thr_progress_later(void) { ErtsThrPrgrVal val = erts_thr_prgr_read_mb__(&erts_thr_prgr__.current); - return erts_thr_progress_later_than(val); + return erts_thr_progress_current_to_later__(val); } ERTS_GLB_INLINE ErtsThrPrgrVal diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c index b23b1f628d..fe1a7ba345 100644 --- a/erts/emulator/beam/io.c +++ b/erts/emulator/beam/io.c @@ -743,7 +743,7 @@ driver_create_port(ErlDrvPort creator_port_ix, /* Creating port */ return (ErlDrvTermData) -1; /* pid does not exist */ } if ((port_num = get_free_port()) < 0) { - errno = ENFILE; + errno = SYSTEM_LIMIT; erts_smp_proc_unlock(rp, ERTS_PROC_LOCK_LINK); erts_smp_mtx_unlock(&erts_driver_list_lock); return (ErlDrvTermData) -1; diff --git a/erts/emulator/drivers/common/efile_drv.c b/erts/emulator/drivers/common/efile_drv.c index 36ed108b76..a251b064da 100644 --- a/erts/emulator/drivers/common/efile_drv.c +++ b/erts/emulator/drivers/common/efile_drv.c @@ -156,11 +156,11 @@ static ErlDrvSysInfo sys_info; * DARWIN. The testcase t_sendfile_crashduring reproduces * this error when using +A 10. */ -#if !defined(DARWIN) -#define USE_THRDS_FOR_SENDFILE (sys_info.async_threads > 0) -#else +#if defined(__APPLE__) && defined(__MACH__) #define USE_THRDS_FOR_SENDFILE 0 -#endif /* !DARWIN */ +#else +#define USE_THRDS_FOR_SENDFILE (sys_info.async_threads > 0) +#endif /* defined(__APPLE__) && defined(__MACH__) */ @@ -259,6 +259,7 @@ static void file_stop_select(ErlDrvEvent event, void* _); enum e_timer {timer_idle, timer_again, timer_write}; #ifdef HAVE_SENDFILE enum e_sendfile {sending, not_sending}; +static void free_sendfile(void *data); #endif /* HAVE_SENDFILE */ struct t_data; @@ -445,6 +446,8 @@ struct t_data } fadvise; #ifdef HAVE_SENDFILE struct { + ErlDrvPort port; + ErlDrvPDL q_mtx; int out_fd; off_t offset; Uint64 nbytes; @@ -752,15 +755,6 @@ file_stop(ErlDrvData e) TRACE_C('p'); -#ifdef HAVE_SENDFILE - if (desc->sendfile_state == sending && !USE_THRDS_FOR_SENDFILE) { - driver_select(desc->port,(ErlDrvEvent)(long)desc->d->c.sendfile.out_fd, - ERL_DRV_WRITE|ERL_DRV_USE,0); - } else if (desc->sendfile_state == sending) { - SET_NONBLOCKING(desc->d->c.sendfile.out_fd); - } -#endif /* HAVE_SENDFILE */ - if (desc->fd != FILE_FD_INVALID) { do_close(desc->flags, desc->fd); desc->fd = FILE_FD_INVALID; @@ -1783,26 +1777,31 @@ static void invoke_sendfile(void *data) d->c.sendfile.written += nbytes; - if (result == 1) { - if (USE_THRDS_FOR_SENDFILE) { - d->result_ok = 0; - } else if (d->c.sendfile.nbytes == 0 && nbytes != 0) { - d->result_ok = 1; - } else if ((d->c.sendfile.nbytes - nbytes) != 0) { - d->result_ok = 1; - d->c.sendfile.nbytes -= nbytes; - } else { - d->result_ok = 0; - } + if (result == 1 || (result == 0 && USE_THRDS_FOR_SENDFILE)) { + d->result_ok = 0; } else if (result == 0 && (d->errInfo.posix_errno == EAGAIN || d->errInfo.posix_errno == EINTR)) { + if ((d->c.sendfile.nbytes - nbytes) != 0) { d->result_ok = 1; + if (d->c.sendfile.nbytes != 0) + d->c.sendfile.nbytes -= nbytes; + } else + d->result_ok = 0; } else { d->result_ok = -1; } } static void free_sendfile(void *data) { + struct t_data *d = (struct t_data *)data; + if (USE_THRDS_FOR_SENDFILE) { + SET_NONBLOCKING(d->c.sendfile.out_fd); + } else { + MUTEX_LOCK(d->c.sendfile.q_mtx); + driver_deq(d->c.sendfile.port,1); + MUTEX_UNLOCK(d->c.sendfile.q_mtx); + driver_select(d->c.sendfile.port, (ErlDrvEvent)(long)d->c.sendfile.out_fd, ERL_DRV_USE_NO_CALLBACK|ERL_DRV_WRITE, 0); + } EF_FREE(data); } @@ -1812,7 +1811,7 @@ static void file_ready_output(ErlDrvData data, ErlDrvEvent event) switch (fd->d->command) { case FILE_SENDFILE: - driver_select(fd->port, event, + driver_select(fd->d->c.sendfile.port, event, (int)ERL_DRV_WRITE,(int) 0); invoke_sendfile((void *)fd->d); file_async_ready(data, (ErlDrvThreadData)fd->d); @@ -1826,6 +1825,15 @@ static void file_stop_select(ErlDrvEvent event, void* _) { } + +static int flush_sendfile(file_descriptor *desc,void *_) { + if (desc->sendfile_state == sending) { + desc->d->result_ok = -1; + desc->d->errInfo.posix_errno = ECONNABORTED; + file_async_ready((ErlDrvData)desc,(ErlDrvThreadData)desc->d); + } + return 1; +} #endif /* HAVE_SENDFILE */ @@ -2248,36 +2256,23 @@ file_async_ready(ErlDrvData e, ErlDrvThreadData data) #ifdef HAVE_SENDFILE case FILE_SENDFILE: if (d->result_ok == -1) { - desc->sendfile_state = not_sending; if (d->errInfo.posix_errno == ECONNRESET || d->errInfo.posix_errno == ENOTCONN || d->errInfo.posix_errno == EPIPE) reply_string_error(desc,"closed"); else reply_error(desc, &d->errInfo); - if (USE_THRDS_FOR_SENDFILE) { - SET_NONBLOCKING(d->c.sendfile.out_fd); - free_sendfile(data); - } else { - driver_select(desc->port, (ErlDrvEvent)(long)d->c.sendfile.out_fd, - ERL_DRV_USE, 0); - free_sendfile(data); - } - } else if (d->result_ok == 0) { desc->sendfile_state = not_sending; + free_sendfile(data); + } else if (d->result_ok == 0) { reply_Sint64(desc, d->c.sendfile.written); - if (USE_THRDS_FOR_SENDFILE) { - SET_NONBLOCKING(d->c.sendfile.out_fd); - free_sendfile(data); - } else { - driver_select(desc->port, (ErlDrvEvent)(long)d->c.sendfile.out_fd, ERL_DRV_USE, 0); - free_sendfile(data); - } + desc->sendfile_state = not_sending; + free_sendfile(data); } else if (d->result_ok == 1) { // If we are using select to send the rest of the data desc->sendfile_state = sending; desc->d = d; driver_select(desc->port, (ErlDrvEvent)(long)d->c.sendfile.out_fd, - ERL_DRV_USE|ERL_DRV_WRITE, 1); + ERL_DRV_USE_NO_CALLBACK|ERL_DRV_WRITE, 1); } break; #endif @@ -2655,6 +2650,10 @@ file_flush(ErlDrvData e) { TRACE_C('f'); +#ifdef HAVE_SENDFILE + flush_sendfile(desc, NULL); +#endif + #ifdef DEBUG r = #endif @@ -3454,11 +3453,13 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { d->fd = desc->fd; d->command = command; d->invoke = invoke_sendfile; - d->free = NULL; + d->free = free_sendfile; d->level = 2; d->c.sendfile.out_fd = (int) out_fd; d->c.sendfile.written = 0; + d->c.sendfile.port = desc->port; + d->c.sendfile.q_mtx = desc->q_mtx; #if SIZEOF_OFF_T == 4 if (offsetH != 0) { @@ -3474,6 +3475,19 @@ file_outputv(ErlDrvData e, ErlIOVec *ev) { if (USE_THRDS_FOR_SENDFILE) { SET_BLOCKING(d->c.sendfile.out_fd); + } else { + /** + * Write a place holder to queue in order to force file_flush + * to be called before the driver is closed. + */ + char tmp[1] = ""; + MUTEX_LOCK(d->c.sendfile.q_mtx); + if (driver_enq(d->c.sendfile.port, tmp, 1)) { + MUTEX_UNLOCK(d->c.sendfile.q_mtx); + reply_posix_error(desc, ENOMEM); + goto done; + } + MUTEX_UNLOCK(d->c.sendfile.q_mtx); } cq_enq(desc, d); diff --git a/erts/emulator/drivers/common/inet_drv.c b/erts/emulator/drivers/common/inet_drv.c index 47a99fdbe6..d1c2dbf94c 100644 --- a/erts/emulator/drivers/common/inet_drv.c +++ b/erts/emulator/drivers/common/inet_drv.c @@ -553,6 +553,12 @@ static int my_strncasecmp(const char *s1, const char *s2, size_t n) # define VALGRIND_MAKE_MEM_DEFINED(ptr,size) #endif +/* + Magic errno value used locally for return of {error, system_limit} + - the emulator definition of SYSTEM_LIMIT is not available here. +*/ +#define INET_ERRNO_SYSTEM_LIMIT (15 << 8) + /*---------------------------------------------------------------------------- ** Interface constants. ** @@ -1645,6 +1651,17 @@ static struct erl_drv_entry dummy_sctp_driver_entry = #endif +/* return lowercase string form of errno value */ +static char *errno_str(int err) +{ + switch (err) { + case INET_ERRNO_SYSTEM_LIMIT: + return "system_limit"; + default: + return erl_errno_id(err); + } +} + /* general control reply function */ static ErlDrvSSizeT ctl_reply(int rep, char* buf, ErlDrvSizeT len, char** rbuf, ErlDrvSizeT rsize) @@ -1665,13 +1682,9 @@ static ErlDrvSSizeT ctl_reply(int rep, char* buf, ErlDrvSizeT len, /* general control error reply function */ static ErlDrvSSizeT ctl_error(int err, char** rbuf, ErlDrvSizeT rsize) { - char response[256]; /* Response buffer. */ - char* s; - char* t; + char* s = errno_str(err); - for (s = erl_errno_id(err), t = response; *s; s++, t++) - *t = tolower(*s); - return ctl_reply(INET_REP_ERROR, response, t-response, rbuf, rsize); + return ctl_reply(INET_REP_ERROR, s, strlen(s), rbuf, rsize); } static ErlDrvSSizeT ctl_xerror(char* xerr, char** rbuf, ErlDrvSizeT rsize) @@ -1683,14 +1696,7 @@ static ErlDrvSSizeT ctl_xerror(char* xerr, char** rbuf, ErlDrvSizeT rsize) static ErlDrvTermData error_atom(int err) { - char errstr[256]; - char* s; - char* t; - - for (s = erl_errno_id(err), t = errstr; *s; s++, t++) - *t = tolower(*s); - *t = '\0'; - return driver_mk_atom(errstr); + return driver_mk_atom(errno_str(err)); } @@ -4089,6 +4095,7 @@ static char* buf_to_sockaddr(char* ptr, char* end, struct sockaddr* addr) addr->sa_family = AF_INET; return ptr + sizeof(struct in_addr); } +#if defined(HAVE_IN6) && defined(AF_INET6) case INET_AF_INET6: { struct in6_addr *p = &((struct sockaddr_in6*)addr)->sin6_addr; buf_check(ptr,end,sizeof(struct in6_addr)); @@ -4096,6 +4103,7 @@ static char* buf_to_sockaddr(char* ptr, char* end, struct sockaddr* addr) addr->sa_family = AF_INET6; return ptr + sizeof(struct in6_addr); } +#endif } error: return NULL; @@ -8051,7 +8059,7 @@ static ErlDrvData tcp_inet_start(ErlDrvPort port, char* args) /* Copy a descriptor, by creating a new port with same settings * as the descriptor desc. - * return NULL on error (ENFILE no ports avail) + * return NULL on error (SYSTEM_LIMIT no ports avail) */ static tcp_descriptor* tcp_inet_copy(tcp_descriptor* desc,SOCKET s, ErlDrvTermData owner, int* err) @@ -8090,7 +8098,7 @@ static tcp_descriptor* tcp_inet_copy(tcp_descriptor* desc,SOCKET s, /* The new port will be linked and connected to the original caller */ port = driver_create_port(port, owner, "tcp_inet", (ErlDrvData) copy_desc); if ((long)port == -1) { - *err = ENFILE; + *err = INET_ERRNO_SYSTEM_LIMIT; FREE(copy_desc); return NULL; } diff --git a/erts/emulator/drivers/common/zlib_drv.c b/erts/emulator/drivers/common/zlib_drv.c index da4a17db1a..a4b02b845e 100644 --- a/erts/emulator/drivers/common/zlib_drv.c +++ b/erts/emulator/drivers/common/zlib_drv.c @@ -64,6 +64,7 @@ static int zlib_init(void); static ErlDrvData zlib_start(ErlDrvPort port, char* buf); static void zlib_stop(ErlDrvData e); +static void zlib_flush(ErlDrvData e); static ErlDrvSSizeT zlib_ctl(ErlDrvData drv_data, unsigned int command, char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen); static void zlib_outputv(ErlDrvData drv_data, ErlIOVec *ev); @@ -82,7 +83,7 @@ ErlDrvEntry zlib_driver_entry = { NULL, /* timeout */ zlib_outputv, NULL, /* read_async */ - NULL, /* flush */ + zlib_flush, NULL, /* call */ NULL, /* event */ ERL_DRV_EXTENDED_MARKER, @@ -410,6 +411,13 @@ static void zlib_stop(ErlDrvData e) driver_free(d); } +static void zlib_flush(ErlDrvData drv_data) +{ + ZLibData* d = (ZLibData*) drv_data; + + driver_deq(d->port, driver_sizeq(d->port)); +} + static ErlDrvSSizeT zlib_ctl(ErlDrvData drv_data, unsigned int command, char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen) { diff --git a/erts/emulator/drivers/unix/unix_efile.c b/erts/emulator/drivers/unix/unix_efile.c index 796843a735..dfb6cece14 100644 --- a/erts/emulator/drivers/unix/unix_efile.c +++ b/erts/emulator/drivers/unix/unix_efile.c @@ -1426,6 +1426,14 @@ efile_fadvise(Efile_error* errInfo, int fd, Sint64 offset, * you would have to emulate it in linux and on BSD/Darwin some complex * calculations have to be made when using a non blocking socket to figure * out how much of the header/file/trailer was sent in each command. + * + * The semantics of the API is this: + * Return value: 1 if all data was sent and the function does not need to + * be called again. 0 if an error occures OR if there is more data which + * has to be sent (EAGAIN or EINTR will be set appropriately) + * + * The amount of data written in a call is returned through nbytes. + * */ int @@ -1446,8 +1454,11 @@ efile_sendfile(Efile_error* errInfo, int in_fd, int out_fd, *nbytes -= retval; } } while (retval == SENDFILE_CHUNK_SIZE); - *nbytes = written; - return check_error(retval == -1 ? -1 : 0, errInfo); + if (written != 0) { + // -1 is not returned by the linux API so we have to simulate it + retval = -1; + errno = EAGAIN; + } #elif defined(__sun) && defined(__SVR4) && defined(HAVE_SENDFILEV) ssize_t retval; size_t len; @@ -1469,8 +1480,6 @@ efile_sendfile(Efile_error* errInfo, int in_fd, int out_fd, written += len; } } while (len == SENDFILE_CHUNK_SIZE); - *nbytes = written; - return check_error(retval == -1 ? -1 : 0, errInfo); #elif defined(DARWIN) int retval; off_t len; @@ -1487,8 +1496,6 @@ efile_sendfile(Efile_error* errInfo, int in_fd, int out_fd, written += len; } } while (len == SENDFILE_CHUNK_SIZE); - *nbytes = written; - return check_error(retval, errInfo); #elif defined(__FreeBSD__) || defined(__DragonFly__) off_t len; int retval; @@ -1504,8 +1511,8 @@ efile_sendfile(Efile_error* errInfo, int in_fd, int out_fd, written += len; } } while(len == SENDFILE_CHUNK_SIZE); +#endif *nbytes = written; return check_error(retval, errInfo); -#endif } #endif /* HAVE_SENDFILE */ diff --git a/erts/emulator/test/erts_debug_SUITE.erl b/erts/emulator/test/erts_debug_SUITE.erl index 4dc2fbaae2..76667772c7 100644 --- a/erts/emulator/test/erts_debug_SUITE.erl +++ b/erts/emulator/test/erts_debug_SUITE.erl @@ -23,13 +23,13 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, init_per_testcase/2,end_per_testcase/2, - flat_size/1,flat_size_big/1,df/1, + test_size/1,flat_size_big/1,df/1, instructions/1]). suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> - [flat_size, flat_size_big, df, instructions]. + [test_size, flat_size_big, df, instructions]. groups() -> []. @@ -55,16 +55,58 @@ end_per_testcase(_Func, Config) -> Dog=?config(watchdog, Config), ?t:timetrap_cancel(Dog). -flat_size(Config) when is_list(Config) -> - 0 = erts_debug:flat_size([]), - 0 = erts_debug:flat_size(42), - 2 = erts_debug:flat_size([a|b]), - 1 = erts_debug:flat_size({}), - 2 = erts_debug:flat_size({[]}), - 3 = erts_debug:flat_size({a,b}), - 7 = erts_debug:flat_size({a,[b,c]}), +test_size(Config) when is_list(Config) -> + ConsCell1 = id([a|b]), + ConsCell2 = id(ConsCell1), + ConsCellSz = 2, + + 0 = do_test_size([]), + 0 = do_test_size(42), + ConsCellSz = do_test_size(ConsCell1), + 1 = do_test_size({}), + 2 = do_test_size({[]}), + 3 = do_test_size({a,b}), + 7 = do_test_size({a,[b,c]}), + + %% Test internal consistency of sizes, but without testing + %% exact sizes. + Const = id(42), + AnotherConst = id(7), + + %% Fun environment size = 0 (the smallest fun possible) + SimplestFun = fun() -> ok end, + FunSz0 = do_test_size(SimplestFun), + + %% Fun environment size = 1 + FunSz1 = do_test_size(fun() -> Const end), + FunSz1 = FunSz0 + 1, + + %% Fun environment size = 2 + FunSz2 = do_test_size(fun() -> Const+AnotherConst end), + FunSz2 = FunSz1 + 1, + + FunSz1 = do_test_size(fun() -> ConsCell1 end) - do_test_size(ConsCell1), + + %% Test shared data structures. + do_test_size([ConsCell1|ConsCell1], + 3*ConsCellSz, + 2*ConsCellSz), + do_test_size(fun() -> {ConsCell1,ConsCell2} end, + FunSz2 + 2*ConsCellSz, + FunSz2 + ConsCellSz), + do_test_size({SimplestFun,SimplestFun}, + 2*FunSz0+do_test_size({a,b}), + FunSz0+do_test_size({a,b})), ok. +do_test_size(Term) -> + Sz = erts_debug:flat_size(Term), + Sz = erts_debug:size(Term). + +do_test_size(Term, FlatSz, Sz) -> + FlatSz = erts_debug:flat_size(Term), + Sz = erts_debug:size(Term). + flat_size_big(Config) when is_list(Config) -> %% Build a term whose external size only fits in a big num (on 32-bit CPU). flat_size_big_1(16#11111111111111117777777777777777888889999, 0, 16#FFFFFFF). @@ -96,3 +138,6 @@ instructions(Config) when is_list(Config) -> ?line Is = erts_debug:instructions(), ?line _ = [list_to_atom(I) || I <- Is], ok. + +id(I) -> + I. diff --git a/erts/etc/common/escript.c b/erts/etc/common/escript.c index 6ed79c91e3..e70c95b67c 100644 --- a/erts/etc/common/escript.c +++ b/erts/etc/common/escript.c @@ -377,7 +377,8 @@ main(int argc, char** argv) last_opt = argv; #ifdef __WIN32__ - if (_stricmp(basename, "escript.exe") == 0) { + if ( (_stricmp(basename, "escript.exe") == 0) + ||(_stricmp(basename, "escript") == 0)) { #else if (strcmp(basename, "escript") == 0) { #endif diff --git a/erts/etc/unix/etp-commands b/erts/etc/unix/etp-commands index 6a01e0b7e0..79e5d6b1d8 100644 --- a/erts/etc/unix/etp-commands +++ b/erts/etc/unix/etp-commands @@ -1883,6 +1883,28 @@ document etp-ets-tables %--------------------------------------------------------------------------- end +define etp-ets-obj +# Args: DbTerm* +# + set $etp_ets_obj_i = 1 + while $etp_ets_obj_i <= (($arg0)->tpl[0] >> 6) + if $etp_ets_obj_i == 1 + printf "{" + else + printf ", " + end + set $etp_ets_elem = ($arg0)->tpl[$etp_ets_obj_i] + if ($etp_ets_elem & 3) == 0 + printf "<compressed>" + else + etp-1 $etp_ets_elem 0 + end + set $etp_ets_obj_i++ + end + printf "}" +end + + define etp-ets-tabledump # Args: int tableindex # @@ -1896,10 +1918,10 @@ define etp-ets-tabledump if $etp_ets_tabledump_t->common.status & 0x130 # Hash table set $etp_ets_tabledump_h = $etp_ets_tabledump_t->hash - printf "%% nitems=%d\n", $etp_ets_tabledump_t->common.nitems - while $etp_ets_tabledump_i < $etp_ets_tabledump_h->nactive - set $etp_ets_tabledump_l = $etp_ets_tabledump_h->seg \ - [$etp_ets_tabledump_i>>8][$etp_ets_tabledump_i&0xFF] + printf "%% nitems=%d\n", (long) $etp_ets_tabledump_t->common.nitems + while $etp_ets_tabledump_i < (long) $etp_ets_tabledump_h->nactive + set $etp_ets_tabledump_seg = ((struct segment**)$etp_ets_tabledump_h->segtab)[$etp_ets_tabledump_i>>8] + set $etp_ets_tabledump_l = $etp_ets_tabledump_seg->buckets[$etp_ets_tabledump_i&0xFF] if $etp_ets_tabledump_l printf "%% Slot %d:\n", $etp_ets_tabledump_i while $etp_ets_tabledump_l @@ -1909,7 +1931,7 @@ define etp-ets-tabledump printf "[" end set $etp_ets_tabledump_n++ - etp-1 ((Eterm)($etp_ets_tabledump_l->dbterm.tpl)|0x2) 0 + etp-ets-obj &($etp_ets_tabledump_l->dbterm) if $etp_ets_tabledump_l->hvalue == ((unsigned long)-1) printf "% *\n" else diff --git a/erts/lib_src/common/erl_misc_utils.c b/erts/lib_src/common/erl_misc_utils.c index 5e94ff19db..162c908285 100644 --- a/erts/lib_src/common/erl_misc_utils.c +++ b/erts/lib_src/common/erl_misc_utils.c @@ -727,7 +727,7 @@ adjust_processor_nodes(erts_cpu_info_t *cpuinfo, int no_nodes) prev = NULL; this = &cpuinfo->topology[0]; - last = &cpuinfo->topology[cpuinfo->configured-1]; + last = &cpuinfo->topology[cpuinfo->topology_size-1]; while (1) { if (processor == this->processor) { if (node != this->node) @@ -834,8 +834,8 @@ read_topology(erts_cpu_info_t *cpuinfo) ix = -1; if (realpath(ERTS_SYS_NODE_PATH, npath)) { - got_nodes = 1; ndir = opendir(npath); + got_nodes = (ndir != NULL); } do { @@ -939,7 +939,7 @@ read_topology(erts_cpu_info_t *cpuinfo) if (res > 1) { prev = this++; - last = &cpuinfo->topology[cpuinfo->configured-1]; + last = &cpuinfo->topology[cpuinfo->topology_size-1]; while (1) { this->thread = ((this->node == prev->node @@ -1094,7 +1094,7 @@ read_topology(erts_cpu_info_t *cpuinfo) if (res > 1) { prev = this++; - last = &cpuinfo->topology[cpuinfo->configured-1]; + last = &cpuinfo->topology[cpuinfo->topology_size-1]; while (1) { this->thread = ((this->node == prev->node diff --git a/erts/lib_src/common/ethr_atomics.c b/erts/lib_src/common/ethr_atomics.c index e4213e1eef..c52166a7ec 100644 --- a/erts/lib_src/common/ethr_atomics.c +++ b/erts/lib_src/common/ethr_atomics.c @@ -561,12 +561,14 @@ int ethr_dw_atomic_cmpxchg(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_s } #endif -int ETHR_DW_ATOMIC_FUNC__(cmpxchg_ddrb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val) +int ethr_dw_atomic_cmpxchg_ddrb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val, ethr_dw_sint_t *old_val) { -#ifdef ETHR_ORDERED_READ_DEPEND - return ETHR_DW_ATOMIC_FUNC__(cmpxchg)(var, val, old_val); +#if defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS) + return ethr_dw_atomic_cmpxchg_ddrb__(var, val, old_val); +#elif defined(ETHR_ORDERED_READ_DEPEND) + return ethr_dw_atomic_cmpxchg(var, val, old_val); #else - return ETHR_DW_ATOMIC_FUNC__(cmpxchg_rb)(var, val, old_val); + return ethr_dw_atomic_cmpxchg_rb(var, val, old_val); #endif } @@ -784,12 +786,14 @@ void ethr_dw_atomic_set(ethr_dw_atomic_t *var, ethr_dw_sint_t *val) } #endif -void ETHR_DW_ATOMIC_FUNC__(set_ddrb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val) +void ethr_dw_atomic_set_ddrb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val) { -#ifdef ETHR_ORDERED_READ_DEPEND - ETHR_DW_ATOMIC_FUNC__(set)(var, val); +#if defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS) + ethr_dw_atomic_set_ddrb__(var, val); +#elif defined(ETHR_ORDERED_READ_DEPEND) + ethr_dw_atomic_set(var, val); #else - ETHR_DW_ATOMIC_FUNC__(set_rb)(var, val); + ethr_dw_atomic_set_rb(var, val); #endif } @@ -947,12 +951,14 @@ void ethr_dw_atomic_read(ethr_dw_atomic_t *var, ethr_dw_sint_t *val) } #endif -void ETHR_DW_ATOMIC_FUNC__(read_ddrb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val) +void ethr_dw_atomic_read_ddrb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val) { -#ifdef ETHR_ORDERED_READ_DEPEND - ETHR_DW_ATOMIC_FUNC__(read)(var, val); +#if defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS) + ethr_dw_atomic_read_ddrb__(var, val); +#elif defined(ETHR_ORDERED_READ_DEPEND) + ethr_dw_atomic_read(var, val); #else - ETHR_DW_ATOMIC_FUNC__(read_rb)(var, val); + ethr_dw_atomic_read_rb(var, val); #endif } @@ -1107,12 +1113,14 @@ void ethr_dw_atomic_init(ethr_dw_atomic_t *var, ethr_dw_sint_t *val) } #endif -void ETHR_DW_ATOMIC_FUNC__(init_ddrb)(ethr_dw_atomic_t *var, ethr_dw_sint_t *val) +void ethr_dw_atomic_init_ddrb(ethr_dw_atomic_t *var, ethr_dw_sint_t *val) { -#ifdef ETHR_ORDERED_READ_DEPEND - ETHR_DW_ATOMIC_FUNC__(init)(var, val); +#if defined(ETHR_HAVE_DOUBLE_WORD_SZ_NATIVE_ATOMIC_OPS) + ethr_dw_atomic_init_ddrb__(var, val); +#elif defined(ETHR_ORDERED_READ_DEPEND) + ethr_dw_atomic_init(var, val); #else - ETHR_DW_ATOMIC_FUNC__(init_rb)(var, val); + ethr_dw_atomic_init_rb(var, val); #endif } @@ -1278,7 +1286,9 @@ ethr_sint_t ethr_atomic_cmpxchg(ethr_atomic_t *var, ethr_sint_t val, ethr_sint_t ethr_sint_t ethr_atomic_cmpxchg_ddrb(ethr_atomic_t *var, ethr_sint_t val, ethr_sint_t old_val) { -#ifdef ETHR_ORDERED_READ_DEPEND +#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS) + return ethr_atomic_cmpxchg_ddrb__(var, val, old_val); +#elif defined(ETHR_ORDERED_READ_DEPEND) return ethr_atomic_cmpxchg(var, val, old_val); #else return ethr_atomic_cmpxchg_rb(var, val, old_val); @@ -1398,7 +1408,9 @@ ethr_sint_t ethr_atomic_xchg(ethr_atomic_t *var, ethr_sint_t val) ethr_sint_t ethr_atomic_xchg_ddrb(ethr_atomic_t *var, ethr_sint_t val) { -#ifdef ETHR_ORDERED_READ_DEPEND +#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS) + return ethr_atomic_xchg_ddrb__(var, val); +#elif defined(ETHR_ORDERED_READ_DEPEND) return ethr_atomic_xchg(var, val); #else return ethr_atomic_xchg_rb(var, val); @@ -1512,7 +1524,9 @@ void ethr_atomic_set(ethr_atomic_t *var, ethr_sint_t val) void ethr_atomic_set_ddrb(ethr_atomic_t *var, ethr_sint_t val) { -#ifdef ETHR_ORDERED_READ_DEPEND +#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS) + ethr_atomic_set_ddrb__(var, val); +#elif defined(ETHR_ORDERED_READ_DEPEND) ethr_atomic_set(var, val); #else ethr_atomic_set_rb(var, val); @@ -1620,7 +1634,9 @@ void ethr_atomic_init(ethr_atomic_t *var, ethr_sint_t val) void ethr_atomic_init_ddrb(ethr_atomic_t *var, ethr_sint_t val) { -#ifdef ETHR_ORDERED_READ_DEPEND +#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS) + ethr_atomic_init_ddrb__(var, val); +#elif defined(ETHR_ORDERED_READ_DEPEND) ethr_atomic_init(var, val); #else ethr_atomic_init_rb(var, val); @@ -1725,7 +1741,9 @@ ethr_sint_t ethr_atomic_add_read(ethr_atomic_t *var, ethr_sint_t val) ethr_sint_t ethr_atomic_add_read_ddrb(ethr_atomic_t *var, ethr_sint_t val) { -#ifdef ETHR_ORDERED_READ_DEPEND +#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS) + return ethr_atomic_add_read_ddrb__(var, val); +#elif defined(ETHR_ORDERED_READ_DEPEND) return ethr_atomic_add_read(var, val); #else return ethr_atomic_add_read_rb(var, val); @@ -1840,7 +1858,9 @@ ethr_sint_t ethr_atomic_read(ethr_atomic_t *var) ethr_sint_t ethr_atomic_read_ddrb(ethr_atomic_t *var) { -#ifdef ETHR_ORDERED_READ_DEPEND +#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS) + return ethr_atomic_read_ddrb__(var); +#elif defined(ETHR_ORDERED_READ_DEPEND) return ethr_atomic_read(var); #else return ethr_atomic_read_rb(var); @@ -1954,7 +1974,9 @@ ethr_sint_t ethr_atomic_inc_read(ethr_atomic_t *var) ethr_sint_t ethr_atomic_inc_read_ddrb(ethr_atomic_t *var) { -#ifdef ETHR_ORDERED_READ_DEPEND +#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS) + return ethr_atomic_inc_read_ddrb__(var); +#elif defined(ETHR_ORDERED_READ_DEPEND) return ethr_atomic_inc_read(var); #else return ethr_atomic_inc_read_rb(var); @@ -2069,7 +2091,9 @@ ethr_sint_t ethr_atomic_dec_read(ethr_atomic_t *var) ethr_sint_t ethr_atomic_dec_read_ddrb(ethr_atomic_t *var) { -#ifdef ETHR_ORDERED_READ_DEPEND +#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS) + return ethr_atomic_dec_read_ddrb__(var); +#elif defined(ETHR_ORDERED_READ_DEPEND) return ethr_atomic_dec_read(var); #else return ethr_atomic_dec_read_rb(var); @@ -2183,7 +2207,9 @@ void ethr_atomic_add(ethr_atomic_t *var, ethr_sint_t val) void ethr_atomic_add_ddrb(ethr_atomic_t *var, ethr_sint_t val) { -#ifdef ETHR_ORDERED_READ_DEPEND +#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS) + ethr_atomic_add_ddrb__(var, val); +#elif defined(ETHR_ORDERED_READ_DEPEND) ethr_atomic_add(var, val); #else ethr_atomic_add_rb(var, val); @@ -2292,7 +2318,9 @@ void ethr_atomic_inc(ethr_atomic_t *var) void ethr_atomic_inc_ddrb(ethr_atomic_t *var) { -#ifdef ETHR_ORDERED_READ_DEPEND +#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS) + ethr_atomic_inc_ddrb__(var); +#elif defined(ETHR_ORDERED_READ_DEPEND) ethr_atomic_inc(var); #else ethr_atomic_inc_rb(var); @@ -2401,7 +2429,9 @@ void ethr_atomic_dec(ethr_atomic_t *var) void ethr_atomic_dec_ddrb(ethr_atomic_t *var) { -#ifdef ETHR_ORDERED_READ_DEPEND +#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS) + ethr_atomic_dec_ddrb__(var); +#elif defined(ETHR_ORDERED_READ_DEPEND) ethr_atomic_dec(var); #else ethr_atomic_dec_rb(var); @@ -2511,7 +2541,9 @@ ethr_sint_t ethr_atomic_read_band(ethr_atomic_t *var, ethr_sint_t val) ethr_sint_t ethr_atomic_read_band_ddrb(ethr_atomic_t *var, ethr_sint_t val) { -#ifdef ETHR_ORDERED_READ_DEPEND +#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS) + return ethr_atomic_read_band_ddrb__(var, val); +#elif defined(ETHR_ORDERED_READ_DEPEND) return ethr_atomic_read_band(var, val); #else return ethr_atomic_read_band_rb(var, val); @@ -2626,7 +2658,9 @@ ethr_sint_t ethr_atomic_read_bor(ethr_atomic_t *var, ethr_sint_t val) ethr_sint_t ethr_atomic_read_bor_ddrb(ethr_atomic_t *var, ethr_sint_t val) { -#ifdef ETHR_ORDERED_READ_DEPEND +#if defined(ETHR_HAVE_WORD_SZ_NATIVE_ATOMIC_OPS) + return ethr_atomic_read_bor_ddrb__(var, val); +#elif defined(ETHR_ORDERED_READ_DEPEND) return ethr_atomic_read_bor(var, val); #else return ethr_atomic_read_bor_rb(var, val); @@ -2761,7 +2795,9 @@ ethr_sint32_t ethr_atomic32_cmpxchg(ethr_atomic32_t *var, ethr_sint32_t val, eth ethr_sint32_t ethr_atomic32_cmpxchg_ddrb(ethr_atomic32_t *var, ethr_sint32_t val, ethr_sint32_t old_val) { -#ifdef ETHR_ORDERED_READ_DEPEND +#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS) + return ethr_atomic32_cmpxchg_ddrb__(var, val, old_val); +#elif defined(ETHR_ORDERED_READ_DEPEND) return ethr_atomic32_cmpxchg(var, val, old_val); #else return ethr_atomic32_cmpxchg_rb(var, val, old_val); @@ -2858,7 +2894,9 @@ ethr_sint32_t ethr_atomic32_xchg(ethr_atomic32_t *var, ethr_sint32_t val) ethr_sint32_t ethr_atomic32_xchg_ddrb(ethr_atomic32_t *var, ethr_sint32_t val) { -#ifdef ETHR_ORDERED_READ_DEPEND +#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS) + return ethr_atomic32_xchg_ddrb__(var, val); +#elif defined(ETHR_ORDERED_READ_DEPEND) return ethr_atomic32_xchg(var, val); #else return ethr_atomic32_xchg_rb(var, val); @@ -2954,7 +2992,9 @@ void ethr_atomic32_set(ethr_atomic32_t *var, ethr_sint32_t val) void ethr_atomic32_set_ddrb(ethr_atomic32_t *var, ethr_sint32_t val) { -#ifdef ETHR_ORDERED_READ_DEPEND +#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS) + ethr_atomic32_set_ddrb__(var, val); +#elif defined(ETHR_ORDERED_READ_DEPEND) ethr_atomic32_set(var, val); #else ethr_atomic32_set_rb(var, val); @@ -3044,7 +3084,9 @@ void ethr_atomic32_init(ethr_atomic32_t *var, ethr_sint32_t val) void ethr_atomic32_init_ddrb(ethr_atomic32_t *var, ethr_sint32_t val) { -#ifdef ETHR_ORDERED_READ_DEPEND +#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS) + ethr_atomic32_init_ddrb__(var, val); +#elif defined(ETHR_ORDERED_READ_DEPEND) ethr_atomic32_init(var, val); #else ethr_atomic32_init_rb(var, val); @@ -3131,7 +3173,9 @@ ethr_sint32_t ethr_atomic32_add_read(ethr_atomic32_t *var, ethr_sint32_t val) ethr_sint32_t ethr_atomic32_add_read_ddrb(ethr_atomic32_t *var, ethr_sint32_t val) { -#ifdef ETHR_ORDERED_READ_DEPEND +#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS) + return ethr_atomic32_add_read_ddrb__(var, val); +#elif defined(ETHR_ORDERED_READ_DEPEND) return ethr_atomic32_add_read(var, val); #else return ethr_atomic32_add_read_rb(var, val); @@ -3228,7 +3272,9 @@ ethr_sint32_t ethr_atomic32_read(ethr_atomic32_t *var) ethr_sint32_t ethr_atomic32_read_ddrb(ethr_atomic32_t *var) { -#ifdef ETHR_ORDERED_READ_DEPEND +#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS) + return ethr_atomic32_read_ddrb__(var); +#elif defined(ETHR_ORDERED_READ_DEPEND) return ethr_atomic32_read(var); #else return ethr_atomic32_read_rb(var); @@ -3325,7 +3371,9 @@ ethr_sint32_t ethr_atomic32_inc_read(ethr_atomic32_t *var) ethr_sint32_t ethr_atomic32_inc_read_ddrb(ethr_atomic32_t *var) { -#ifdef ETHR_ORDERED_READ_DEPEND +#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS) + return ethr_atomic32_inc_read_ddrb__(var); +#elif defined(ETHR_ORDERED_READ_DEPEND) return ethr_atomic32_inc_read(var); #else return ethr_atomic32_inc_read_rb(var); @@ -3422,7 +3470,9 @@ ethr_sint32_t ethr_atomic32_dec_read(ethr_atomic32_t *var) ethr_sint32_t ethr_atomic32_dec_read_ddrb(ethr_atomic32_t *var) { -#ifdef ETHR_ORDERED_READ_DEPEND +#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS) + return ethr_atomic32_dec_read_ddrb__(var); +#elif defined(ETHR_ORDERED_READ_DEPEND) return ethr_atomic32_dec_read(var); #else return ethr_atomic32_dec_read_rb(var); @@ -3518,7 +3568,9 @@ void ethr_atomic32_add(ethr_atomic32_t *var, ethr_sint32_t val) void ethr_atomic32_add_ddrb(ethr_atomic32_t *var, ethr_sint32_t val) { -#ifdef ETHR_ORDERED_READ_DEPEND +#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS) + ethr_atomic32_add_ddrb__(var, val); +#elif defined(ETHR_ORDERED_READ_DEPEND) ethr_atomic32_add(var, val); #else ethr_atomic32_add_rb(var, val); @@ -3609,7 +3661,9 @@ void ethr_atomic32_inc(ethr_atomic32_t *var) void ethr_atomic32_inc_ddrb(ethr_atomic32_t *var) { -#ifdef ETHR_ORDERED_READ_DEPEND +#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS) + ethr_atomic32_inc_ddrb__(var); +#elif defined(ETHR_ORDERED_READ_DEPEND) ethr_atomic32_inc(var); #else ethr_atomic32_inc_rb(var); @@ -3700,7 +3754,9 @@ void ethr_atomic32_dec(ethr_atomic32_t *var) void ethr_atomic32_dec_ddrb(ethr_atomic32_t *var) { -#ifdef ETHR_ORDERED_READ_DEPEND +#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS) + ethr_atomic32_dec_ddrb__(var); +#elif defined(ETHR_ORDERED_READ_DEPEND) ethr_atomic32_dec(var); #else ethr_atomic32_dec_rb(var); @@ -3792,7 +3848,9 @@ ethr_sint32_t ethr_atomic32_read_band(ethr_atomic32_t *var, ethr_sint32_t val) ethr_sint32_t ethr_atomic32_read_band_ddrb(ethr_atomic32_t *var, ethr_sint32_t val) { -#ifdef ETHR_ORDERED_READ_DEPEND +#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS) + return ethr_atomic32_read_band_ddrb__(var, val); +#elif defined(ETHR_ORDERED_READ_DEPEND) return ethr_atomic32_read_band(var, val); #else return ethr_atomic32_read_band_rb(var, val); @@ -3889,7 +3947,9 @@ ethr_sint32_t ethr_atomic32_read_bor(ethr_atomic32_t *var, ethr_sint32_t val) ethr_sint32_t ethr_atomic32_read_bor_ddrb(ethr_atomic32_t *var, ethr_sint32_t val) { -#ifdef ETHR_ORDERED_READ_DEPEND +#if defined(ETHR_HAVE_32BIT_NATIVE_ATOMIC_OPS) + return ethr_atomic32_read_bor_ddrb__(var, val); +#elif defined(ETHR_ORDERED_READ_DEPEND) return ethr_atomic32_read_bor(var, val); #else return ethr_atomic32_read_bor_rb(var, val); diff --git a/erts/lib_src/utils/make_atomics_api b/erts/lib_src/utils/make_atomics_api index d8b1a56100..74736c5a2d 100755 --- a/erts/lib_src/utils/make_atomics_api +++ b/erts/lib_src/utils/make_atomics_api @@ -805,17 +805,40 @@ rtchk_fallback_call(Return, #atomic_context{dw = DW, non_native_barrier(B) -> lists:member(B, ?NON_NATIVE_BARRIERS). -non_native_barrier_impl(AC, Type, Macro, Op, B) -> +non_native_barrier_impl(AC, inline_implementation = Type, Op, B) -> [" -", func_header(AC, Type, Macro, Op, B), " +", func_header(AC, Type, false, Op, B), " {", case B of ddrb -> [" #ifdef ETHR_ORDERED_READ_DEPEND - ", func_call(AC, Type, Macro, Op, none, true), " + ", func_call(AC, Type, Op, none, true), " #else - ", func_call(AC, Type, Macro, Op, rb, true), " + ", func_call(AC, Type, Op, rb, true), " +#endif +" + ] + end, + "} +" + ]; +non_native_barrier_impl(#atomic_context{have_native_atomic_ops = HaveNative} = AC, + implementation = Type, + Op, + B) -> + [" +", func_header(AC, Type, false, Op, B), " +{", + case B of + ddrb -> + [" +#if defined(", HaveNative, ") + ", func_call(AC, Type, Op, B, true), " +#elif defined(ETHR_ORDERED_READ_DEPEND) + ", func_call(AC, symbol_implementation, Op, none, true), " +#else + ", func_call(AC, symbol_implementation, Op, rb, true), " #endif " ] @@ -824,12 +847,12 @@ non_native_barrier_impl(AC, Type, Macro, Op, B) -> " ]. -func_call(#atomic_context{'ATMC' = ATMC} = AC, inline_implementation, _Macro, Op, B, RetStatement) -> +func_call(#atomic_context{'ATMC' = ATMC} = AC, inline_implementation, Op, B, RetStatement) -> func_call(AC, Op, ["ETHR_", ATMC, "_FUNC__(", opstr(Op), op_barrier_ext(B), ")"], RetStatement); -func_call(#atomic_context{atomic = Atomic} = AC, implementation, false, Op, B, RetStatement) -> - func_call(AC, Op, [Atomic, "_", opstr(Op), op_barrier_ext(B)], RetStatement); -func_call(AC, implementation, Macro, Op, B, RetStatement) -> - func_call(AC, Op, [Macro, "(", opstr(Op), op_barrier_ext(B), ")"], RetStatement). +func_call(#atomic_context{atomic = Atomic} = AC, implementation, Op, B, RetStatement) -> + func_call(AC, Op, [Atomic, "_", opstr(Op), op_barrier_ext(B), "__"], RetStatement); +func_call(#atomic_context{atomic = Atomic} = AC, symbol_implementation, Op, B, RetStatement) -> + func_call(AC, Op, [Atomic, "_", opstr(Op), op_barrier_ext(B)], RetStatement). func_call(#atomic_context{dw = DW, arg1 = Arg1, arg2 = Arg2, arg3 = Arg3} = AC, Op, Func, true) -> op_call(Op, DW, case is_return_op(AC, Op) of @@ -901,7 +924,7 @@ make_implementations(#atomic_context{dw = DW, lists:map(fun (B) -> case non_native_barrier(B) of true -> - non_native_barrier_impl(AC, inline_implementation, false, Op, B); + non_native_barrier_impl(AC, inline_implementation, Op, B); false -> TryBarriers = try_barrier_order(B), [" @@ -1211,7 +1234,7 @@ int ethr_have_native_dw_atomic(void) end, case non_native_barrier(B) of true -> - non_native_barrier_impl(AC, implementation, Macro, Op, B); + non_native_barrier_impl(AC, implementation, Op, B); false -> ["\n", func_header(AC, implementation, Macro, Op, B), diff --git a/erts/preloaded/ebin/prim_inet.beam b/erts/preloaded/ebin/prim_inet.beam Binary files differindex f382236af7..b2f3ab6c5b 100644 --- a/erts/preloaded/ebin/prim_inet.beam +++ b/erts/preloaded/ebin/prim_inet.beam diff --git a/erts/preloaded/ebin/zlib.beam b/erts/preloaded/ebin/zlib.beam Binary files differindex bf88a51502..7a1f896d36 100644 --- a/erts/preloaded/ebin/zlib.beam +++ b/erts/preloaded/ebin/zlib.beam diff --git a/erts/preloaded/src/prim_inet.erl b/erts/preloaded/src/prim_inet.erl index 0cedd284db..14bf3b6c69 100644 --- a/erts/preloaded/src/prim_inet.erl +++ b/erts/preloaded/src/prim_inet.erl @@ -83,8 +83,10 @@ open(Protocol, Family, Type, Req, Data) -> end catch %% The only (?) way to get here is to try to open - %% the sctp driver when it does not exist - error:badarg -> {error,eprotonosupport} + %% the sctp driver when it does not exist (badarg) + error:badarg -> {error, eprotonosupport}; + %% system_limit if out of port slots + error:system_limit -> {error, system_limit} end. enc_family(inet) -> ?INET_AF_INET; diff --git a/erts/preloaded/src/zlib.erl b/erts/preloaded/src/zlib.erl index 210532edac..71b730016d 100644 --- a/erts/preloaded/src/zlib.erl +++ b/erts/preloaded/src/zlib.erl @@ -349,10 +349,14 @@ getQSize(Z) -> Compressed :: binary(). compress(Data) -> Z = open(), - deflateInit(Z, default), - Bs = deflate(Z, Data, finish), - deflateEnd(Z), - close(Z), + Bs = try + deflateInit(Z, default), + B = deflate(Z, Data, finish), + deflateEnd(Z), + B + after + close(Z) + end, iolist_to_binary(Bs). -spec uncompress(Data) -> Decompressed when @@ -364,10 +368,14 @@ uncompress(Data) -> if Size >= 8 -> Z = open(), - inflateInit(Z), - Bs = inflate(Z, Data), - inflateEnd(Z), - close(Z), + Bs = try + inflateInit(Z), + B = inflate(Z, Data), + inflateEnd(Z), + B + after + close(Z) + end, iolist_to_binary(Bs); true -> erlang:error(data_error) @@ -383,10 +391,14 @@ uncompress(Data) -> Compressed :: binary(). zip(Data) -> Z = open(), - deflateInit(Z, default, deflated, -?MAX_WBITS, 8, default), - Bs = deflate(Z, Data, finish), - deflateEnd(Z), - close(Z), + Bs = try + deflateInit(Z, default, deflated, -?MAX_WBITS, 8, default), + B = deflate(Z, Data, finish), + deflateEnd(Z), + B + after + close(Z) + end, iolist_to_binary(Bs). -spec unzip(Data) -> Decompressed when @@ -394,10 +406,14 @@ zip(Data) -> Decompressed :: binary(). unzip(Data) -> Z = open(), - inflateInit(Z, -?MAX_WBITS), - Bs = inflate(Z, Data), - inflateEnd(Z), - close(Z), + Bs = try + inflateInit(Z, -?MAX_WBITS), + B = inflate(Z, Data), + inflateEnd(Z), + B + after + close(Z) + end, iolist_to_binary(Bs). -spec gzip(Data) -> Compressed when @@ -405,10 +421,14 @@ unzip(Data) -> Compressed :: binary(). gzip(Data) -> Z = open(), - deflateInit(Z, default, deflated, 16+?MAX_WBITS, 8, default), - Bs = deflate(Z, Data, finish), - deflateEnd(Z), - close(Z), + Bs = try + deflateInit(Z, default, deflated, 16+?MAX_WBITS, 8, default), + B = deflate(Z, Data, finish), + deflateEnd(Z), + B + after + close(Z) + end, iolist_to_binary(Bs). -spec gunzip(Data) -> Decompressed when @@ -416,10 +436,14 @@ gzip(Data) -> Decompressed :: binary(). gunzip(Data) -> Z = open(), - inflateInit(Z, 16+?MAX_WBITS), - Bs = inflate(Z, Data), - inflateEnd(Z), - close(Z), + Bs = try + inflateInit(Z, 16+?MAX_WBITS), + B = inflate(Z, Data), + inflateEnd(Z), + B + after + close(Z) + end, iolist_to_binary(Bs). -spec collect(zstream()) -> iolist(). diff --git a/erts/test/otp_SUITE.erl b/erts/test/otp_SUITE.erl index 79cd91221f..b34d9a5422 100644 --- a/erts/test/otp_SUITE.erl +++ b/erts/test/otp_SUITE.erl @@ -151,6 +151,9 @@ ssl_crypto_filter(Undef) -> {{error,bad_name},{error,bad_name}} -> filter(fun({_,{ssl,_,_}}) -> false; ({_,{crypto,_,_}}) -> false; + ({_,{ssh,_,_}}) -> false; + ({_,{ssh_connection,_,_}}) -> false; + ({_,{ssh_sftp,_,_}}) -> false; (_) -> true end, Undef); {_,_} -> Undef diff --git a/lib/asn1/c_src/asn1_erl_nif.c b/lib/asn1/c_src/asn1_erl_nif.c index accd368af1..dbff14f9b3 100644 --- a/lib/asn1/c_src/asn1_erl_nif.c +++ b/lib/asn1/c_src/asn1_erl_nif.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2002-2011. All Rights Reserved. + * Copyright Ericsson AB 2002-2012. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in @@ -1197,7 +1197,7 @@ static ERL_NIF_TERM encode_per_complete(ErlNifEnv* env, int argc, ErlNifBinary out_binary; int complete_len; if (!enif_inspect_iolist_as_binary(env, argv[0], &in_binary)) - return enif_make_atom(env, "badarg"); + return enif_make_badarg(env); if (!enif_alloc_binary(in_binary.size, &out_binary)) return enif_make_atom(env, "alloc_binary_failed"); diff --git a/lib/asn1/doc/src/asn1ct.xml b/lib/asn1/doc/src/asn1ct.xml index 0b9ec3df7f..3be58cbc8e 100644 --- a/lib/asn1/doc/src/asn1ct.xml +++ b/lib/asn1/doc/src/asn1ct.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1997</year><year>2011</year> + <year>1997</year><year>2012</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -44,15 +44,15 @@ </description> <funcs> <func> - <name>compile(Asn1module) -> ok | {error,Reason}</name> - <name>compile(Asn1module , Options) -> ok | {error,Reason}</name> + <name>compile(Asn1module) -> ok | {error, Reason}</name> + <name>compile(Asn1module, Options) -> ok | {error, Reason}</name> <fsummary>Compile an ASN.1 module and generate encode/decode functions according to the encoding rules BER or PER.</fsummary> <type> <v>Asn1module = atom() | string()</v> <v>Options = [Option| OldOption]</v> - <v>Option = ber_bin | per_bin | uper_bin | der | compact_bit_string | - noobj | {n2n,EnumTypeName} |{outdir,Dir} | {i,IncludeDir} | optimize | - nif | asn1config | undec_rest | {inline,OutputName} | inline | + <v>Option = ber_bin | per_bin | uper_bin | der | compact_bit_string | + noobj | {n2n, EnumTypeName} |{outdir, Dir} | {i, IncludeDir} | optimize | + nif | asn1config | undec_rest | {inline, OutputName} | inline | {macro_name_prefix, Prefix} | {record_name_prefix, Prefix} | verbose | warnings_as_errors</v> <v>OldOption = ber | per</v> <v>Reason = term()</v> @@ -158,7 +158,7 @@ File3.asn </pre> of the BIT STRING type in Erlang. The notation: </p> <pre> -BitString = {Unused,Binary}, +BitString = {Unused, Binary}, Unused = integer(), Binary = binary() </pre> @@ -172,7 +172,7 @@ Binary = binary() </seealso>. </p> </item> - <tag><c>{n2n,EnumTypeName}</c></tag> + <tag><c>{n2n, EnumTypeName}</c></tag> <item> <p> Tells the compiler to generate functions for conversion between @@ -190,17 +190,17 @@ Binary = binary() <c>.erl</c> file. If this option is omitted the generated Erlang module will be compiled.</p> </item> - <tag><c>{i,IncludeDir}</c></tag> + <tag><c>{i, IncludeDir}</c></tag> <item> <p>Adds <c>IncludeDir</c> to the search-path for <c>.asn1db</c> and asn1 source files. The compiler tries to open a <c>.asn1db</c> file when a module imports definitions from another ASN.1 module. If no <c>.asn1db</c> file is found the asn1 source file is - parsed. Several <c>{i,IncludeDir}</c> can be given. + parsed. Several <c>{i, IncludeDir}</c> can be given. </p> </item> - <tag><c>{outdir,Dir}</c></tag> + <tag><c>{outdir, Dir}</c></tag> <item> <p>Specifies the directory <c>Dir</c> where all generated files shall be placed. If omitted the files are placed in the @@ -251,11 +251,11 @@ Binary = binary() also have some following bytes. Now it is possible to get those following bytes returned together with the decoded value. If an asn1 spec is compiled with this option a tuple - <c>{ok,Value,Rest}</c> is returned. <c>Rest</c> may be a + <c>{ok, Value, Rest}</c> is returned. <c>Rest</c> may be a list or a binary. Earlier versions of the compiler ignored those following bytes.</p> </item> - <tag><c>{inline,OutputName}</c></tag> + <tag><c>{inline, OutputName}</c></tag> <item> <p>Compiling with this option gives one output module containing all asn1 run-time functionality. The asn1 specs @@ -267,7 +267,7 @@ Binary = binary() by the <c>igor</c> module of <c>syntax_tools</c>. By default the functions generated from the first asn1 spec in the <c>.set.asn</c> are exported, unless a - <c>{export,[atom()]}</c> or <c>{export_all,true}</c> option + <c>{export, [atom()]}</c> or <c>{export_all, true}</c> option are provided. The list of atoms are names of chosen asn1 specs from the <c>.set.asn</c> file. </p> <p>When used together with <c>nif</c> for <c>ber_bin</c>, the @@ -278,7 +278,7 @@ Binary = binary() <tag><c>inline</c></tag> <item> <p>It is also possible to use the sole argument <c>inline</c>. - It is as <c>{inline,OutputName}</c>, but the output file gets the + It is as <c>{inline, OutputName}</c>, but the output file gets the default name of the source <c>.set.asn</c> file.</p> </item> <tag><c>{macro_name_prefix, Prefix}</c></tag> @@ -322,7 +322,7 @@ Binary = binary() </desc> </func> <func> - <name>encode(Module,Type,Value)-> {ok,Bytes} | {error,Reason}</name> + <name>encode(Module, Type, Value)-> {ok, Bytes} | {error, Reason}</name> <fsummary>Encode an ASN.1 value.</fsummary> <type> <v>Module = Type = atom()</v> @@ -337,13 +337,13 @@ Binary = binary() encode function only performs rudimentary tests that the input <c>Value</c> is a correct instance of <c>Type</c>. The length of strings is for example - not always checked. Returns <c>{ok,Bytes}</c> if successful or - <c>{error,Reason}</c> if an error occurred. + not always checked. Returns <c>{ok, Bytes}</c> if successful or + <c>{error, Reason}</c> if an error occurred. </p> </desc> </func> <func> - <name>decode(Module,Type,Bytes) -> {ok,Value}|{error,Reason}</name> + <name>decode(Module, Type, Bytes) -> {ok, Value} | {error, Reason}</name> <fsummary>Decode from Bytes into an ASN.1 value.</fsummary> <type> <v>Module = Type = atom()</v> @@ -352,11 +352,11 @@ Binary = binary() </type> <desc> <p>Decodes <c>Type</c> from <c>Module</c> from the list of bytes - <c>Bytes</c>. Returns <c>{ok,Value}</c> if successful.</p> + <c>Bytes</c>. Returns <c>{ok, Value}</c> if successful.</p> </desc> </func> <func> - <name>value(Module ,Type) -> {ok,Value} | {error,Reason}</name> + <name>value(Module, Type) -> {ok, Value} | {error, Reason}</name> <fsummary>Create an ASN.1 value for test purposes.</fsummary> <type> <v>Module = Type = atom()</v> @@ -371,26 +371,48 @@ Binary = binary() </desc> </func> <func> - <name>test(Module) -> ok | {error,Reason}</name> - <name>test(Module,Type) -> ok | {error,Reason}</name> - <name>test(Module,Type,Value) -> ok | {error,Reason}</name> - <fsummary>Perform a test of encode and decode for types in an ASN.1 module.</fsummary> + <name>test(Module) -> ok | {error, Reason}</name> + <name>test(Module, Type | Options) -> ok | {error, Reason}</name> + <name>test(Module, Type, Value | Options) -> ok | {error, Reason}</name> + <fsummary>Perform a test of encode and decode for types in an ASN.1 module.</fsummary> + <type> + <v>Module = Type = atom()</v> + <v>Value = term()</v> + <v>Options = [{i, IncludeDir}]</v> + <v>Reason = term()</v> + </type> <desc> - <p>Performs a test of encode and decode of all types in <c>Module</c>. + <p>Performs a test of encode and decode of types in <c>Module</c>. The generated functions are called by this function. This function is useful during test to secure that the generated - encode and decode functions and the general runtime support work - as expected. <br></br> -<c>test/1</c> iterates over all types in <c>Module</c>. <br></br> -<c>test/2</c> tests type <c>Type</c> with a random value. <br></br> -<c><![CDATA[test/3 tests type <c>Type]]></c> with <c>Value</c>. <br></br> + encode and decode functions and the general runtime support work + as expected.</p> + + <list type="bulleted"> + <item> + <p><c>test/1</c> iterates over all types in <c>Module</c>.</p> + </item> + <item> + <p><c>test/2</c> tests type <c>Type</c> with a random value.</p> + </item> + <item> + <p><c>test/3</c> tests type <c>Type</c> with <c>Value</c>.</p> + </item> + </list> - Schematically the following happens for each type in the module.</p> - <p></p> + <p>Schematically the following happens for each type in the module: <code type="none"> -{ok,Value} = asn1ct:value(Module,Type), -{ok,Bytes} = asn1ct:encode(Module,Type,Value), -{ok,Value} = asn1ct:decode(Module,Type,Bytes). </code> +{ok, Value} = asn1ct:value(Module, Type), +{ok, Bytes} = asn1ct:encode(Module, Type, Value), +{ok, Value} = asn1ct:decode(Module, Type, Bytes).</code></p> + + <p>The <c>test</c> functions utilizes the <c>*.asn1db</c> files + for all included modules. If they are located in a different + directory than the current working directory, use the include + option to add paths. This is only needed when automatically + generating values. For static values using <c>Value</c> no + options are needed.</p> + </desc> </func> </funcs> diff --git a/lib/asn1/src/Makefile b/lib/asn1/src/Makefile index 3a59773d93..5614cbea91 100644 --- a/lib/asn1/src/Makefile +++ b/lib/asn1/src/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 1997-2011. All Rights Reserved. +# Copyright Ericsson AB 1997-2012. All Rights Reserved. # # The contents of this file are subject to the Erlang Public License, # Version 1.1, (the "License"); you may not use this file except in @@ -58,7 +58,8 @@ CT_MODULES= \ asn1ct_gen_ber_bin_v2 \ asn1ct_value \ asn1ct_tok \ - asn1ct_parser2 + asn1ct_parser2 \ + asn1ct_table RT_MODULES= \ asn1rt \ diff --git a/lib/asn1/src/asn1_db.erl b/lib/asn1/src/asn1_db.erl index f680b3d064..0862ef6e02 100644 --- a/lib/asn1/src/asn1_db.erl +++ b/lib/asn1/src/asn1_db.erl @@ -1,167 +1,146 @@ %% %% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1997-2009. All Rights Reserved. -%% +%% +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. +%% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. -%% +%% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. -%% +%% %% %CopyrightEnd% %% %% -module(asn1_db). -%-compile(export_all). --export([dbnew/1,dbsave/2,dbload/1,dbput/3,dbget/2,dbget_all/1]). --export([dbget_all_mod/1,dbstop/0,dbclear/0,dberase_module/1,dbstart/1,stop_server/1]). -%% internal exports --export([dbloop0/1,dbloop/2]). -%% Db stuff -dbstart(Includes) -> - start_server(asn1db, asn1_db, dbloop0, [Includes]). +-export([dbstart/1,dbnew/1,dbsave/2,dbload/1,dbput/3,dbget/2,dbget_all/1]). +-export([dbget_all_mod/1,dbclear/0,dberase_module/1,dbstop/0]). -dbloop0(Includes) -> - dbloop(Includes, ets:new(asn1, [set,named_table])). - -opentab(Tab,Mod,[]) -> - opentab(Tab,Mod,["."]); -opentab(Tab,Mod,Includes) -> - Base = lists:concat([Mod,".asn1db"]), - opentab2(Tab,Base,Mod,Includes,ok). +-record(state, {parent, monitor, includes, table}). -opentab2(_Tab,_Base,_Mod,[],Error) -> - Error; -opentab2(Tab,Base,Mod,[Ih|It],_Error) -> - File = filename:join(Ih,Base), - case ets:file2tab(File) of - {ok,Modtab} -> - ets:insert(Tab,{Mod, Modtab}), - {ok,Modtab}; - NewErr -> - opentab2(Tab,Base,Mod,It,NewErr) +%% Interface +dbstart(Includes) -> + Parent = self(), + case get(?MODULE) of + undefined -> + put(?MODULE, spawn_link(fun() -> init(Parent, Includes) end)), + true; + _Pid -> + req({new_includes, Includes}) end. - -dbloop(Includes, Tab) -> +dbnew(Module) -> req({new, Module}). +dbsave(OutFile, Module) -> req({save, OutFile, Module}). +dbload(Module) -> req({load, Module}). +dbput(Module, K, V) -> req({set, Module, K, V}). +dbget(Module, K) -> req({get, Module, K}). +dbget_all(K) -> req({get_all, K}). +dbget_all_mod(Mod) -> req({all_mod, Mod}). +dbclear() -> req(clear). +dberase_module({module,M}) -> req({delete_mod, M}). +dbstop() -> Resp = req(stop), erase(?MODULE), Resp. + +%% Internal functions +req(Request) -> + get(?MODULE) ! {self(), Request}, + receive {?MODULE, Reply} -> Reply after 5000 -> exit(db_timeout) end. + +reply(From, Response) -> + From ! {?MODULE, Response}. + +init(Parent, Includes) -> + MRef = erlang:monitor(process, Parent), + loop(#state{parent = Parent, monitor = MRef, includes = Includes, + table = ets:new(?MODULE, [])}). + +loop(#state{parent = Parent, monitor = MRef, table = Table, + includes = Includes} = State) -> receive - {From,{set, Mod, K2, V}} -> - [{_,Modtab}] = ets:lookup(Tab,Mod), - ets:insert(Modtab,{K2, V}), - From ! {asn1db, ok}, - dbloop(Includes, Tab); - {From, {get, Mod, K2}} -> - Result = case ets:lookup(Tab,Mod) of - [] -> - opentab(Tab,Mod,Includes); - [{_,Modtab}] -> {ok,Modtab} - end, - case Result of - {ok,Newtab} -> - From ! {asn1db, lookup(Newtab, K2)}; - _Error -> - From ! {asn1db, undefined} - end, - dbloop(Includes, Tab); - {From, {all_mod, Mod}} -> - [{_,Modtab}] = ets:lookup(Tab,Mod), - From ! {asn1db, ets:tab2list(Modtab)}, - dbloop(Includes, Tab); - {From, {delete_mod, Mod}} -> - [{_,Modtab}] = ets:lookup(Tab,Mod), - ets:delete(Modtab), - ets:delete(Tab,Mod), - From ! {asn1db, ok}, - dbloop(Includes, Tab); - {From, {save, OutFile,Mod}} -> - [{_,Mtab}] = ets:lookup(Tab,Mod), - From ! {asn1db, ets:tab2file(Mtab,OutFile)}, - dbloop(Includes,Tab); - {From, {load, Mod}} -> - Result = case ets:lookup(Tab,Mod) of - [] -> - opentab(Tab,Mod,Includes); - [{_,Modtab}] -> {ok,Modtab} - end, - From ! {asn1db,Result}, - dbloop(Includes,Tab); - {From, {new, Mod}} -> - case ets:lookup(Tab,Mod) of - [{_,Modtab}] -> - ets:delete(Modtab); - _ -> - true - end, - Tabname = list_to_atom(lists:concat(["asn1_",Mod])), - ets:new(Tabname, [set,named_table]), - ets:insert(Tab,{Mod,Tabname}), - From ! {asn1db, ok}, - dbloop(Includes,Tab); - {From, stop} -> - From ! {asn1db, ok}; %% nothing to store - {From, clear} -> - ModTabList = [Mt||{_,Mt} <- ets:tab2list(Tab)], - lists:foreach(fun(T) -> ets:delete(T) end,ModTabList), - ets:delete(Tab), - From ! {asn1db, cleared}, - dbloop(Includes, ets:new(asn1, [set])); - {From,{new_includes,[NewIncludes]}} -> - From ! {asn1db,done}, - dbloop(NewIncludes,Tab) + {From, {set, Mod, K2, V}} -> + [{_, Modtab}] = ets:lookup(Table, Mod), + ets:insert(Modtab, {K2, V}), + reply(From, ok), + loop(State); + {From, {get, Mod, K2}} -> + Result = case ets:lookup(Table, Mod) of + [] -> opentab(Table, Mod, Includes); + [{_, Modtab}] -> {ok, Modtab} + end, + case Result of + {ok, Newtab} -> reply(From, lookup(Newtab, K2)); + _Error -> reply(From, undefined) + end, + loop(State); + {From, {all_mod, Mod}} -> + [{_, Modtab}] = ets:lookup(Table, Mod), + reply(From, ets:tab2list(Modtab)), + loop(State); + {From, {delete_mod, Mod}} -> + [{_, Modtab}] = ets:lookup(Table, Mod), + ets:delete(Modtab), + ets:delete(Table, Mod), + reply(From, ok), + loop(State); + {From, {save, OutFile, Mod}} -> + [{_,Mtab}] = ets:lookup(Table, Mod), + reply(From, ets:tab2file(Mtab, OutFile)), + loop(State); + {From, {load, Mod}} -> + Result = case ets:lookup(Table, Mod) of + [] -> opentab(Table, Mod, Includes); + [{_, Modtab}] -> {ok, Modtab} + end, + reply(From, Result), + loop(State); + {From, {new, Mod}} -> + case ets:lookup(Table, Mod) of + [{_, Modtab}] -> ets:delete(Modtab); + _ -> true + end, + ModTableId = ets:new(list_to_atom(lists:concat(["asn1_",Mod])), []), + ets:insert(Table, {Mod, ModTableId}), + reply(From, ok), + loop(State); + {From, clear} -> + [ets:delete(Mt) || {_, Mt} <- ets:tab2list(Table)], + ets:delete(Table), + reply(From, cleared), + loop(State#state{table = ets:new(asn1, [set])}); + {From, {new_includes, NewIncludes}} -> + reply(From, true), + loop(State#state{includes = NewIncludes}); + {From, stop} -> + reply(From, stopped); %% Nothing to store + {'DOWN', MRef, process, Parent, Reason} -> + exit(Reason) end. +opentab(Tab, Mod, []) -> + opentab(Tab, Mod, ["."]); +opentab(Tab, Mod, Includes) -> + Base = lists:concat([Mod, ".asn1db"]), + opentab2(Tab, Base, Mod, Includes, ok). -%%all(Tab, K) -> -%% pickup(K, ets:match(Tab, {{K, '$1'}, '$2'})). -%%pickup(K, []) -> []; -%%pickup(K, [[V1,V2] |T]) -> -%% [{{K,V1},V2} | pickup(K, T)]. +opentab2(_Tab, _Base, _Mod, [], Error) -> + Error; +opentab2(Tab, Base, Mod, [Ih|It], _Error) -> + File = filename:join(Ih, Base), + case ets:file2tab(File) of + {ok, Modtab} -> + ets:insert(Tab, {Mod, Modtab}), + {ok, Modtab}; + NewErr -> + opentab2(Tab, Base, Mod, It, NewErr) + end. lookup(Tab, K) -> case ets:lookup(Tab, K) of - [] -> undefined; - [{K,V}] -> V + [] -> undefined; + [{K,V}] -> V end. - - -dbnew(Module) -> req({new,Module}). -dbsave(OutFile,Module) -> req({save,OutFile,Module}). -dbload(Module) -> req({load,Module}). - -dbput(Module,K,V) -> req({set, Module, K, V}). -dbget(Module,K) -> req({get, Module, K}). -dbget_all(K) -> req({get_all, K}). -dbget_all_mod(Mod) -> req({all_mod,Mod}). -dbstop() -> stop_server(asn1db). -dbclear() -> req(clear). -dberase_module({module,M})-> - req({delete_mod, M}). - -req(R) -> - asn1db ! {self(), R}, - receive {asn1db, Reply} -> Reply end. - -stop_server(Name) -> - stop_server(Name, whereis(Name)). -stop_server(_, undefined) -> stopped; -stop_server(Name, _Pid) -> - Name ! {self(), stop}, - receive {Name, _} -> stopped end. - - -start_server(Name,Mod,Fun,Args) -> - case whereis(Name) of - undefined -> - register(Name, spawn(Mod,Fun, Args)); - _Pid -> - req({new_includes,Args}) - end. - - diff --git a/lib/asn1/src/asn1ct.erl b/lib/asn1/src/asn1ct.erl index 85bb5b2f28..2d17f73a2c 100644 --- a/lib/asn1/src/asn1ct.erl +++ b/lib/asn1/src/asn1ct.erl @@ -1,7 +1,8 @@ +%% vim: tabstop=8:shiftwidth=4 %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2011. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -24,13 +25,13 @@ %%-compile(export_all). %% Public exports -export([compile/1, compile/2]). --export([start/0, start/1, stop/0]). +-export([start/0, start/1]). -export([encode/2, encode/3, decode/3]). --export([test/1, test/2, test/3, value/2]). +-export([test/1, test/2, test/3, value/2, value/3]). %% Application internal exports -export([compile_asn/3,compile_asn1/3,compile_py/3,compile/3, - value/1,vsn/0, - create_ets_table/2,get_name_of_def/1,get_pos_of_def/1]). + vsn/0, + get_name_of_def/1,get_pos_of_def/1]). -export([read_config_data/1,get_gen_state_field/1,get_gen_state/0, partial_inc_dec_toptype/1,save_gen_state/1,update_gen_state/2, get_tobe_refed_func/1,reset_gen_state/0,is_function_generated/1, @@ -93,25 +94,24 @@ compile(File,Options) when is_list(Options) -> end, Options1 = optimize_ber_bin(Options), Options2 = includes(File,Options1), - Includes=[I||{i,I}<-Options2], - case (catch input_file_type(File,Includes)) of - {single_file,SuffixedFile} -> %% "e.g. "/tmp/File.asn" - (catch compile1(SuffixedFile,Options2)); - {multiple_files_file,SetBase,FileName} -> - FileList = get_file_list(FileName,Includes), -%% io:format("FileList: ~p~n",[FileList]), - case FileList of - L when is_list(L) -> - (catch compile_set(SetBase,FileList,Options2)); - Err -> - Err - end; - Err = {input_file_error,_Reason} -> - {error,Err}; - Err2 -> Err2 + Includes = strip_includes(Options2), + in_process(fun() -> compile_proc(File, Includes, Options2) end). + +compile_proc(File, Includes, Options) -> + case input_file_type(File, Includes) of + {single_file, SuffixedFile} -> %% "e.g. "/tmp/File.asn" + compile1(SuffixedFile, Options); + {multiple_files_file, SetBase, FileName} -> + case get_file_list(FileName, Includes) of + FileList when is_list(FileList) -> + compile_set(SetBase, FileList, Options); + Err -> + Err + end; + Err = {input_file_error, _Reason} -> + {error, Err} end. - compile1(File,Options) when is_list(Options) -> verbose("Erlang ASN.1 version ~p compiling ~p ~n",[?vsn,File],Options), verbose("Compiler Options: ~p~n",[Options],Options), @@ -121,13 +121,13 @@ compile1(File,Options) when is_list(Options) -> DbFile = outfile(Base,"asn1db",Options), Includes = [I || {i,I} <- Options], EncodingRule = get_rule(Options), - create_ets_table(asn1_functab,[named_table]), + asn1ct_table:new(asn1_functab), Continue1 = scan(File,Options), Continue2 = parse(Continue1,File,Options), Continue3 = check(Continue2,File,OutFile,Includes,EncodingRule, DbFile,Options,[]), Continue4 = generate(Continue3,OutFile,EncodingRule,Options), - delete_tables([asn1_functab]), + asn1ct_table:delete(asn1_functab), Ret = compile_erl(Continue4,OutFile,Options), case inline(is_inline(Options), inline_output(Options,filename:rootname(File)), @@ -189,7 +189,7 @@ compile_set(SetBase,Files,Options) DbFile = outfile(SetBase,"asn1db",Options), Includes = [I || {i,I} <- Options], EncodingRule = get_rule(Options), - create_ets_table(asn1_functab,[named_table]), + asn1ct_table:new(asn1_functab), ScanRes = scan_set(Files,Options), ParseRes = parse_set(ScanRes,Options), Result = @@ -214,7 +214,7 @@ compile_set(SetBase,Files,Options) {error,{'unexpected error in scan/parse phase', lists:map(fun(X)->element(3,X) end,Other)}} end, - delete_tables([asn1_functab]), + asn1ct_table:delete(asn1_functab), Result. check_set(ParseRes,SetBase,OutFile,Includes,EncRule,DbFile, @@ -226,7 +226,7 @@ check_set(ParseRes,SetBase,OutFile,Includes,EncRule,DbFile, Options,InputModules), Continue2 = generate(Continue1,OutFile,EncRule,Options), - delete_tables([renamed_defs,original_imports,automatic_tags]), + asn1ct_table:delete([renamed_defs, original_imports, automatic_tags]), Ret = compile_erl(Continue2,OutFile,Options), case inline(is_inline(Options), @@ -247,12 +247,11 @@ check_set(ParseRes,SetBase,OutFile,Includes,EncRule,DbFile, merge_modules(ParseRes,CommonName) -> ModuleList = lists:map(fun(X)->element(2,X) end,ParseRes), NewModuleList = remove_name_collisions(ModuleList), - case ets:info(renamed_defs,size) of - 0 -> ets:delete(renamed_defs); - _ -> ok + case asn1ct_table:size(renamed_defs) of + 0 -> asn1ct_table:delete(renamed_defs); + _ -> ok end, save_imports(NewModuleList), -% io:format("~p~n~p~n~p~n~n",[ets:lookup(original_imports,'M1'),ets:lookup(original_imports,'M2'),ets:tab2list(original_imports)]), TypeOrVal = lists:append(lists:map(fun(X)->X#module.typeorval end, NewModuleList)), InputMNameList = lists:map(fun(X)->X#module.name end, @@ -272,7 +271,7 @@ merge_modules(ParseRes,CommonName) -> %% causes an exit if duplicate definition names exist in a module remove_name_collisions(Modules) -> - create_ets_table(renamed_defs,[named_table]), + asn1ct_table:new(renamed_defs), %% Name duplicates in the same module is not allowed. lists:foreach(fun exit_if_nameduplicate/1,Modules), %% Then remove duplicates in different modules and return the @@ -304,7 +303,8 @@ remove_name_collisions2(ModName,[T|Ts],Ms,Acc) -> %% rename T NewT = set_name_of_def(ModName,Name,T), %rename def warn_renamed_def(ModName,get_name_of_def(NewT),Name), - ets:insert(renamed_defs,{get_name_of_def(NewT),Name,ModName}), + asn1ct_table:insert(renamed_defs, + {get_name_of_def(NewT), Name, ModName}), remove_name_collisions2(ModName,Ts,NewMs,[NewT|Acc]); {NewMs,?dupl_equaldefs} -> % name duplicates, but identical defs %% keep name of T @@ -328,8 +328,8 @@ discover_dupl_in_mods(Name,Def,[M=#module{name=N,typeorval=TorV}|Ms], %% rename def NewT=set_name_of_def(N,Name,T), warn_renamed_def(N,get_name_of_def(NewT),Name), - ets:insert(renamed_defs,{get_name_of_def(NewT), - Name,N}), + asn1ct_table:insert(renamed_defs, + {get_name_of_def(NewT), Name, N}), {NewT,?dupl_uniquedefs bor RenamedOrDupl}; {Name,equal} -> %% delete def @@ -484,8 +484,9 @@ save_imports(ModuleList)-> [] -> ok; ImportsList2 -> - create_ets_table(original_imports,[named_table]), - lists:foreach(fun(X) -> ets:insert(original_imports,X) end,ImportsList2) + asn1ct_table:new(original_imports), + lists:foreach(fun(X) -> asn1ct_table:insert(original_imports, X) end, + ImportsList2) end. @@ -561,7 +562,7 @@ check_tagdefault(ModList) -> case have_same_tagdefault(ModList) of {true,TagDefault} -> TagDefault; {false,TagDefault} -> - create_ets_table(automatic_tags,[named_table]), + asn1ct_table:new(automatic_tags), save_automatic_tagged_types(ModList), TagDefault end. @@ -588,7 +589,7 @@ save_automatic_tagged_types([#module{tagdefault='AUTOMATIC', typeorval=TorV}|Ms]) -> Fun = fun(T) -> - ets:insert(automatic_tags,{get_name_of_def(T)}) + asn1ct_table:insert(automatic_tags, {get_name_of_def(T)}) end, lists:foreach(Fun,TorV), save_automatic_tagged_types(Ms); @@ -827,22 +828,14 @@ generate({true,{M,_Module,GenTOrV}},OutFile,EncodingRule,Options) -> _ -> ok end, put(encoding_options,Options), - create_ets_table(check_functions,[named_table]), + asn1ct_table:new(check_functions), %% create decoding function names and taglists for partial decode - %% For the time being leave errors unnoticed !!!!!!!!! -% io:format("Options: ~p~n",[Options]), - case catch specialized_decode_prepare(EncodingRule,M,GenTOrV,Options) of - {error, enoent} -> ok; - {error, Reason} -> warning("Error in configuration " - "file: ~n~p~n",[Reason],Options, - "Error in configuration file"); - {'EXIT',Reason} -> warning("Internal error when " - "analyzing configuration " - "file: ~n~p~n",[Reason],Options, - "Internal error when " - "analyzing configuration"); - _ -> ok + case specialized_decode_prepare(EncodingRule,M,GenTOrV,Options) of + {error, Reason} -> warning("Error in configuration file: ~n~p~n", + [Reason], Options, + "Error in configuration file"); + _ -> ok end, Result = @@ -859,7 +852,7 @@ generate({true,{M,_Module,GenTOrV}},OutFile,EncodingRule,Options) -> erase(encoding_options), erase(tlv_format), % used in ber_bin, optimize erase(class_default_type),% used in ber_bin, optimize - ets:delete(check_functions), + asn1ct_table:delete(check_functions), case Result of {error,_} -> {false,Result}; @@ -1181,17 +1174,28 @@ optimize_ber_bin(Options) -> end. includes(File,Options) -> - Dir = filename:dirname(File), - Options2 = - case lists:member({i,"."},Options) of - false -> Options ++ [{i,"."}]; - _ -> Options - end, - case lists:member({i,Dir}, Options2) of - false -> Options2 ++ [{i,Dir}]; - _ -> Options2 + Options2 = include_append(".", Options), + Options3 = include_append(filename:dirname(File), Options2), + case proplists:get_value(outdir, Options) of + undefined -> Options3; + OutDir -> include_prepend(OutDir, Options3) + end. + +include_append(Dir, Options) -> + option_add({i, Dir}, Options, fun(Opts) -> Opts ++ [{i, Dir}] end). + +include_prepend(Dir, Options) -> + option_add({i, Dir}, Options, fun(Opts) -> [{i, Dir}|Opts] end). + +option_add(Option, Options, Fun) -> + case lists:member(Option, Options) of + true -> Options; + false -> Fun(Options) end. +strip_includes(Includes) -> + [I || {i, I} <- Includes]. + is_inline(Options) -> case lists:member(inline,Options) of true -> true; @@ -1221,10 +1225,7 @@ compile_py(File,OutFile,Options) -> compile(lists:concat([File,".py"]),OutFile,Options). compile(File, _OutFile, Options) -> - case catch compile(File, make_erl_options(Options)) of - Exit = {'EXIT',_Reason} -> - error("~p~n~s~n",[Exit,"error"],Options), - error; + case compile(File, make_erl_options(Options)) of {error,_Reason} -> %% case occurs due to error in asn1ct_parser2,asn1ct_check %% io:format("~p~n",[_Reason]), @@ -1237,10 +1238,7 @@ compile(File, _OutFile, Options) -> ok; ScanRes when is_list(ScanRes) -> io:format("~p~n",[ScanRes]), - ok; - Unknown -> - error("~p~n~s~n",[Unknown,"error"],Options), - error + ok end. %% Converts generic compiler options to specific options. @@ -1339,17 +1337,6 @@ start() -> start(Includes) when is_list(Includes) -> asn1_db:dbstart(Includes). -stop() -> - save(), - asn1_db:stop_server(ns), - asn1_db:stop_server(rand), - stopped. - -save() -> - asn1_db:dbstop(). - -%%clear() -> -%% asn1_db:dbclear(). encode(Module,Term) -> asn1rt:encode(Module,Term). @@ -1365,94 +1352,116 @@ decode(Module,Type,Bytes) -> asn1rt:decode(Module,Type,Bytes). -test(Module) -> - start(), - M = asn1_db:dbget(Module,'MODULE'), - {Types,_Values,_Ptypes,_Classes,_Objects,_ObjectSets} = M#module.typeorval, - test_each(Module,Types). - -test_each(Module,[Type | Rest]) -> - case test(Module,Type) of - {ok,_Result} -> - test_each(Module,Rest); - Error -> - Error +test(Module) -> test_module(Module, []). + +test(Module, [] = Options) -> test_module(Module, Options); +test(Module, [{i, _}|_] = Options) -> test_module(Module, Options); +test(Module, Type) -> test_type(Module, Type, []). + +test(Module, Type, [] = Options) -> test_type(Module, Type, Options); +test(Module, Type, [{i, _}|_] = Options) -> test_type(Module, Type, Options); +test(Module, Type, Value) -> test_value(Module, Type, Value). + +test_module(Module, Includes) -> + in_process(fun() -> + start(strip_includes(Includes)), + case check(Module, Includes) of + {ok, NewTypes} -> test_each(Module, NewTypes); + Error -> Error + end + end). + +test_each(Module, [Type|Rest]) -> + case test_type(Module, Type) of + {ok, _Result} -> test_each(Module, Rest); + Error -> Error end; test_each(_,[]) -> ok. -test(Module,Type) -> - io:format("~p:~p~n",[Module,Type]), - case (catch value(Module,Type)) of - {ok,Val} -> - %% io:format("asn1ct:test/2: ~w~n",[Val]), - test(Module,Type,Val); - {'EXIT',Reason} -> - {error,{asn1,{value,Reason}}} +test_type(Module, Type, Includes) -> + in_process(fun() -> + start(strip_includes(Includes)), + case check(Module, Includes) of + {ok, _NewTypes} -> test_type(Module, Type); + Error -> Error + end + end). + +test_type(Module, Type) -> + case get_value(Module, Type) of + {ok, Val} -> test_value(Module, Type, Val); + {error, Reason} -> {error, {asn1, {value, Reason}}} end. +test_value(Module, Type, Value) -> + in_process(fun() -> + case catch encode(Module, Type, Value) of + {ok, Bytes} -> + M = to_atom(Module), + NewBytes = prepare_bytes(M:encoding_rule(), Bytes), + case decode(Module, Type, NewBytes) of + {ok, Value} -> + {ok, {Module, Type, Value}}; + {ok, Res} -> + {error, {asn1, + {encode_decode_mismatch, + {{Module, Type, Value}, Res}}}}; + Error -> + {error, {asn1, + {{decode, + {Module, Type, Value}, Error}}}} + end; + Error -> + {error, {asn1, + {encode, {{Module, Type, Value}, Error}}}} + end + end). + +value(Module, Type) -> value(Module, Type, []). + +value(Module, Type, Includes) -> + in_process(fun() -> + start(strip_includes(Includes)), + case check(Module, Includes) of + {ok, _NewTypes} -> get_value(Module, Type); + Error -> Error + end + end). + +get_value(Module, Type) -> + case asn1ct_value:from_type(Module, Type) of + {error, Reason} -> {error, Reason}; + Result -> {ok, Result} + end. -test(Module,Type,Value) -> - case catch encode(Module,Type,Value) of - {ok,Bytes} -> - %% io:format("test 1: ~p~n",[{Bytes}]), - M = if - is_list(Module) -> - list_to_atom(Module); - true -> - Module - end, - NewBytes = - case M:encoding_rule() of - ber -> - lists:flatten(Bytes); - ber_bin when is_binary(Bytes) -> - Bytes; - ber_bin -> - list_to_binary(Bytes); - ber_bin_v2 when is_binary(Bytes) -> - Bytes; - ber_bin_v2 -> - list_to_binary(Bytes); - per -> - lists:flatten(Bytes); - per_bin when is_binary(Bytes) -> - Bytes; - per_bin -> - list_to_binary(Bytes); - uper_bin -> - Bytes - end, - case decode(Module,Type,NewBytes) of - {ok,Value} -> - {ok,{Module,Type,Value}}; - {ok,Res} -> - {error,{asn1,{encode_decode_mismatch, - {{Module,Type,Value},Res}}}}; - Error -> - {error,{asn1,{{decode, - {Module,Type,Value},Error}}}} - end; - Error -> - {error,{asn1,{encode,{{Module,Type,Value},Error}}}} +check(Module, Includes) -> + case asn1_db:dbget(Module,'MODULE') of + undefined -> + {error, {file_not_found, lists:concat([Module, ".asn1db"])}}; + M -> + TypeOrVal = M#module.typeorval, + State = #state{mname = M#module.name, + module = M#module{typeorval=[]}, + options = Includes}, + case asn1ct_check:check(State, TypeOrVal) of + {ok, {NewTypes, _, _, _, _, _}, _} -> {ok, NewTypes}; + {error, Reason} -> {error, Reason} + end end. -value(Module) -> - start(), - M = asn1_db:dbget(Module,'MODULE'), - {Types,_Values,_Ptypes,_Classes,_Objects,_ObjectSets} = M#module.typeorval, - lists:map(fun(A) ->value(Module,A) end,Types). +to_atom(Term) when is_list(Term) -> list_to_atom(Term); +to_atom(Term) when is_atom(Term) -> Term. -value(Module,Type) -> - start(), - case catch asn1ct_value:get_type(Module,Type,no) of - {error,Reason} -> - {error,Reason}; - {'EXIT',Reason} -> - {error,Reason}; - Result -> - {ok,Result} - end. +prepare_bytes(ber, Bytes) -> lists:flatten(Bytes); +prepare_bytes(ber_bin, Bytes) when is_binary(Bytes) -> Bytes; +prepare_bytes(ber_bin, Bytes) -> list_to_binary(Bytes); +prepare_bytes(ber_bin_v2, Bytes) when is_binary(Bytes) -> Bytes; +prepare_bytes(ber_bin_v2, Bytes) -> list_to_binary(Bytes); +prepare_bytes(per, Bytes) -> lists:flatten(Bytes); +prepare_bytes(per_bin, Bytes) when is_binary(Bytes) -> Bytes; +prepare_bytes(per_bin, Bytes) -> list_to_binary(Bytes); +prepare_bytes(uper_bin, Bytes) -> Bytes. vsn() -> ?vsn. @@ -1484,38 +1493,6 @@ print_listing([],_) -> ok. -%% functions to administer ets tables - -%% Always creates a new table -create_ets_table(Name,Options) when is_atom(Name) -> - case ets:info(Name) of - undefined -> - ets:new(Name,Options); - _ -> - ets:delete(Name), - ets:new(Name,Options) - end. - -%% Creates a new ets table only if no table exists -create_if_no_table(Name,Options) -> - case ets:info(Name) of - undefined -> - %% create a new table - create_ets_table(Name,Options); - _ -> ok - end. - - -delete_tables([Table|Ts]) -> - case ets:info(Table) of - undefined -> ok; - _ -> ets:delete(Table) - end, - delete_tables(Ts); -delete_tables([]) -> - ok. - - specialized_decode_prepare(Erule,M,TsAndVs,Options) -> case lists:member(asn1config,Options) of true -> @@ -1534,26 +1511,26 @@ partial_decode_prepare(ber_bin_v2,M,TsAndVs,Options) when is_tuple(TsAndVs) -> _ -> M#module.name end, %% io:format("ModName: ~p~nM#module.name: ~p~n~n",[ModName,M#module.name]), - CfgList = read_config_file(ModName), - SelectedDecode = get_config_info(CfgList,selective_decode), - ExclusiveDecode = get_config_info(CfgList,exclusive_decode), - CommandList = - create_partial_decode_gen_info(M#module.name,SelectedDecode), - %% To convert CommandList to a proper list for the driver change - %% the list:[[choosen,Tag1],skip,[skip_optional,Tag2]] to L = - %% [5,2,Tag1,0,1,Tag2] where 5 is the length, and call - %% port_control(asn1_driver_port,3,[L| Bin]) - save_config(partial_decode,CommandList), - save_gen_state(selective_decode,SelectedDecode), -% io:format("selective_decode: CommandList:~n~p~nSelectedDecode:~n~p~n", -% [CommandList,SelectedDecode]), - CommandList2 = - create_partial_inc_decode_gen_info(M#module.name,ExclusiveDecode), -% io:format("partial_incomplete_decode = ~p~n",[CommandList2]), - Part_inc_tlv_tags = tlv_tags(CommandList2), -% io:format("partial_incomplete_decode: tlv_tags = ~p~n",[Part_inc_tlv_tags]), - save_config(partial_incomplete_decode,Part_inc_tlv_tags), - save_gen_state(exclusive_decode,ExclusiveDecode,Part_inc_tlv_tags); + case read_config_file(ModName) of + no_config_file -> + ok; + CfgList -> + SelectedDecode = get_config_info(CfgList,selective_decode), + ExclusiveDecode = get_config_info(CfgList,exclusive_decode), + CommandList = create_partial_decode_gen_info(M#module.name, + SelectedDecode), + %% To convert CommandList to a proper list for the driver change + %% the list:[[choosen,Tag1],skip,[skip_optional,Tag2]] to L = + %% [5,2,Tag1,0,1,Tag2] where 5 is the length, and call + %% port_control(asn1_driver_port,3,[L| Bin]) + save_config(partial_decode,CommandList), + save_gen_state(selective_decode,SelectedDecode), + CommandList2 = create_partial_inc_decode_gen_info(M#module.name, + ExclusiveDecode), + Part_inc_tlv_tags = tlv_tags(CommandList2), + save_config(partial_incomplete_decode,Part_inc_tlv_tags), + save_gen_state(exclusive_decode,ExclusiveDecode,Part_inc_tlv_tags) + end; partial_decode_prepare(_,_,_,_) -> ok. @@ -2032,7 +2009,7 @@ read_config_file(ModuleName) -> read_config_file1(ModuleName,[]) -> case filename:extension(ModuleName) of ".asn1config" -> - throw({error,enoent}); + no_config_file; _ -> read_config_file(lists:concat([ModuleName,".asn1config"])) end; @@ -2061,14 +2038,14 @@ get_config_info(CfgList,InfoType) -> %% Before saving anything check if a table exists %% The record gen_state is saved with the key {asn1_config,gen_state} save_config(Key,Info) -> - create_if_no_table(asn1_general,[named_table]), - ets:insert(asn1_general,{{asn1_config,Key},Info}). + asn1ct_table:new_reuse(asn1_general), + asn1ct_table:insert(asn1_general, {{asn1_config, Key}, Info}). read_config_data(Key) -> - case ets:info(asn1_general) of - undefined -> undefined; - _ -> - case ets:lookup(asn1_general,{asn1_config,Key}) of + case asn1ct_table:exists(asn1_general) of + false -> undefined; + true -> + case asn1ct_table:lookup(asn1_general,{asn1_config,Key}) of [{_,Data}] -> Data; Err -> % Err is [] when nothing was saved in the ets table %% io:format("strange data from config file ~w~n",[Err]), @@ -2595,3 +2572,21 @@ is_werr(S) when is_record(S, state) -> is_werr(S#state.options); is_werr(O) -> lists:member(warnings_as_errors, O). + + +in_process(Fun) -> + Parent = self(), + Pid = spawn_link(fun() -> process(Parent, Fun) end), + receive + {Pid, Result} -> Result; + {Pid, Class, Reason, Stack} -> + ST = try throw(x) catch throw:x -> erlang:get_stacktrace() end, + erlang:raise(Class, Reason, Stack ++ ST) + end. + +process(Parent, Fun) -> + try + Parent ! {self(), Fun()} + catch Class:Reason -> + Parent ! {self(), Class, Reason, erlang:get_stacktrace()} + end. diff --git a/lib/asn1/src/asn1ct_check.erl b/lib/asn1/src/asn1ct_check.erl index 105fc02819..c223561f12 100644 --- a/lib/asn1/src/asn1ct_check.erl +++ b/lib/asn1/src/asn1ct_check.erl @@ -1,7 +1,8 @@ +%% vim: tabstop=8:shiftwidth=4 %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2011. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -94,8 +95,8 @@ check(S,{Types,Values,ParameterizedTypes,Classes,Objects,ObjectSets}) -> _Perror = checkp(S,ParameterizedTypes,[]), % must do this before the templates are used %% table to save instances of parameterized objects,object sets - asn1ct:create_ets_table(parameterized_objects,[named_table]), - asn1ct:create_ets_table(inlined_objects,[named_table]), + asn1ct_table:new(parameterized_objects), + asn1ct_table:new(inlined_objects), Terror = checkt(S,Types,[]), @@ -144,17 +145,17 @@ check(S,{Types,Values,ParameterizedTypes,Classes,Objects,ObjectSets}) -> NewObjectSets, [],[],[]), ?dbg("checko finished with errors:~n~p~n~n",[Oerror]), - InlinedObjTuples = ets:tab2list(inlined_objects), + InlinedObjTuples = asn1ct_table:to_list(inlined_objects), InlinedObjects = lists:map(Element2,InlinedObjTuples), - ets:delete(inlined_objects), - ParameterizedElems = ets:tab2list(parameterized_objects), + asn1ct_table:delete(inlined_objects), + ParameterizedElems = asn1ct_table:to_list(parameterized_objects), ParObjectSets = lists:filter(fun({_OSName,objectset,_}) -> true; (_)-> false end,ParameterizedElems), ParObjectSetNames = lists:map(Element1,ParObjectSets), ParTypes = lists:filter(fun({_TypeName,type,_}) -> true; (_) -> false end, ParameterizedElems), ParTypesNames = lists:map(Element1,ParTypes), - ets:delete(parameterized_objects), + asn1ct_table:delete(parameterized_objects), put(asn1_reference,undefined), Exporterror = check_exports(S,S#state.module), @@ -4923,12 +4924,7 @@ get_referenced(S,Emod,Ename,Pos) -> %% May be an imported entity in module Emod or Emod may not exist case asn1_db:dbget(Emod,'MODULE') of undefined -> - case parse_and_save(S,Emod) of - ok -> - get_referenced(S,Emod,Ename,Pos); - _ -> - throw({error,{asn1,{module_not_found,Emod}}}) - end; + throw({error,{asn1,{module_not_found,Emod}}}); _ -> NewS = update_state(S,Emod), get_imported(NewS,Ename,Emod,Pos) @@ -4970,13 +4966,7 @@ get_imported(S,Name,Module,Pos) -> parse_and_save(S,Imodule), case asn1_db:dbget(Imodule,'MODULE') of undefined -> - case parse_and_save(S,Imodule) of - ok -> - %% check with cover - get_referenced(S,Module,Name,Pos); - _ -> - throw({error,{asn1,{module_not_found,Imodule}}}) - end; + throw({error,{asn1,{module_not_found,Imodule}}}); Im when is_record(Im,module) -> case is_exported(Im,Name) of false -> @@ -5116,16 +5106,16 @@ renamed_reference(S,#'Externaltypereference'{type=Name,module=Module}) -> renamed_reference(S,Name,Module) -> %% first check if there is a renamed type in this module %% second check if any type was imported with this name - case ets:info(renamed_defs) of - undefined -> undefined; - _ -> - case ets:match(renamed_defs,{'$1',Name,Module}) of + case asn1ct_table:exists(renamed_defs) of + false -> undefined; + true -> + case asn1ct_table:match(renamed_defs, {'$1',Name,Module}) of [] -> - case ets:info(original_imports) of - undefined -> + case asn1ct_table:exists(original_imports) of + false -> undefined; - _ -> - case ets:match(original_imports,{Module,'$1'}) of + true -> + case asn1ct_table:match(original_imports, {Module,'$1'}) of [] -> undefined; [[ImportsList]] -> @@ -6005,17 +5995,12 @@ tag_nums_root2([],Ext,Root2) -> [0,Ext,Root2]. is_automatic_tagged_in_multi_file(Name) -> - case ets:info(automatic_tags) of - undefined -> + case asn1ct_table:exists(automatic_tags) of + false -> %% this case when not multifile compilation false; - _ -> -% case ets:member(automatic_tags,Name) of - case ets:lookup(automatic_tags,Name) of -% true -> -% true; -% _ -> -% false + true -> + case asn1ct_table:lookup(automatic_tags, Name) of [] -> false; _ -> true end diff --git a/lib/asn1/src/asn1ct_gen.erl b/lib/asn1/src/asn1ct_gen.erl index 0f8833f716..fda4e1c6d9 100644 --- a/lib/asn1/src/asn1ct_gen.erl +++ b/lib/asn1/src/asn1ct_gen.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2011. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -169,7 +169,7 @@ pgen_objectsets(Rtmod,Erules,Module,[H|T]) -> pgen_objectsets(Rtmod,Erules,Module,T). pgen_check_defaultval(Erules,Module) -> - CheckObjects = ets:tab2list(check_functions), + CheckObjects = asn1ct_table:to_list(check_functions), case get(asndebug) of true -> FileName = lists:concat([Module,".table"]), @@ -1598,7 +1598,7 @@ gen_check_call(TopType,Cname,Type,InnerType,WhatKind,DefaultValue,Element) -> NameList = [Cname|TopType], Name = list2name(NameList ++ [check]), emit({"'",Name,"'(",DefaultValue,", ",Element,")"}), - ets:insert(check_functions,{Name,Type}), + asn1ct_table:insert(check_functions, {Name, Type}), %% Must look for check functions in InnerType, %% that may be referenced or internal defined %% constructed types not used elsewhere. @@ -1744,10 +1744,9 @@ lookahead_reference(#'Externaltypereference'{module=M,type=T}) -> end. insert_once(Table,Object) -> - _Info = ets:info(Table), - case ets:lookup(Table,element(1,Object)) of + case asn1ct_table:lookup(Table, element(1, Object)) of [] -> - ets:insert(Table,Object); %returns true + asn1ct_table:insert(Table, Object); %returns true _ -> false end. diff --git a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl index 365bb84d52..597fb0030b 100644 --- a/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl +++ b/lib/asn1/src/asn1ct_gen_ber_bin_v2.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2002-2011. All Rights Reserved. +%% Copyright Ericsson AB 2002-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -1834,7 +1834,7 @@ mk_object_val(Val, Ack, Len) -> mk_object_val(Val bsr 7, [((Val band 127) bor 128) | Ack], Len + 1). add_func(F={_Func,_Arity}) -> - ets:insert(asn1_functab,{F}). + asn1ct_table:insert(asn1_functab, {F}). %% For BER the ExtensionAdditionGroup notation has no impact on the encoding/decoding %% and therefore we only filter away the ExtensionAdditionGroup start and end markers diff --git a/lib/asn1/src/asn1ct_name.erl b/lib/asn1/src/asn1ct_name.erl index a6aa4255cc..3ab6f7b0ed 100644 --- a/lib/asn1/src/asn1ct_name.erl +++ b/lib/asn1/src/asn1ct_name.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -20,8 +20,7 @@ -module(asn1ct_name). %%-compile(export_all). --export([name_server_loop/1, - start/0, +-export([start/0, stop/0, push/1, pop/1, @@ -35,38 +34,50 @@ new/1]). start() -> - start_server(asn1_ns, asn1ct_name,name_server_loop,[[]]). + Parent = self(), + case get(?MODULE) of + undefined -> + put(?MODULE, spawn_link(fun() -> + Ref = monitor(process, Parent), + name_server_loop({Ref,Parent},[]) + end)), + ok; + _Pid -> + already_started + end. -stop() -> stop_server(asn1_ns). +stop() -> + req(stop), + erase(?MODULE). -name_server_loop(Vars) -> +name_server_loop({Ref, Parent} = Monitor,Vars) -> %% io:format("name -- ~w~n",[Vars]), receive {From,{current,Variable}} -> - From ! {asn1_ns,get_curr(Vars,Variable)}, - name_server_loop(Vars); + From ! {?MODULE,get_curr(Vars,Variable)}, + name_server_loop(Monitor,Vars); {From,{pop,Variable}} -> - From ! {asn1_ns,done}, - name_server_loop(pop_var(Vars,Variable)); + From ! {?MODULE,done}, + name_server_loop(Monitor,pop_var(Vars,Variable)); {From,{push,Variable}} -> - From ! {asn1_ns,done}, - name_server_loop(push_var(Vars,Variable)); + From ! {?MODULE,done}, + name_server_loop(Monitor,push_var(Vars,Variable)); {From,{delete,Variable}} -> - From ! {asn1_ns,done}, - name_server_loop(delete_var(Vars,Variable)); + From ! {?MODULE,done}, + name_server_loop(Monitor,delete_var(Vars,Variable)); {From,{new,Variable}} -> - From ! {asn1_ns,done}, - name_server_loop(new_var(Vars,Variable)); + From ! {?MODULE,done}, + name_server_loop(Monitor,new_var(Vars,Variable)); {From,{prev,Variable}} -> - From ! {asn1_ns,get_prev(Vars,Variable)}, - name_server_loop(Vars); + From ! {?MODULE,get_prev(Vars,Variable)}, + name_server_loop(Monitor,Vars); {From,{next,Variable}} -> - From ! {asn1_ns,get_next(Vars,Variable)}, - name_server_loop(Vars); + From ! {?MODULE,get_next(Vars,Variable)}, + name_server_loop(Monitor,Vars); + {'DOWN', Ref, process, Parent, Reason} -> + exit(Reason); {From,stop} -> - unregister(asn1_ns), - From ! {asn1_ns,stopped}, - exit(normal) + From ! {?MODULE,stopped} end. active(V) -> @@ -76,12 +87,16 @@ active(V) -> end. req(Req) -> - asn1_ns ! {self(), Req}, - receive {asn1_ns, Reply} -> Reply end. + get(?MODULE) ! {self(), Req}, + receive + {?MODULE, Reply} -> Reply + after 5000 -> + exit(name_server_timeout) + end. pop(V) -> req({pop,V}). push(V) -> req({push,V}). -clear() -> req(stop), start(). +clear() -> stop(), start(). curr(V) -> req({current,V}). new(V) -> req({new,V}). delete(V) -> req({delete,V}). @@ -209,25 +224,3 @@ get_next(Vars,Variable) -> _ -> none end. - - -stop_server(Name) -> - stop_server(Name, whereis(Name)). -stop_server(_Name, undefined) -> stopped; -stop_server(Name, _Pid) -> - Name ! {self(), stop}, - receive {Name, _} -> stopped end. - - -start_server(Name,Mod,Fun,Args) -> - case whereis(Name) of - undefined -> - case catch register(Name, spawn(Mod,Fun, Args)) of - {'EXIT',{badarg,_}} -> - start_server(Name,Mod,Fun,Args); - _ -> - ok - end; - _Pid -> - already_started - end. diff --git a/lib/asn1/src/asn1ct_parser2.erl b/lib/asn1/src/asn1ct_parser2.erl index 224a535e87..007d390a1b 100644 --- a/lib/asn1/src/asn1ct_parser2.erl +++ b/lib/asn1/src/asn1ct_parser2.erl @@ -1,7 +1,8 @@ +%% vim: tabstop=8:shiftwidth=4 %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2010. All Rights Reserved. +%% Copyright Ericsson AB 2000-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -81,14 +82,15 @@ parse_ModuleDefinition([{typereference,L1,ModuleIdentifier}|Rest0]) -> case Rest3 of [{'::=',_L7}, {'BEGIN',_L8}|Rest4] -> {Exports, Rest5} = parse_Exports(Rest4), - {Imports, Rest6} = parse_Imports(Rest5), + {{imports, Imports}, Rest6} = parse_Imports(Rest5), + put({get(asn1_module), imports}, Imports), {#module{ pos = L1, name = ModuleIdentifier, defid = [], % fix this tagdefault = TagDefault, extensiondefault = ExtensionDefault, exports = Exports, - imports = Imports},Rest6}; + imports = {imports, Imports}}, Rest6}; _ -> throw({asn1_error,{get_line(hd(Rest3)),get(asn1_module), [got,get_token(hd(Rest3)),expected,"::= BEGIN"]}}) end; @@ -717,12 +719,12 @@ parse_DefinedType(Tokens=[{typereference,L1,TypeName}, {'EXIT',_Reason} -> Rest2 = [T2,T3|Rest], {#type{def = #'Externaltypereference'{pos=L1, - module=get(asn1_module), + module=resolve_module(TypeName), type=TypeName}},Rest2}; {asn1_error,_} -> Rest2 = [T2,T3|Rest], {#type{def = #'Externaltypereference'{pos=L1, - module=get(asn1_module), + module=resolve_module(TypeName), type=TypeName}},Rest2}; Result -> Result @@ -735,7 +737,7 @@ parse_DefinedType([{typereference,L1,Module},{'.',_},{typereference,_,TypeName}| parse_DefinedType([{typereference,L1,TypeName}|Rest]) -> case is_pre_defined_class(TypeName) of false -> - {#type{def = #'Externaltypereference'{pos=L1,module=get(asn1_module), + {#type{def = #'Externaltypereference'{pos=L1,module=resolve_module(TypeName), type=TypeName}},Rest}; _ -> throw({asn1_error, @@ -758,6 +760,21 @@ parse_SelectionType(Tokens) -> [got,get_token(hd(Tokens)),expected,'identifier <']}}). +resolve_module(Type) -> + Current = get(asn1_module), + Imports = get({Current, imports}), + resolve_module(Type, Current, Imports). + +resolve_module(_Type, Current, undefined) -> + Current; +resolve_module(Type, Current, Imports) -> + case [Mod || #'SymbolsFromModule'{symbols = S, module = Mod} <- Imports, + #'Externaltypereference'{type = T} <- S, + Type == T] of + [#'Externaltypereference'{type = Mod}] -> Mod; + [] -> Current + end. + %% -------------------------- @@ -1539,7 +1556,7 @@ parse_DefinedObjectSet([{typereference,L1,ModuleName},{'.',_}, {{objectset,L1,#'Externaltypereference'{pos=L2,module=ModuleName, type=ObjSetName}},Rest}; parse_DefinedObjectSet([{typereference,L1,ObjSetName}|Rest]) -> - {{objectset,L1,#'Externaltypereference'{pos=L1,module=get(asn1_module), + {{objectset,L1,#'Externaltypereference'{pos=L1,module=resolve_module(ObjSetName), type=ObjSetName}},Rest}; parse_DefinedObjectSet(Tokens) -> throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), @@ -3203,17 +3220,17 @@ prioritize_error(ErrList) -> tref2Exttref(#typereference{pos=Pos,val=Name}) -> #'Externaltypereference'{pos=Pos, - module=get(asn1_module), + module=resolve_module(Name), type=Name}. tref2Exttref(Pos,Name) -> #'Externaltypereference'{pos=Pos, - module=get(asn1_module), + module=resolve_module(Name), type=Name}. identifier2Extvalueref(#identifier{pos=Pos,val=Name}) -> #'Externalvaluereference'{pos=Pos, - module=get(asn1_module), + module=resolve_module(Name), value=Name}. %% lookahead_assignment/1 checks that the next sequence of tokens diff --git a/lib/asn1/src/asn1ct_table.erl b/lib/asn1/src/asn1ct_table.erl new file mode 100644 index 0000000000..a5eb6d0413 --- /dev/null +++ b/lib/asn1/src/asn1ct_table.erl @@ -0,0 +1,76 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2012. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%% +-module(asn1ct_table). + +%% Table abstraction module for ASN.1 compiler + +-export([new/1]). +-export([new/2]). +-export([new_reuse/1]). +-export([new_reuse/2]). +-export([exists/1]). +-export([size/1]). +-export([insert/2]). +-export([lookup/2]). +-export([match/2]). +-export([to_list/1]). +-export([delete/1]). % TODO: Remove (since we run in a separate process) + + +%% Always creates a new table +new(Table) -> new(Table, []). +new(Table, Options) -> + TableId = case get(Table) of + undefined -> + ets:new(Table, Options); + _ -> + delete(Table), + ets:new(Table, Options) + end, + put(Table, TableId). + +%% Only create it if it doesn't exist yet +new_reuse(Table) -> new_reuse(Table, []). +new_reuse(Table, Options) -> + not exists(Table) andalso new(Table, Options). + +exists(Table) -> get(Table) =/= undefined. + +size(Table) -> ets:info(get(Table), size). + +insert(Table, Tuple) -> ets:insert(get(Table), Tuple). + +lookup(Table, Key) -> ets:lookup(get(Table), Key). + +match(Table, MatchSpec) -> ets:match(get(Table), MatchSpec). + +to_list(Table) -> ets:tab2list(get(Table)). + +delete(Tables) when is_list(Tables) -> + [delete(T) || T <- Tables], + true; +delete(Table) when is_atom(Table) -> + case get(Table) of + undefined -> + true; + TableId -> + ets:delete(TableId), + erase(Table) + end. diff --git a/lib/asn1/src/asn1ct_value.erl b/lib/asn1/src/asn1ct_value.erl index d099376b1b..9013baef92 100644 --- a/lib/asn1/src/asn1ct_value.erl +++ b/lib/asn1/src/asn1ct_value.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2011. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -25,58 +25,58 @@ -include("asn1_records.hrl"). %-compile(export_all). --export([get_type/3]). --export([i_random/1]). - +-export([from_type/2]). %% Generate examples of values ****************************** %%****************************************x -get_type(M,Typename,Tellname) -> +from_type(M,Typename) -> case asn1_db:dbget(M,Typename) of undefined -> - {asn1_error,{not_found,{M,Typename}}}; + {error,{not_found,{M,Typename}}}; Tdef when is_record(Tdef,typedef) -> Type = Tdef#typedef.typespec, - get_type(M,[Typename],Type,Tellname); + from_type(M,[Typename],Type); + Vdef when is_record(Vdef,valuedef) -> + from_value(Vdef); Err -> - {asn1_error,{other,Err}} + {error,{other,Err}} end. -get_type(M,Typename,Type,Tellname) when is_record(Type,type) -> +from_type(M,Typename,Type) when is_record(Type,type) -> InnerType = get_inner(Type#type.def), case asn1ct_gen:type(InnerType) of #'Externaltypereference'{module=Emod,type=Etype} -> - get_type(Emod,Etype,Tellname); + from_type(Emod,Etype); {_,user} -> - case Tellname of - yes -> {Typename,get_type(M,InnerType,no)}; - no -> get_type(M,InnerType,no) - end; + from_type(M,InnerType); {notype,_} -> true; {primitive,bif} -> - get_type_prim(Type,get_encoding_rule(M)); + from_type_prim(Type,get_encoding_rule(M)); 'ASN1_OPEN_TYPE' -> case Type#type.constraint of [#'Externaltypereference'{type=TrefConstraint}] -> - get_type(M,TrefConstraint,no); + from_type(M,TrefConstraint); _ -> ERule = get_encoding_rule(M), open_type_value(ERule) end; {constructed,bif} when Typename == ['EXTERNAL'] -> - Val=get_type_constructed(M,Typename,InnerType,Type), + Val=from_type_constructed(M,Typename,InnerType,Type), asn1rt_check:transform_to_EXTERNAL1994(Val); {constructed,bif} -> - get_type_constructed(M,Typename,InnerType,Type) + from_type_constructed(M,Typename,InnerType,Type) end; -get_type(M,Typename,#'ComponentType'{name = Name,typespec = Type},_) -> - get_type(M,[Name|Typename],Type,no); -get_type(_,_,_,_) -> % 'EXTENSIONMARK' +from_type(M,Typename,#'ComponentType'{name = Name,typespec = Type}) -> + from_type(M,[Name|Typename],Type); +from_type(_,_,_) -> % 'EXTENSIONMARK' undefined. +from_value(#valuedef{type = #type{def = 'INTEGER'}, value = Val}) -> + Val. + get_inner(A) when is_atom(A) -> A; get_inner(Ext) when is_record(Ext,'Externaltypereference') -> Ext; get_inner({typereference,_Pos,Name}) -> Name; @@ -93,7 +93,7 @@ get_inner(T) when is_tuple(T) -> -get_type_constructed(M,Typename,InnerType,D) when is_record(D,type) -> +from_type_constructed(M,Typename,InnerType,D) when is_record(D,type) -> case InnerType of 'SET' -> get_sequence(M,Typename,D); @@ -132,7 +132,7 @@ get_components(M,Typename,{Root,Ext}) -> %% Should enhance this *** HERE *** with proper handling of extensions get_components(M,Typename,[H|T]) -> - [get_type(M,Typename,H,no)| + [from_type(M,Typename,H)| get_components(M,Typename,T)]; get_components(_,_,[]) -> []. @@ -145,10 +145,10 @@ get_choice(M,Typename,Type) -> {CompList,ExtList} -> % Should be enhanced to handle extensions too CList = CompList ++ ExtList, C = lists:nth(random(length(CList)),CList), - {C#'ComponentType'.name,get_type(M,Typename,C,no)}; + {C#'ComponentType'.name,from_type(M,Typename,C)}; CompList when is_list(CompList) -> C = lists:nth(random(length(CompList)),CompList), - {C#'ComponentType'.name,get_type(M,Typename,C,no)} + {C#'ComponentType'.name,from_type(M,Typename,C)} end. get_sequence_of(M,Typename,Type,TypeSuffix) -> @@ -157,14 +157,14 @@ get_sequence_of(M,Typename,Type,TypeSuffix) -> C = Type#type.constraint, S = size_random(C), NewTypeName = [TypeSuffix|Typename], - gen_list(M,NewTypeName,Oftype,no,S). + gen_list(M,NewTypeName,Oftype,S). -gen_list(_,_,_,_,0) -> +gen_list(_,_,_,0) -> []; -gen_list(M,Typename,Oftype,Tellname,N) -> - [get_type(M,Typename,Oftype,no)|gen_list(M,Typename,Oftype,Tellname,N-1)]. +gen_list(M,Typename,Oftype,N) -> + [from_type(M,Typename,Oftype)|gen_list(M,Typename,Oftype,N-1)]. -get_type_prim(D,Erule) -> +from_type_prim(D,Erule) -> C = D#type.constraint, case D#type.def of 'INTEGER' -> @@ -198,6 +198,7 @@ get_type_prim(D,Erule) -> NN = [X||{X,_} <- NNew], case NN of [] -> + io:format(user, "Enum = ~p~n", [Enum]), asn1_EMPTY; _ -> case C of @@ -412,14 +413,20 @@ adjust_list1(Len,Orig,[Oh|Ot],Acc) -> adjust_list1(Len-1,Orig,Ot,[Oh|Acc]). -get_constraint(C,Key) -> - case lists:keysearch(Key,1,C) of - false -> - no; - {value,{_,V}} -> - V +get_constraint(C, Key) -> + case lists:keyfind(Key, 1, C) of + false -> no; + {'ValueRange', {Lb, Ub}} -> {check_external(Lb), check_external(Ub)}; + {'SizeConstraint', N} -> N; + {Key, Value} -> Value end. +check_external(ExtRef) when is_record(ExtRef, 'Externalvaluereference') -> + #'Externalvaluereference'{module = Emod, value = Evalue} = ExtRef, + from_type(Emod, Evalue); +check_external(Value) -> + Value. + get_encoding_rule(M) -> Mod = if is_list(M) -> diff --git a/lib/asn1/test/Makefile b/lib/asn1/test/Makefile index 7ecd544d4b..1621abbec9 100644 --- a/lib/asn1/test/Makefile +++ b/lib/asn1/test/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 1997-2011. All Rights Reserved. +# Copyright Ericsson AB 1997-2012. All Rights Reserved. # # The contents of this file are subject to the Erlang Public License, # Version 1.1, (the "License"); you may not use this file except in @@ -28,11 +28,10 @@ MODULES= \ h323test \ choice_extension \ ber_decode_error \ - testExternal \ testPrim \ - testPrimStrings \ + testPrimStrings \ testCompactBitString \ - testPrimExternal \ + testPrimExternal \ testChoPrim \ testChoExtension \ testChoExternal \ @@ -86,15 +85,12 @@ MODULES= \ testMergeCompile \ testDeepTConstr \ testTimer \ - testRANAP \ testMegaco \ - testMvrasn6 \ testSeqSetDefaultVal \ testParamBasic \ testContextSwitchingTypes \ testTypeValueNotation \ testOpenTypeImplicitTag \ - testROSE \ testINSTANCE_OF \ test_partial_incomplete_decode \ testDER \ @@ -108,7 +104,6 @@ MODULES= \ test_inline \ testTcapsystem \ testNBAPsystem \ - test_bad_values \ test_compile_options \ testDoubleEllipses \ test_modified_x420 \ @@ -118,16 +113,9 @@ MODULES= \ asn1_app_test \ asn1_appup_test \ asn1_wrapper \ - asn1_SUITE \ - asn1_bin_SUITE \ - asn1_bin_v2_SUITE + asn1_SUITE SUITE= asn1_SUITE.erl -SUITE_BIN= asn1_bin_SUITE.erl -SUITE_BIN_V2= asn1_bin_v2_SUITE.erl -SUITE_SRC= asn1_SUITE.erl.src -SUITE_BIN_SRC= asn1_bin_SUITE.erl.src -SUITE_BIN_V2_SRC= asn1_bin_SUITE.erl.src ERL_FILES= $(MODULES:%=%.erl) @@ -156,30 +144,10 @@ $(EMAKEFILE): $(ERL_FILES) $(HRL_FILES) tests debug opt: $(SUITE) $(SUITE_BIN) $(SUITE_BIN_V2) $(EMAKEFILE) clean: - rm -f $(SUITE) $(SUITE_BIN) $(SUITE_BIN_V2) rm -f core docs: -#----------------------------------------------------- -# Special Targets -#----------------------------------------------------- -$(SUITE): $(SUITE_SRC) - sed -e 's;%BIN%;;' -e 's;%PER%;per;' -e 's;%BER%;ber;' $< > $@ - cat asn1_common_SUITE.erl.src >> $@ - cat asn1_particular_SUITE.erl.src >> $@ - - -$(SUITE_BIN): $(SUITE_SRC) - sed -e 's;%BIN%;bin_;' -e 's;%PER%;per_bin;' -e 's;%BER%;ber_bin;' $< > $@ - echo "common() -> []." >> $@ - cat asn1_bin_particular_SUITE.erl.src >> $@ - -$(SUITE_BIN_V2): $(SUITE_SRC) - sed -e 's;%BIN%;bin_v2_;' -e 's;%PER%;per_bin;' -e 's;%BER%;ber_bin_v2;' $< > $@ - echo "common() -> []." >> $@ - cat asn1_bin_v2_particular_SUITE.erl.src >> $@ - # ---------------------------------------------------- # Release Target # ---------------------------------------------------- @@ -190,15 +158,11 @@ release_spec: opt release_tests_spec: opt $(INSTALL_DIR) $(RELSYSDIR) $(INSTALL_DIR) $(RELSYSDIR)/asn1_SUITE_data - $(INSTALL_DIR) $(RELSYSDIR)/asn1_bin_SUITE_data - $(INSTALL_DIR) $(RELSYSDIR)/asn1_bin_v2_SUITE_data $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR) $(INSTALL_DATA) asn1.spec asn1.cover $(INSTALL_PROGS) $(RELSYSDIR) chmod -R u+w $(RELSYSDIR) cd asn1_SUITE_data; tar cfh $(RELSYSDIR)/asn1_SUITE_data.tar * cd $(RELSYSDIR)/asn1_SUITE_data; tar xf $(RELSYSDIR)/asn1_SUITE_data.tar - cd $(RELSYSDIR)/asn1_bin_SUITE_data; tar xf $(RELSYSDIR)/asn1_SUITE_data.tar - cd $(RELSYSDIR)/asn1_bin_v2_SUITE_data; tar xf $(RELSYSDIR)/asn1_SUITE_data.tar rm $(RELSYSDIR)/asn1_SUITE_data.tar release_docs_spec: diff --git a/lib/asn1/test/asn1_SUITE.erl b/lib/asn1/test/asn1_SUITE.erl new file mode 100644 index 0000000000..3b9a7532c0 --- /dev/null +++ b/lib/asn1/test/asn1_SUITE.erl @@ -0,0 +1,1511 @@ +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2001-2012. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +%% Purpose: Test suite for the ASN.1 application + +-module(asn1_SUITE). + +-define(only_per(Func), + if Rule == per orelse Rule == per_bin -> Func; + true -> ok + end). +-define(only_ber(Func), + if Rule == ber orelse Rule == ber_bin orelse Rule == ber_bin_v2 -> Func; + true -> ok + end). +-define(only_uper(Func), + case Rule of + uper_bin -> Func; + _ -> ok + end). +-define(only_per_nif(Func), + case {Rule, lists:member(optimize, Opts)} of + {per_bin, true} -> Func; + _ -> ok + end). +-define(only_ber_nif(Func), + case {Rule, lists:member(nif, Opts)} of + {ber_bin_v2, true} -> Func; + _ -> ok + end). + +-compile(export_all). + +-include_lib("test_server/include/test_server.hrl"). + +%%------------------------------------------------------------------------------ +%% Suite definition +%%------------------------------------------------------------------------------ + +suite() -> [{ct_hooks, [ts_install_cth]}]. + +all() -> + [{group, parallel}, + {group, app_test}, + {group, appup_test}, + + % TODO: Investigate parallel running of these: + testComment, + testName2Number, + ticket_7407, + ticket7904, + + {group, performance}]. + +groups() -> + [{compile, parallel([]), + [c_syntax, + c_string, + c_implicit_before_choice]}, + + {ber, parallel([]), + [ber_choiceinseq, + % Uses 'SOpttest' + {group, [], [ber_optional, + ber_optional_keyed_list]}]}, + + {app_test, [], [{asn1_app_test, all}]}, + + {appup_test, [], [{asn1_appup_test, all}]}, + + {parallel, parallel([]), + [{group, compile}, + {group, ber}, + % Uses 'P-Record', 'Constraints', 'MEDIA-GATEWAY-CONTROL'... + {group, [], [parse, + test_driver_load, + test_undecoded_rest, + test_inline, + specialized_decodes, + special_decode_performance, + testMegaco, + testConstraints, + testCompactBitString]}, + default, + % Uses 'Def', 'MULTIMEDIA-SYSTEM-CONTROL', 'H323-MESSAGES', 'Prim', + % 'Real' + {group, [], [testPrim, + rtUI, + testPrimStrings, + testInvokeMod, + per, + ber_other, + h323test, + per_GeneralString]}, + testChoPrim, + testChoExtension, + testChoOptional, + testChoOptionalImplicitTag, + testChoRecursive, + testChoTypeRefCho, + testChoTypeRefPrim, + testChoTypeRefSeq, + testChoTypeRefSet, + testDef, + testOpt, + testSeqDefault, + % Uses 'External' + {group, [], [testChoExternal, + testPrimExternal, + testSeqExtension, + testSeqExternal, + testSeqOfExternal, + testSeqOfTag, + testSeqTag, + testSetExtension, + testSetExternal, + testSetOfExternal, + testSetOfTag, + testSetTag]}, + testSeqOptional, + testSeqPrim, + testSeqTypeRefCho, + % Uses 'SeqTypeRefPrim' + {group, [], [testSeqTypeRefPrim, + testTypeValueNotation]}, + testSeqTypeRefSeq, + testSeqTypeRefSet, + % Uses 'SeqOf' + {group, [], [testSeqOf, + testSeqOfIndefinite]}, % Uses 'Mvrasn*' + testSeqOfCho, + testSetDefault, + testExtensionAdditionGroup, + testSetOptional, + testSetPrim, + testSetTypeRefCho, + testSetTypeRefPrim, + testSetTypeRefSeq, + testSetTypeRefSet, + testSetOf, + testSetOfCho, + testEnumExt, + value_test, + value_bad_enum_test, + testSeq2738, + % Uses 'Constructed' + {group, [], [constructed, + ber_decode_error]}, + % Uses 'SeqSetIndefinite' + {group, [], [testSeqIndefinite, + testSetIndefinite]}, + testChoiceIndefinite, + per_open_type, + testInfObjectClass, + testParameterizedInfObj, + testMergeCompile, + testobj, + testDeepTConstr, + testExport, + testImport, + % Uses 'ParamBasic' + {group, [], [testParamBasic, + testDER]}, + testMvrasn6, + testContextSwitchingTypes, + testOpenTypeImplicitTag, + duplicate_tags, + testROSE, + testINSTANCE_OF, + testTCAP, + test_ParamTypeInfObj, + test_WS_ParamClass, + test_Defed_ObjectIdentifier, + testSelectionType, + testSSLspecs, + testNortel, + % Uses 'PKCS7' + {group, [], [test_modified_x420, + testX420]}, + testTcapsystem, + testNBAPsystem, + test_compile_options, + testDoubleEllipses, + test_x691, + ticket_6143, + testExtensionAdditionGroup, + test_OTP_9688]}, + + {performance, [], + [testTimer_ber, + testTimer_ber_bin, + testTimer_ber_bin_opt, + testTimer_ber_bin_opt_driver, + testTimer_per, + testTimer_per_bin, + testTimer_per_bin_opt, + testTimer_uper_bin, + smp]}]. + +parallel(Options) -> + case erlang:system_info(smp_support) andalso + erlang:system_info(schedulers) > 1 of + true -> [parallel|Options]; + false -> Options + end. + +%%------------------------------------------------------------------------------ +%% Init/end +%%------------------------------------------------------------------------------ + +init_per_suite(Config) -> + PrivDir = ?config(priv_dir, Config), + true = code:add_patha(PrivDir), + Config. + +end_per_suite(_Config) -> + ok. + +init_per_group(_GroupName, Config) -> + Config. + +end_per_group(_GroupName, Config) -> + Config. + +init_per_testcase(Func, Config) -> + CaseDir = filename:join([?config(priv_dir, Config), ?MODULE, Func]), + ok = filelib:ensure_dir(filename:join([CaseDir, dummy_file])), + true = code:add_patha(CaseDir), + + Dog = case Func of + testX420 -> test_server:timetrap({minutes, 90}); + _ -> test_server:timetrap({minutes, 60}) + end, + [{case_dir, CaseDir}, {watchdog, Dog}|Config]. + +end_per_testcase(_Func, Config) -> + true = code:del_path(?config(case_dir, Config)), + test_server:timetrap_cancel(?config(watchdog, Config)). + +%%------------------------------------------------------------------------------ +%% Test runners +%%------------------------------------------------------------------------------ + +test(Config, TestF) -> + test(Config, TestF, [per, + per_bin, + {per_bin, [optimize]}, + uper_bin, + ber, + ber_bin, + ber_bin_v2, + % TODO: {ber_bin_v2, [optimize, nif]} ? + {ber_bin_v2, [nif]}]). + +test(Config, TestF, Rules) -> + Fun = fun(C, R, O) -> + M = element(2, erlang:fun_info(TestF, module)), + F = element(2, erlang:fun_info(TestF, name)), + io:format("Running ~p:~p with ~p...~n", [M, F, {R, O}]), + try + TestF(C, R, O) + catch + Class:Reason -> + NewReason = {Reason, [{rule, R}, {options, O}]}, + erlang:raise(Class, NewReason, + erlang:get_stacktrace()) + end + end, + Result = [run_case(Config, Fun, rule(Rule), opts(Rule)) || Rule <- Rules], + case lists:usort(Result) of + [true|_Skips] -> true; % At least one test ran + Skips -> {skip, [R || {skip, R} <- Skips]} % All skipped + end. + +rule(A) when is_atom(A) -> A; +rule({A, _Opts} ) -> A. + +opts(Rule) when is_atom(Rule) -> []; +opts({_Rule, Opts}) -> Opts. + +run_case(Config, Fun, Rule, Opts) -> + CaseDir = ?config(case_dir, Config), + Dir = filename:join([CaseDir, join(Rule, Opts)]), + ok = filelib:ensure_dir(filename:join([Dir, dummy_file])), + replace_path(CaseDir, Dir), + NewConfig = lists:keyreplace(case_dir, 1, Config, {case_dir, Dir}), + + % Run the actual test function + Result = Fun(NewConfig, Rule, Opts), + + replace_path(Dir, CaseDir), + case Result of + {skip, _Reason} -> Result; + _ -> true + end. + +replace_path(PathA, PathB) -> + true = code:del_path(PathA), + true = code:add_patha(PathB). + +join(Rule, Opts) -> + string:join([atom_to_list(Rule)|lists:map(fun atom_to_list/1, Opts)], "_"). + +case_dir([], _Dir) -> + exit(no_case_dir); +case_dir([{case_dir, _}|Config], Dir) -> + [{case_dir, Dir}|Config]; +case_dir([C|Config], Opt) -> + [C|case_dir(Config, Opt)]. + +%%------------------------------------------------------------------------------ +%% Test cases +%%------------------------------------------------------------------------------ + +testPrim(Config) -> test(Config, fun testPrim/3). +testPrim(Config, Rule, Opts) -> + asn1_test_lib:compile_all(["Prim", "Real"], Config, [Rule|Opts]), + testPrim:bool(Rule), + testPrim:int(Rule), + testPrim:enum(Rule), + testPrim:obj_id(Rule), + testPrim:rel_oid(Rule), + testPrim:null(Rule), + testPrim:real(Rule). + +testCompactBitString(Config) -> test(Config, fun testCompactBitString/3). +testCompactBitString(Config, Rule, Opts) -> + asn1_test_lib:compile("PrimStrings", Config, + [Rule, compact_bit_string|Opts]), + testCompactBitString:compact_bit_string(Rule), + ?only_uper(testCompactBitString:bit_string_unnamed(Rule)), + ?only_per(testCompactBitString:bit_string_unnamed(Rule)), + ?only_per_nif(testCompactBitString:ticket_7734(Rule)), + ?only_per_nif(asn1_test_lib:compile("Constraints", Config, + [Rule, compact_bit_string|Opts])), + ?only_per_nif(testCompactBitString:otp_4869(Rule)). + +testPrimStrings(Config) -> test(Config, fun testPrimStrings/3). +testPrimStrings(Config, Rule, Opts) -> + asn1_test_lib:compile_all(["PrimStrings", "BitStr"], Config, [Rule|Opts]), + testPrimStrings_cases(Rule), + ?only_ber(testPrimStrings:more_strings(Rule)). + +testPrimStrings_cases(Rule) -> + testPrimStrings:bit_string(Rule), + testPrimStrings:bit_string_unnamed(Rule), + testPrimStrings:octet_string(Rule), + testPrimStrings:numeric_string(Rule), + testPrimStrings:other_strings(Rule), + testPrimStrings:universal_string(Rule), + testPrimStrings:bmp_string(Rule), + testPrimStrings:times(Rule), + testPrimStrings:utf8_string(Rule). + +testPrimExternal(Config) -> test(Config, fun testPrimExternal/3). +testPrimExternal(Config, Rule, Opts) -> + asn1_test_lib:compile_all(["External", "PrimExternal"], Config, + [Rule|Opts]), + testPrimExternal:external(Rule), + ?only_ber_nif(asn1_test_lib:compile_all(["PrimStrings", "BitStr"], Config, + [Rule|Opts])), + ?only_ber_nif(testPrimStrings_cases(Rule)), + ?only_ber_nif(testPrimStrings:more_strings(Rule)). + +testChoPrim(Config) -> test(Config, fun testChoPrim/3). +testChoPrim(Config, Rule, Opts) -> + asn1_test_lib:compile("ChoPrim", Config, [Rule|Opts]), + testChoPrim:bool(Rule), + testChoPrim:int(Rule). + +testChoExtension(Config) -> test(Config, fun testChoExtension/3). +testChoExtension(Config, Rule, Opts) -> + asn1_test_lib:compile("ChoExtension", Config, [Rule|Opts]), + testChoExtension:extension(Rule). + +testChoExternal(Config) -> test(Config, fun testChoExternal/3). +testChoExternal(Config, Rule, Opts) -> + asn1_test_lib:compile_all(["External", "ChoExternal"], Config, [Rule|Opts]), + testChoExternal:external(Rule). + +testChoOptional(Config) -> test(Config, fun testChoOptional/3). +testChoOptional(Config, Rule, Opts) -> + asn1_test_lib:compile("ChoOptional", Config, [Rule|Opts]), + testChoOptional:optional(Rule). + +testChoOptionalImplicitTag(Config) -> + test(Config, fun testChoOptionalImplicitTag/3, + [ber, ber_bin, ber_bin_v2]). +testChoOptionalImplicitTag(Config, Rule, Opts) -> + %% Only meaningful for ber & co + asn1_test_lib:compile("ChoOptionalImplicitTag", Config, [Rule|Opts]), + testChoOptionalImplicitTag:optional(Rule). + +testChoRecursive(Config) -> test(Config, fun testChoRecursive/3). +testChoRecursive(Config, Rule, Opts) -> + asn1_test_lib:compile("ChoRecursive", Config, [Rule|Opts]), + testChoRecursive:recursive(Rule). + +testChoTypeRefCho(Config) -> test(Config, fun testChoTypeRefCho/3). +testChoTypeRefCho(Config, Rule, Opts) -> + asn1_test_lib:compile("ChoTypeRefCho", Config, [Rule|Opts]), + testChoTypeRefCho:choice(Rule). + +testChoTypeRefPrim(Config) -> test(Config, fun testChoTypeRefPrim/3). +testChoTypeRefPrim(Config, Rule, Opts) -> + asn1_test_lib:compile("ChoTypeRefPrim", Config, [Rule|Opts]), + testChoTypeRefPrim:prim(Rule). + +testChoTypeRefSeq(Config) -> test(Config, fun testChoTypeRefSeq/3). +testChoTypeRefSeq(Config, Rule, Opts) -> + asn1_test_lib:compile("ChoTypeRefSeq", Config, [Rule|Opts]), + testChoTypeRefSeq:seq(Rule). + +testChoTypeRefSet(Config) -> test(Config, fun testChoTypeRefSet/3). +testChoTypeRefSet(Config, Rule, Opts) -> + asn1_test_lib:compile("ChoTypeRefSet", Config, [Rule|Opts]), + testChoTypeRefSet:set(Rule). + +testDef(Config) -> test(Config, fun testDef/3). +testDef(Config, Rule, Opts) -> + asn1_test_lib:compile("Def", Config, [Rule|Opts]), + testDef:main(Rule). + +testOpt(Config) -> test(Config, fun testOpt/3). +testOpt(Config, Rule, Opts) -> + asn1_test_lib:compile("Opt", Config, [Rule|Opts]), + testOpt:main(Rule). + +testEnumExt(Config) -> test(Config, fun testEnumExt/3). +testEnumExt(Config, Rule, Opts) -> + asn1_test_lib:compile("EnumExt", Config, [Rule|Opts]), + testEnumExt:main(Rule). + +%% Test of OTP-2523 ENUMERATED with extensionmark. +testSeqDefault(Config) -> test(Config, fun testSeqDefault/3). +testSeqDefault(Config, Rule, Opts) -> + asn1_test_lib:compile("SeqDefault", Config, [Rule|Opts]), + testSeqDefault:main(Rule). + +testSeqExtension(Config) -> test(Config, fun testSeqExtension/3). +testSeqExtension(Config, Rule, Opts) -> + asn1_test_lib:compile_all(["External", "SeqExtension"], Config, + [Rule|Opts]), + testSeqExtension:main(Rule). + +testSeqExternal(Config) -> test(Config, fun testSeqExternal/3). +testSeqExternal(Config, Rule, Opts) -> + asn1_test_lib:compile_all(["External", "SeqExternal"], Config, [Rule|Opts]), + testSeqExternal:main(Rule). + +testSeqOptional(Config) -> test(Config, fun testSeqOptional/3). +testSeqOptional(Config, Rule, Opts) -> + asn1_test_lib:compile("SeqOptional", Config, [Rule|Opts]), + testSeqOptional:main(Rule). + +testSeqPrim(Config) -> test(Config, fun testSeqPrim/3). +testSeqPrim(Config, Rule, Opts) -> + asn1_test_lib:compile("SeqPrim", Config, [Rule|Opts]), + testSeqPrim:main(Rule). + +%% Test of OTP-2738 Detect corrupt optional component. +testSeq2738(Config) -> test(Config, fun testSeq2738/3). +testSeq2738(Config, Rule, Opts) -> + asn1_test_lib:compile("Seq2738", Config, [Rule|Opts]), + testSeq2738:main(Rule). + +testSeqTag(Config) -> test(Config, fun testSeqTag/3). +testSeqTag(Config, Rule, Opts) -> + asn1_test_lib:compile_all(["External", "SeqTag"], Config, [Rule|Opts]), + testSeqTag:main(Rule). + +testSeqTypeRefCho(Config) -> test(Config, fun testSeqTypeRefCho/3). +testSeqTypeRefCho(Config, Rule, Opts) -> + asn1_test_lib:compile("SeqTypeRefCho", Config, [Rule|Opts]), + testSeqTypeRefCho:main(Rule). + +testSeqTypeRefPrim(Config) -> test(Config, fun testSeqTypeRefPrim/3). +testSeqTypeRefPrim(Config, Rule, Opts) -> + asn1_test_lib:compile("SeqTypeRefPrim", Config, [Rule|Opts]), + testSeqTypeRefPrim:main(Rule). + +testSeqTypeRefSeq(Config) -> test(Config, fun testSeqTypeRefSeq/3). +testSeqTypeRefSeq(Config, Rule, Opts) -> + asn1_test_lib:compile("SeqTypeRefSeq", Config, [Rule|Opts]), + testSeqTypeRefSeq:main(Rule). + +testSeqTypeRefSet(Config) -> test(Config, fun testSeqTypeRefSet/3). +testSeqTypeRefSet(Config, Rule, Opts) -> + asn1_test_lib:compile("SeqTypeRefSet", Config, [Rule|Opts]), + testSeqTypeRefSet:main(Rule). + +testSeqOf(Config) -> test(Config, fun testSeqOf/3). +testSeqOf(Config, Rule, Opts) -> + asn1_test_lib:compile_all(["SeqOf", "SeqOfEnum", "XSeqOf"], Config, + [Rule|Opts]), + testSeqOf:main(Rule). + +testSeqOfCho(Config) -> test(Config, fun testSeqOfCho/3). +testSeqOfCho(Config, Rule, Opts) -> + asn1_test_lib:compile("SeqOfCho", Config, [Rule|Opts]), + testSeqOfCho:main(Rule). + +testSeqOfIndefinite(Config) -> + test(Config, fun testSeqOfIndefinite/3, + [ber, ber_bin, ber_bin_v2, {ber_bin_v2, [nif]}]). +testSeqOfIndefinite(Config, Rule, Opts) -> + Files = ["Mvrasn-Constants-1", "Mvrasn-DataTypes-1", "Mvrasn-21-4", + "Mvrasn-20-4", "Mvrasn-19-4", "Mvrasn-18-4", "Mvrasn-17-4", + "Mvrasn-15-4", "Mvrasn-14-4", "Mvrasn-11-4", "SeqOf"], + asn1_test_lib:compile_all(Files, Config, [Rule|Opts]), + testSeqOfIndefinite:main(). + +testSeqOfExternal(Config) -> test(Config, fun testSeqOfExternal/3). +testSeqOfExternal(Config, Rule, Opts) -> + asn1_test_lib:compile_all(["External", "SeqOfExternal"], Config, + [Rule|Opts]), + testSeqOfExternal:main(Rule). + +testSeqOfTag(Config) -> test(Config, fun testSeqOfTag/3). +testSeqOfTag(Config, Rule, Opts) -> + asn1_test_lib:compile_all(["External", "SeqOfTag"], Config, [Rule|Opts]), + testSeqOfTag:main(Rule). + +testSetDefault(Config) -> test(Config, fun testSetDefault/3). +testSetDefault(Config, Rule, Opts) -> + asn1_test_lib:compile("SetDefault", Config, [Rule|Opts]), + testSetDefault:main(Rule). + +testParamBasic(Config) -> test(Config, fun testParamBasic/3). +testParamBasic(Config, Rule, Opts) -> + asn1_test_lib:compile("ParamBasic", Config, [Rule|Opts]), + testParamBasic:main(Rule). + +testSetExtension(Config) -> test(Config, fun testSetExtension/3). +testSetExtension(Config, Rule, Opts) -> + asn1_test_lib:compile_all(["External", "SetExtension"], Config, + [Rule|Opts]), + testSetExtension:main(Rule). + +testSetExternal(Config) -> test(Config, fun testSetExternal/3). +testSetExternal(Config, Rule, Opts) -> + asn1_test_lib:compile_all(["External", "SetExternal"], Config, [Rule|Opts]), + testSetExternal:main(Rule). + +testSetOptional(Config) -> test(Config, fun testSetOptional/3). +testSetOptional(Config, Rule, Opts) -> + asn1_test_lib:compile("SetOptional", Config, [Rule|Opts]), + testSetOptional:ticket_7533(Rule), + testSetOptional:main(Rule). + +testSetPrim(Config) -> test(Config, fun testSetPrim/3). +testSetPrim(Config, Rule, Opts) -> + asn1_test_lib:compile("SetPrim", Config, [Rule|Opts]), + testSetPrim:main(Rule). + +testSetTag(Config) -> test(Config, fun testSetTag/3). +testSetTag(Config, Rule, Opts) -> + asn1_test_lib:compile_all(["External", "SetTag"], Config, [Rule|Opts]), + testSetTag:main(Rule). + +testSetTypeRefCho(Config) -> test(Config, fun testSetTypeRefCho/3). +testSetTypeRefCho(Config, Rule, Opts) -> + asn1_test_lib:compile("SetTypeRefCho", Config, [Rule|Opts]), + testSetTypeRefCho:main(Rule). + +testSetTypeRefPrim(Config) -> test(Config, fun testSetTypeRefPrim/3). +testSetTypeRefPrim(Config, Rule, Opts) -> + asn1_test_lib:compile("SetTypeRefPrim", Config, [Rule|Opts]), + testSetTypeRefPrim:main(Rule). + +testSetTypeRefSeq(Config) -> test(Config, fun testSetTypeRefSeq/3). +testSetTypeRefSeq(Config, Rule, Opts) -> + asn1_test_lib:compile("SetTypeRefSeq", Config, [Rule|Opts]), + testSetTypeRefSeq:main(Rule). + +testSetTypeRefSet(Config) -> test(Config, fun testSetTypeRefSet/3). +testSetTypeRefSet(Config, Rule, Opts) -> + asn1_test_lib:compile("SetTypeRefSet", Config, [Rule|Opts]), + testSetTypeRefSet:main(Rule). + +testSetOf(Config) -> test(Config, fun testSetOf/3). +testSetOf(Config, Rule, Opts) -> + asn1_test_lib:compile("SetOf", Config, [Rule|Opts]), + testSetOf:main(Rule). + +testSetOfCho(Config) -> test(Config, fun testSetOfCho/3). +testSetOfCho(Config, Rule, Opts) -> + asn1_test_lib:compile("SetOfCho", Config, [Rule|Opts]), + testSetOfCho:main(Rule). + +testSetOfExternal(Config) -> test(Config, fun testSetOfExternal/3). +testSetOfExternal(Config, Rule, Opts) -> + asn1_test_lib:compile_all(["External", "SetOfExternal"], Config, + [Rule|Opts]), + testSetOfExternal:main(Rule). + +testSetOfTag(Config) -> test(Config, fun testSetOfTag/3). +testSetOfTag(Config, Rule, Opts) -> + asn1_test_lib:compile_all(["External", "SetOfTag"], Config, [Rule|Opts]), + testSetOfTag:main(Rule). + +c_syntax(Config) -> + DataDir = ?config(data_dir, Config), + [{error, _} = asn1ct:compile(filename:join(DataDir, F)) + || F <-["Syntax", + "BadTypeEnding", + "BadValueAssignment1", + "BadValueAssignment2", + "BadValueSet", + "ChoiceBadExtension", + "EnumerationBadExtension", + "Example", + "Export1", + "MissingEnd", + "SequenceBadComma", + "SequenceBadComponentName", + "SequenceBadComponentType", + "SeqBadComma"]]. + +c_string(Config) -> + test(Config, fun c_string/3, [per, per_bin, ber, ber_bin, ber_bin_v2]). +c_string(Config, Rule, Opts) -> + asn1_test_lib:compile("String", Config, [Rule|Opts]). + +c_implicit_before_choice(Config) -> + test(Config, fun c_implicit_before_choice/3, + [ber, ber_bin, ber_bin_v2]). +c_implicit_before_choice(Config, Rule, Opts) -> + DataDir = ?config(data_dir, Config), + CaseDir = ?config(case_dir, Config), + {error, _R2} = asn1ct:compile(filename:join(DataDir, "CCSNARG3"), + [Rule, {outdir, CaseDir}|Opts]). + +parse(Config) -> + [asn1_test_lib:compile(M, Config, [abs]) || M <- test_modules()]. + +per(Config) -> + test(Config, fun per/3, [per, per_bin, {per_bin, [optimize]}]). +per(Config, Rule, Opts) -> + [module_test(M, Config, Rule, Opts) || M <- per_modules()]. + +ber_other(Config) -> + test(Config, fun ber_other/3, [ber, ber_bin, ber_bin_v2]). +ber_other(Config, Rule, Opts) -> + [module_test(M, Config, Rule, Opts) || M <- ber_modules()]. + + +module_test(M, Config, Rule, Opts) -> + asn1_test_lib:compile(M, Config, [Rule|Opts]), + case asn1ct:test(list_to_atom(M), [{i, ?config(case_dir, Config)}]) of + ok -> ok; + Error -> + erlang:error({test_failed, M, Opts, Error}) + end. + + +ber_choiceinseq(Config) -> + test(Config, fun ber_choiceinseq/3, [ber, ber_bin, ber_bin_v2]). +ber_choiceinseq(Config, Rule, Opts) -> + asn1_test_lib:compile("ChoiceInSeq", Config, [Rule|Opts]). + +ber_optional(Config) -> + test(Config, fun ber_optional/3, [ber, ber_bin, ber_bin_v2]). +ber_optional(Config, Rule, Opts) -> + asn1_test_lib:compile("SOpttest", Config, [Rule|Opts]), + V = {'S', {'A', 10, asn1_NOVALUE, asn1_NOVALUE}, + {'B', asn1_NOVALUE, asn1_NOVALUE, asn1_NOVALUE}, + {'C', asn1_NOVALUE, 111, asn1_NOVALUE}}, + {ok, B} = asn1_wrapper:encode('SOpttest', 'S', V), + Bytes = lists:flatten(B), + V2 = asn1_wrapper:decode('SOpttest', 'S', Bytes), + V = element(2, V2). + +ber_optional_keyed_list(Config) -> + test(Config, fun ber_optional_keyed_list/3, [ber, ber_bin]). +ber_optional_keyed_list(Config, Rule, Opts) -> + asn1_test_lib:compile("SOpttest", Config, [Rule, keyed_list|Opts]), + Vrecord = {'S', {'A', 10, asn1_NOVALUE, asn1_NOVALUE}, + {'B', asn1_NOVALUE, asn1_NOVALUE, asn1_NOVALUE}, + {'C', asn1_NOVALUE, 111, asn1_NOVALUE}}, + V = [{a, [{scriptKey, 10}]}, + {b, []}, + {c, [{callingPartysCategory, 111}]}], + {ok, B} = asn1_wrapper:encode('SOpttest', 'S', V), + Bytes = lists:flatten(B), + V2 = asn1_wrapper:decode('SOpttest', 'S', Bytes), + Vrecord = element(2, V2). + +%% records used by test-case default +-record('Def1', {bool0, + bool1 = asn1_DEFAULT, + bool2 = asn1_DEFAULT, + bool3 = asn1_DEFAULT}). + +default(Config) -> test(Config, fun default/3). +default(Config, Rule, Opts) -> + asn1_test_lib:compile("Def", Config, [Rule|Opts]), + {ok, Bytes1} = asn1_wrapper:encode('Def', 'Def1', #'Def1'{bool0 = true}), + {ok, {'Def1', true, false, false, false}} = + asn1_wrapper:decode('Def', 'Def1', lists:flatten(Bytes1)), + + {ok, Bytes2} = asn1_wrapper:encode('Def', 'Def1', #'Def1'{bool0 = true, + bool2 = false}), + {ok, {'Def1', true, false, false, false}} = + asn1_wrapper:decode('Def', 'Def1', lists:flatten(Bytes2)). + +value_test(Config) -> test(Config, fun value_test/3). +value_test(Config, Rule, Opts) -> + asn1_test_lib:compile("ObjIdValues", Config, [Rule|Opts]), + {ok, _} = asn1ct:test('ObjIdValues', 'ObjIdType', + 'ObjIdValues':'mobileDomainId'()). + +value_bad_enum_test(Config) -> + case ?MODULE of + asn1_SUITE -> + {error, _} = asn1ct:compile(?config(data_dir, Config) + ++ "BadEnumValue1", + [{outdir, ?config(case_dir, Config)}]); + _ -> {skip, "Runs in asn1_SUITE only"} + end. + +constructed(Config) -> + test(Config, fun constructed/3, [ber, ber_bin, ber_bin_v2]). +constructed(Config, Rule, Opts) -> + asn1_test_lib:compile("Constructed", Config, [Rule|Opts]), + {ok, B} = asn1_wrapper:encode('Constructed', 'S', {'S', false}), + [40, 3, 1, 1, 0] = lists:flatten(B), + {ok, B1} = asn1_wrapper:encode('Constructed', 'S2', {'S2', false}), + [40, 5, 48, 3, 1, 1, 0] = lists:flatten(B1), + {ok, B2} = asn1_wrapper:encode('Constructed', 'I', 10), + [136, 1, 10] = lists:flatten(B2). + +ber_decode_error(Config) -> + test(Config, fun ber_decode_error/3, [ber, ber_bin, ber_bin_v2]). +ber_decode_error(Config, Rule, Opts) -> + asn1_test_lib:compile("Constructed", Config, [Rule|Opts]), + ber_decode_error:run(Opts). + +h323test(Config) -> test(Config, fun h323test/3). +h323test(Config, Rule, Opts) -> + Files = ["H235-SECURITY-MESSAGES", "H323-MESSAGES", + "MULTIMEDIA-SYSTEM-CONTROL"], + asn1_test_lib:compile_all(Files, Config, [Rule|Opts]), + h323test:run(Rule). + +per_GeneralString(Config) -> + test(Config, fun per_GeneralString/3, [per, per_bin]). +per_GeneralString(Config, Rule, Opts) -> + asn1_test_lib:compile("MULTIMEDIA-SYSTEM-CONTROL", Config, [Rule|Opts]), + UI = [109, 64, 1, 57], + {ok, _V} = asn1_wrapper:decode('MULTIMEDIA-SYSTEM-CONTROL', + 'MultimediaSystemControlMessage', UI). + +per_open_type(Config) -> test(Config, fun per_open_type/3, [per, per_bin]). +per_open_type(Config, Rule, Opts) -> + asn1_test_lib:compile("OpenType", Config, [Rule|Opts]), + {ok, _} = asn1ct:test('OpenType', 'Ot', {'Stype', 10, true}). + +testConstraints(Config) -> test(Config, fun testConstraints/3). +testConstraints(Config, Rule, Opts) -> + asn1_test_lib:compile("Constraints", Config, [Rule|Opts]), + testConstraints:int_constraints(Rule). + + +testSeqIndefinite(Config) -> + test(Config, fun testSeqIndefinite/3, [ber, ber_bin, ber_bin_v2, + {ber_bin_v2, [nif]}]). +testSeqIndefinite(Config, Rule, Opts) -> + asn1_test_lib:compile("SeqSetIndefinite", Config, [Rule|Opts]), + testSeqIndefinite:main(Rule). + + +testSetIndefinite(Config) -> + test(Config, fun testSetIndefinite/3, [ber, ber_bin, ber_bin_v2, + {ber_bin_v2, [nif]}]). +testSetIndefinite(Config, Rule, Opts) -> + asn1_test_lib:compile("SeqSetIndefinite", Config, [Rule|Opts]), + testSetIndefinite:main(Rule). + + +testChoiceIndefinite(Config) -> + test(Config, fun testChoiceIndefinite/3, [ber, ber_bin, ber_bin_v2, + {ber_bin_v2, [nif]}]). +testChoiceIndefinite(Config, Rule, Opts) -> + asn1_test_lib:compile("ChoiceIndef", Config, [Rule|Opts]), + testChoiceIndefinite:main(Rule). + +testInfObjectClass(Config) -> test(Config, fun testInfObjectClass/3). +testInfObjectClass(Config, Rule, Opts) -> + Files = ["ErrorClass", "InfClass"], + InfObjFiles = ["RANAPextract1", "InfObj", "MAP-ExtensionDataTypes", + "Objects", "INAPv2extract"], + RANAPFiles = ["RANAP-CommonDataTypes", "RANAP-Constants", + "RANAP-Containers", "RANAP-IEs", "RANAP-PDU-Contents", + "RANAP-PDU-Descriptions"], + asn1_test_lib:compile_all(Files ++ InfObjFiles ++ RANAPFiles, Config, + [Rule|Opts]), + testInfObjectClass:main(Rule), + testInfObj:main(Rule). + +testParameterizedInfObj(Config) -> + test(Config, fun testParameterizedInfObj/3). +testParameterizedInfObj(Config, Rule, Opts) -> + asn1_test_lib:compile("Param", Config, [Rule|Opts]), + testParameterizedInfObj:main(Rule). + +testMergeCompile(Config) -> test(Config, fun testMergeCompile/3). +testMergeCompile(Config, Rule, Opts) -> + Files = ["MS.set.asn", "RANAPSET.set.asn1", "Mvrasn4.set.asn", + "Mvrasn6.set.asn"], + asn1_test_lib:compile_all(Files, Config, [Rule|Opts]), + testMergeCompile:main(Rule), + testMergeCompile:mvrasn(Rule). + +testobj(Config) -> test(Config, fun testobj/3). +testobj(Config, Rule, Opts) -> + asn1_test_lib:compile("RANAP", Config, [Rule|Opts]), + asn1_test_lib:compile_erlang("testobj", Config, []), + ok = testobj:run(), + ok = testParameterizedInfObj:ranap(Rule). + +testDeepTConstr(Config) -> test(Config, fun testDeepTConstr/3). +testDeepTConstr(Config, Rule, Opts) -> + asn1_test_lib:compile_all(["TConstrChoice", "TConstr"], Config, + [Rule|Opts]), + testDeepTConstr:main(Rule). + +testInvokeMod(Config) -> test(Config, fun testInvokeMod/3). +testInvokeMod(Config, Rule, Opts) -> + asn1_test_lib:compile("PrimStrings", Config, [Rule|Opts]), + {ok, _Result2} = 'PrimStrings':encode('Bs1', [1, 0, 1, 0]). + +testExport(Config) -> + case ?MODULE of + asn1_SUITE -> + {error, {asn1, _Reason}} = + asn1ct:compile(filename:join(?config(data_dir, Config), + "IllegalExport"), + [{outdir, ?config(case_dir, Config)}]); + _ -> + {skip, "Runs in asn1_SUITE only"} + end. + +testImport(Config) -> + test(Config, fun testImport/3, [ber, ber_bin, ber_bin_v2]). +testImport(Config, Rule, Opts) -> + {error, _} = asn1ct:compile(filename:join(?config(data_dir, Config), + "ImportsFrom"), + [Rule, {outdir, ?config(priv_dir, Config)} + |Opts]). + +testMegaco(Config) -> test(Config, fun testMegaco/3). +testMegaco(Config, Rule, Opts) -> + {ok, Module1, Module2} = testMegaco:compile(Config, Rule, Opts), + ok = testMegaco:main(Module1, Config), + ok = testMegaco:main(Module2, Config). + +testMvrasn6(Config) -> test(Config, fun testMvrasn6/3). +testMvrasn6(Config, Rule, Opts) -> + asn1_test_lib:compile_all(["Mvrasn-21-4", "Mvrasn-20-6", "Mvrasn-19-6", + "Mvrasn-15-6", "Mvrasn-18-6", "Mvrasn-14-6", + "Mvrasn-11-6"], Config, [Rule|Opts]). + +testContextSwitchingTypes(Config) -> + test(Config, fun testContextSwitchingTypes/3). +testContextSwitchingTypes(Config, Rule, Opts) -> + asn1_test_lib:compile("ContextSwitchingTypes", Config, [Rule|Opts]), + testContextSwitchingTypes:test(Config). + +testTypeValueNotation(Config) -> test(Config, fun testTypeValueNotation/3). +testTypeValueNotation(Config, Rule, Opts) -> + asn1_test_lib:compile_all(["SeqTypeRefPrim", "ValueTest"], Config, + [Rule|Opts]), + testTypeValueNotation:main(Rule, Opts). + +testOpenTypeImplicitTag(Config) -> + test(Config, fun testOpenTypeImplicitTag/3). +testOpenTypeImplicitTag(Config, Rule, Opts) -> + asn1_test_lib:compile("OpenTypeImplicitTag", Config, [Rule|Opts]), + testOpenTypeImplicitTag:main(Rule). + +duplicate_tags(Config) -> + case ?MODULE of + asn1_SUITE -> + DataDir = ?config(data_dir, Config), + CaseDir = ?config(case_dir, Config), + {error, {asn1, [{error, {type, _, _, 'SeqOpt1Imp', {asn1, {duplicates_of_the_tags, _}}}}]}} = + asn1ct:compile(filename:join(DataDir, "SeqOptional2"), + [abs, {outdir, CaseDir}]); + _ -> + {skip, "Runs in asn1_SUITE only"} + end. + +rtUI(Config) -> test(Config, fun rtUI/3, [per, per_bin, ber, + ber_bin, ber_bin_v2]). +rtUI(Config, Rule, Opts) -> + asn1_test_lib:compile("Prim", Config, [Rule|Opts]), + {ok, _} = asn1rt:info('Prim'). + +testROSE(Config) -> test(Config, fun testROSE/3). +testROSE(Config, Rule, Opts) -> + asn1_test_lib:compile("Remote-Operations-Merged.set.asn1", Config, + [Rule|Opts]). + +testINSTANCE_OF(Config) -> test(Config, fun testINSTANCE_OF/3). +testINSTANCE_OF(Config, Rule, Opts) -> + asn1_test_lib:compile("INSTANCEOF.asn1", Config, [Rule|Opts]), + testINSTANCE_OF:main(Rule). + +testTCAP(Config) -> + test(Config, fun testTCAP/3, + [ber, ber_bin, ber_bin_v2, {ber_bin_v2, [nif]}]). +testTCAP(Config, Rule, Opts) -> + testTCAP:compile(Config, [Rule|Opts]), + testTCAP:test(Rule, Config), + case Rule of + ber_bin_v2 -> testTCAP:compile_asn1config(Config, [Rule, asn1config]), + testTCAP:test_asn1config(); + _ -> ok + end. + +testDER(Config) -> + test(Config, fun testDER/3, [ber, ber_bin, ber_bin_v2]). +testDER(Config, Rule, Opts) -> + asn1_test_lib:compile("DERSpec", Config, [Rule, der|Opts]), + testDER:test(), + asn1_test_lib:compile("ParamBasic", Config, [Rule, der|Opts]), + testParamBasic:main(der), + asn1_test_lib:compile("Default", Config, [Rule, der|Opts]), + testSeqSetDefaultVal:main(Rule). + +specialized_decodes(Config) -> + test(Config, fun specialized_decodes/3, [ber_bin_v2]). +specialized_decodes(Config, Rule, Opts) -> + asn1_test_lib:compile_all(["PartialDecSeq.asn", + "PartialDecSeq2.asn", + "PartialDecSeq3.asn", + "PartialDecMyHTTP.asn", + "MEDIA-GATEWAY-CONTROL.asn", + "P-Record"], + Config, [Rule, optimize, asn1config|Opts]), + test_partial_incomplete_decode:test(Config), + test_selective_decode:test(). + +special_decode_performance(Config) -> + test(Config, fun special_decode_performance/3, + [{ber_bin, [optimize]}, {ber_bin_v2, [optimize, nif]}]). +special_decode_performance(Config, Rule, Opts) -> + Files = ["MEDIA-GATEWAY-CONTROL", "PartialDecSeq"], + asn1_test_lib:compile_all(Files, Config, [Rule, asn1config|Opts]), + test_special_decode_performance:go(all). + + +test_driver_load(Config) -> + test(Config, fun test_driver_load/3, [{per_bin, [optimize]}]). +test_driver_load(Config, Rule, Opts) -> + asn1_test_lib:compile("P-Record", Config, [Rule|Opts]), + test_driver_load:test(5). + +test_ParamTypeInfObj(Config) -> + asn1_test_lib:compile("IN-CS-1-Datatypes", Config, [ber_bin]). + +test_WS_ParamClass(Config) -> + asn1_test_lib:compile("InformationFramework", Config, [ber_bin]). + +test_Defed_ObjectIdentifier(Config) -> + asn1_test_lib:compile("UsefulDefinitions", Config, [ber_bin]). + +testSelectionType(Config) -> test(Config, fun testSelectionType/3). +testSelectionType(Config, Rule, Opts) -> + asn1_test_lib:compile("SelectionType", Config, [Rule|Opts]), + {ok, _} = testSelectionTypes:test(). + +testSSLspecs(Config) -> + test(Config, fun testSSLspecs/3, [ber, ber_bin, ber_bin_v2, {ber_bin_v2, [optimize]}]). +testSSLspecs(Config, Rule, Opts) -> + ok = testSSLspecs:compile(Config, + [Rule, compact_bit_string, der|Opts]), + testSSLspecs:run(Rule), + + case code:which(asn1ct) of + cover_compiled -> + ok; + _ -> + ok = testSSLspecs:compile_inline(Config, Rule), + ok = testSSLspecs:run_inline(Rule) + end. + +testNortel(Config) -> test(Config, fun testNortel/3). +testNortel(Config, Rule, Opts) -> + asn1_test_lib:compile("Nortel", Config, [Rule|Opts]). + +test_undecoded_rest(Config) -> test(Config, fun test_undecoded_rest/3). +test_undecoded_rest(Config, Rule, Opts) -> + asn1_test_lib:compile("P-Record", Config, [Rule|Opts]), + ok = test_undecoded_rest:test([], Config), + asn1_test_lib:compile("P-Record", Config, [Rule,undec_rest|Opts]), + case Rule of + ber_bin_v2 -> ok; + _ -> test_undecoded_rest:test(undec_rest, Config) + end. + +test_inline(Config) -> + test(Config, fun test_inline/3, [ber, ber_bin, ber_bin_v2]). +test_inline(Config, Rule, Opts) -> + case code:which(asn1ct) of + cover_compiled -> + {skip, "Not runnable when cover compiled"}; + _ -> + test_inline:compile(Config, Opts), + test_inline:main(Config, Rule), + test_inline:inline1(Config, Rule, Opts), + test_inline:performance2() + end. + +testTcapsystem(Config) -> + test(Config, fun testTcapsystem/3, [ber, ber_bin, ber_bin_v2]). +testTcapsystem(Config, Rule, Opts) -> + testTcapsystem:compile(Config, [Rule|Opts]). + +testNBAPsystem(Config) -> test(Config, fun testNBAPsystem/3, + [per, per_bin, {per_bin, [optimize]}]). +testNBAPsystem(Config, Rule, Opts) -> + testNBAPsystem:compile(Config, [Rule|Opts]), + testNBAPsystem:test(Rule, Config). + +test_compile_options(Config) -> + case code:which(asn1ct) of + cover_compiled -> + {skip, "Not runnable when cover compiled"}; + _ -> + ok = test_compile_options:wrong_path(Config), + ok = test_compile_options:path(Config), + ok = test_compile_options:noobj(Config), + ok = test_compile_options:record_name_prefix(Config), + ok = test_compile_options:verbose(Config), + ok = test_compile_options:warnings_as_errors(Config) + end. + +testDoubleEllipses(Config) -> test(Config, fun testDoubleEllipses/3). +testDoubleEllipses(Config, Rule, Opts) -> + asn1_test_lib:compile("DoubleEllipses", Config, [Rule|Opts]), + testDoubleEllipses:main(Rule). + +test_modified_x420(Config) -> + Files = [filename:join(modified_x420, F) || F <- ["PKCS7", + "InformationFramework", + "AuthenticationFramework"]], + asn1_test_lib:compile_all(Files, Config, [der]), + test_modified_x420:test_io(Config). + +testX420(Config) -> + test(Config, fun testX420/3, [ber, ber_bin, ber_bin_v2]). +testX420(Config, Rule, Opts) -> + testX420:compile(Rule, [der|Opts], Config), + ok = testX420:ticket7759(Rule, Config), + testX420:compile(Rule, Opts, Config). + +test_x691(Config) -> + test(Config, fun test_x691/3, + [per, per_bin, uper_bin, {per_bin, [optimize]}]). +test_x691(Config, Rule, Opts) -> + Files = ["P-RecordA1", "P-RecordA2", "P-RecordA3"], + asn1_test_lib:compile_all(Files, Config, [Rule|Opts]), + test_x691:cases(Rule, case Rule of + uper_bin -> unaligned; + _ -> aligned + end), + asn1_test_lib:ticket_7708(Config, []), + asn1_test_lib:ticket_7763(Config). + +ticket_6143(Config) -> + ok = test_compile_options:ticket_6143(Config). + +testExtensionAdditionGroup(Config) -> + %% FIXME problems with automatic tags [ber_bin], [ber_bin, optimize] + test(Config, fun testExtensionAdditionGroup/3, + [per_bin, {per_bin, [optimize]}, uper_bin]). +testExtensionAdditionGroup(Config, Rule, Opts) -> + asn1_test_lib:compile("Extension-Addition-Group", Config, [Rule|Opts]), + asn1_test_lib:compile_erlang("extensionAdditionGroup", Config, + [debug_info]), + extensionAdditionGroup:run([Rule|Opts]), + extensionAdditionGroup:run2([Rule|Opts]), + asn1_test_lib:compile("EUTRA-RRC-Definitions", Config, [Rule, {record_name_prefix, "RRC-"}|Opts]), + extensionAdditionGroup:run3([Rule|Opts]). + +% parse_modules() -> +% ["ImportsFrom"]. + +per_modules() -> + [X || X <- test_modules()]. + +ber_modules() -> + [X || X <- test_modules(), + X =/= "CommonDataTypes", + X =/= "DS-EquipmentUser-CommonFunctionOrig-TransmissionPath", + X =/= "H323-MESSAGES", + X =/= "H235-SECURITY-MESSAGES", + X =/= "MULTIMEDIA-SYSTEM-CONTROL"]. + +test_modules() -> + ["BitStr", + "CAP", + "CommonDataTypes", + "Constraints", + "ContextSwitchingTypes", + "DS-EquipmentUser-CommonFunctionOrig-TransmissionPath", + "Enum", + "From", + "H235-SECURITY-MESSAGES", + "H323-MESSAGES", + "Import", + "Int", + "MAP-commonDataTypes", + "Null", + "Octetstr", + "One", + "P-Record", + "P", + "Person", + "PrimStrings", + "Real", + "XSeq", + "XSeqOf", + "XSet", + "XSetOf", + "String", + "SwCDR", + "Time", + "SeqSetLib", % must be compiled before Seq and Set + "Seq", + "Set", + "SetOf", + "SeqOf", + "Prim", + "Cho", + "Def", + "Opt", + "ELDAPv3", + "LDAP"]. + +test_OTP_9688(Config) -> + PrivDir = ?config(case_dir, Config), + Data = " +OTP-9688 DEFINITIONS ::= BEGIN + + foo INTEGER ::= 1 + bar INTEGER ::= 42 + + Baz ::= INTEGER {x-y-z1(foo), x-y-z2(bar)} + Qux ::= SEQUENCE {flerpInfo SEQUENCE {x INTEGER (-10 | -9 | (0..4))} OPTIONAL} + +END +", + File = filename:join(PrivDir, "OTP-9688.asn1"), + ok = file:write_file(File, Data), + %% Does it compile with changes to asn1ct_check and asn1ct_gen_per_rt2ct? + %% (see ticket) + ok = asn1ct:compile(File, [{outdir, PrivDir}]). + + +timer_compile(Config, Rule, Opts) -> + asn1_test_lib:compile_all(["H235-SECURITY-MESSAGES", "H323-MESSAGES"], + Config, [Rule|Opts]). + +testTimer_ber(suite) -> []; +testTimer_ber(Config) -> + timer_compile(Config,ber,[]), + testTimer:go(Config,ber). + +testTimer_ber_bin(suite) -> []; +testTimer_ber_bin(Config) -> + timer_compile(Config,ber_bin,[]), + testTimer:go(Config,ber_bin). + +testTimer_ber_bin_opt(suite) -> []; +testTimer_ber_bin_opt(Config) -> + timer_compile(Config,ber_bin,[optimize]), + testTimer:go(Config,ber_bin). + +testTimer_ber_bin_opt_driver(suite) -> []; +testTimer_ber_bin_opt_driver(Config) -> + timer_compile(Config,ber_bin,[optimize,driver]), + testTimer:go(Config,ber_bin). + +testTimer_per(suite) -> []; +testTimer_per(Config) -> + timer_compile(Config,per,[]), + testTimer:go(Config,per). + +testTimer_per_bin(suite) -> []; +testTimer_per_bin(Config) -> + timer_compile(Config,per_bin,[]), + testTimer:go(Config,per_bin). + +testTimer_per_bin_opt(suite) -> []; +testTimer_per_bin_opt(Config) -> + timer_compile(Config,per_bin,[optimize]), + testTimer:go(Config,per_bin). + + +testTimer_uper_bin(suite) -> []; +testTimer_uper_bin(Config) -> + timer_compile(Config,uper_bin,[]), + {comment,_} = testTimer:go(Config,uper_bin). + +%% Test of multiple-line comment, OTP-8043 +testComment(suite) -> []; +testComment(Config) -> + asn1_test_lib:compile("Comment", Config, []), + {ok,Enc} = asn1_wrapper:encode('Comment','Seq',{'Seq',12,true}), + {ok,{'Seq',12,true}} = asn1_wrapper:decode('Comment','Seq',Enc), + ok. + +testName2Number(suite) -> []; +testName2Number(Config) -> + N2NOptions = [{n2n,Type} || Type <- ['CauseMisc', 'CauseProtocol', + 'CauseRadioNetwork', + 'CauseTransport','CauseNas']], + asn1_test_lib:compile("S1AP-IEs", Config, N2NOptions), + + 0 = 'S1AP-IEs':name2num_CauseMisc('control-processing-overload'), + 'unknown-PLMN' = 'S1AP-IEs':num2name_CauseMisc(5), + ok. + +ticket_7407(Config) -> + asn1_test_lib:compile("EUTRA-extract-7407", Config, [uper_bin]), + asn1_test_lib:ticket_7407_code(true), + + asn1_test_lib:compile("EUTRA-extract-7407", Config, + [uper_bin, no_final_padding]), + asn1_test_lib:ticket_7407_code(false). + +smp(suite) -> []; +smp(Config) -> + case erlang:system_info(smp_support) of + true -> + NumOfProcs = erlang:system_info(schedulers), + io:format("smp starting ~p workers\n",[NumOfProcs]), + + Msg = {initiatingMessage, testNBAPsystem:cell_setup_req_msg()}, + ok = testNBAPsystem:compile(Config, [per_bin, optimize]), + + enc_dec(NumOfProcs,Msg,2), + + N = 10000, + + {Time1,ok} = timer:tc(?MODULE,enc_dec,[NumOfProcs,Msg, N]), + {Time1S,ok} = timer:tc(?MODULE,enc_dec,[1, Msg, NumOfProcs * N]), + + ok = testNBAPsystem:compile(Config, [ber_bin, optimize, nif]), + {Time3,ok} = timer:tc(?MODULE,enc_dec,[NumOfProcs,Msg, N]), + + {Time3S,ok} = timer:tc(?MODULE,enc_dec,[1, Msg, NumOfProcs * N]), + + {comment,lists:flatten( + io_lib:format( + "Encode/decode time parallell with ~p cores: ~p [microsecs]~n" + "Encode/decode time sequential: ~p [microsecs]", + [NumOfProcs,Time1+Time3,Time1S+Time3S]))}; + false -> + {skipped,"No smp support"} + end. + +per_performance(Config) -> + PrivDir = proplists:get_value(priv_dir, Config), + NifDir = filename:join(PrivDir,"nif"), + ErlDir = filename:join(PrivDir,"erl"), + file:make_dir(NifDir),file:make_dir(ErlDir), + + Msg = {initiatingMessage, testNBAPsystem:cell_setup_req_msg()}, + ok = testNBAPsystem:compile([{priv_dir,NifDir}|Config], + [per_bin, optimize]), + ok = testNBAPsystem:compile([{priv_dir,ErlDir}|Config], + [per_bin]), + + Modules = ['NBAP-CommonDataTypes', + 'NBAP-Constants', + 'NBAP-Containers', + 'NBAP-IEs', + 'NBAP-PDU-Contents', + 'NBAP-PDU-Discriptions'], + + + PreNif = fun() -> + code:add_patha(NifDir), + lists:foreach(fun(M) -> + code:purge(M), + code:load_file(M) + end,Modules) + end, + + PreErl = fun() -> + code:add_patha(ErlDir), + lists:foreach(fun(M) -> + code:purge(M), + code:load_file(M) + end,Modules) + end, + + Func = fun() -> + element(1,timer:tc( + asn1_wrapper,encode,['NBAP-PDU-Discriptions', + 'NBAP-PDU', + Msg])) + end, + + nif_vs_erlang_performance({{{PreNif,Func},{PreErl,Func}},100000,32}). + +ber_performance(Config) -> + + Msg = {initiatingMessage, testNBAPsystem:cell_setup_req_msg()}, + ok = testNBAPsystem:compile(Config, [ber_bin, optimize, nif]), + + + BerFun = fun() -> + {ok,B} = asn1_wrapper:encode('NBAP-PDU-Discriptions', + 'NBAP-PDU', Msg), + asn1_wrapper:decode( + 'NBAP-PDU-Discriptions', + 'NBAP-PDU', + B) + end, + nif_vs_erlang_performance({BerFun,100000,32}). + +cert_pem_performance(Config) when is_list(Config) -> + cert_pem_performance({100000, 32}); +cert_pem_performance({N,S}) -> + nif_vs_erlang_performance({fun pem_performance:cert_pem/0,N,S}). + +dsa_pem_performance(Config) when is_list(Config) -> + dsa_pem_performance({100000, 32}); +dsa_pem_performance({N,S}) -> + nif_vs_erlang_performance({fun pem_performance:dsa_pem/0,N,S}). + + +nif_vs_erlang_performance({{TC1,TC2},N,Sched}) -> + random:seed({123,456,789}), + io:format("Running a ~p sample with ~p max procs...~n~n",[N,Sched]), + + {True,False} = exec(TC1,TC2,Sched,N+1), + + io:format("~ndone!~n"), + + io:format("~n"),TStats = print_stats(strip(True,N div 20)), + io:format("~n"),FStats = print_stats(strip(False,N div 20)), + Str = io_lib:format("~nNifs are ~.3f% faster than erlang!~n", + [(element(2,FStats) - element(2,TStats)) / + element(2,FStats) * 100]), + io:format(Str), + {comment, lists:flatten(Str)}; +nif_vs_erlang_performance({T,N,Sched}) -> + PTC1 = fun() -> + application:set_env(asn1, nif_loadable, true) + end, + PTC2 = fun() -> + application:set_env(asn1, nif_loadable, false) + end, + TC = fun() -> + element(1,timer:tc(T)) + end, + nif_vs_erlang_performance({{{PTC1,TC},{PTC2,TC}},N,Sched}). + + +print_stats(Data) -> + Length = length(Data), + Mean = lists:sum(Data) / Length, + Variance = lists:foldl(fun(N,Acc) -> math:pow(N - Mean, 2)+Acc end, 0, Data), + StdDev = math:sqrt(Variance / Length), + Median = lists:nth(round(Length/2),Data), + Min = lists:min(Data), + Max = lists:max(Data), + if Length < 20 -> + io:format("Data: ~w~n",[Data]); + true -> + ok + end, + io:format("Length: ~p~nMean: ~p~nStdDev: ~p~nMedian: ~p~nMin: ~p~nMax: ~p~n", + [Length,Mean,StdDev,Median,Min,Max]), + {Length,Mean,StdDev,Median,Min,Max}. + +collect(Acc) -> + receive + {Tag,Val} -> + Prev = proplists:get_value(Tag,Acc,[]), + collect(lists:keystore(Tag,1,Acc,{Tag,[Val|Prev]})) + after 100 -> + Acc + end. + +exec(One,Two,Max,N) -> + exec(One,Two,Max,N,{[],[]}). +exec(_,_,_,1,{D1,D2}) -> + {lists:flatten(D1),lists:flatten(D2)}; +exec({PreOne,One} = O,{PreTwo,Two} = T,MaxProcs, N, {D1,D2}) -> + Num = random:uniform(round(N/2)), + if Num rem 3 == 0 -> + timer:sleep(Num rem 1000); + true -> + ok + end, + Procs = random:uniform(MaxProcs), + io:format("\tBatch: ~p items in ~p processes, ~p left~n",[Num,Procs,N-Num]), + if Num rem 2 == 1 -> + erlang:garbage_collect(), + PreOne(), + MoreOne = pexec(One, Num, Procs, []), + erlang:garbage_collect(), + PreTwo(), + MoreTwo = pexec(Two, Num, Procs, []); + true -> + erlang:garbage_collect(), + PreTwo(), + MoreTwo = pexec(Two, Num, Procs, []), + erlang:garbage_collect(), + PreOne(), + MoreOne = pexec(One, Num, Procs, []) + end, + exec(O,T,MaxProcs,N-Num,{[MoreOne|D1], + [MoreTwo|D2]}). + +pexec(_Fun, _, 0, []) -> + []; +pexec(Fun, _, 0, [{Ref,Pid}|Rest]) -> + receive + {data,D} -> + [D|pexec(Fun,0,0,[{Ref,Pid}|Rest])]; + {'DOWN', Ref, process, Pid, normal} -> + pexec(Fun, 0,0,Rest) + end; +pexec(Fun, 0, 1, AccProcs) -> + pexec(Fun, 0, 0, AccProcs); +pexec(Fun, N, 1, AccProcs) -> + [Fun()|pexec(Fun, N - 1, 1, AccProcs)]; +pexec(Fun, N, Procs, AccProcs) -> + S = self(), + Pid = spawn(fun() -> + S ! {data,pexec(Fun,N,1,[])} + end), + Ref = erlang:monitor(process, Pid), + pexec(Fun, N, Procs - 1, [{Ref,Pid}|AccProcs]). + +strip(Data,Num) -> + {_,R} = lists:split(Num,lists:sort(Data)), + element(2,lists:split(Num,lists:reverse(R))). + +faster(A,B) -> + (B - A)/B * 100. + +enc_dec(1, Msg, N) -> + worker_loop(N, Msg); +enc_dec(NumOfProcs,Msg, N) -> + pforeach(fun(_) -> + worker_loop(N, Msg) + end, [I || I <- lists:seq(1,NumOfProcs)]). + +worker_loop(0, _Msg) -> + ok; +worker_loop(N, Msg) -> + {ok,B}=asn1_wrapper:encode('NBAP-PDU-Discriptions', + 'NBAP-PDU', + Msg), + {ok,_Msg}=asn1_wrapper:decode('NBAP-PDU-Discriptions', + 'NBAP-PDU', + B), + worker_loop(N - 1, Msg). + + +pforeach(Fun, List) -> + pforeach(Fun, List, []). +pforeach(Fun, [], [{Pid,Ref}|Pids]) -> + receive + {'DOWN', Ref, process, Pid, normal} -> + pforeach(Fun, [], Pids) + end; +pforeach(Fun, [H|T], Pids) -> + Pid = spawn(fun() -> Fun(H) end), + Ref = erlang:monitor(process, Pid), + pforeach(Fun, T, [{Pid, Ref}|Pids]); +pforeach(_Fun,[],[]) -> + ok. + +-record('InitiatingMessage',{procedureCode,criticality,value}). +-record('Iu-ReleaseCommand',{first,second}). + +ticket7904(Config) -> + asn1_test_lib:compile("RANAPextract1", Config, [per_bin, optimize]), + + Val1 = #'InitiatingMessage'{procedureCode=1, + criticality=ignore, + value=#'Iu-ReleaseCommand'{ + first=13, + second=true}}, + + {ok,_} = 'RANAPextract1':encode('InitiatingMessage', Val1), + {ok,_} = 'RANAPextract1':encode('InitiatingMessage', Val1). diff --git a/lib/asn1/test/asn1_SUITE.erl.src b/lib/asn1/test/asn1_SUITE.erl.src deleted file mode 100644 index 3f51b125ec..0000000000 --- a/lib/asn1/test/asn1_SUITE.erl.src +++ /dev/null @@ -1,2392 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2001-2011. All Rights Reserved. -%% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%% -%% %CopyrightEnd% -%% -%% -%%% Purpose : Test suite for the ASN.1 application - --module(asn1_%BIN%SUITE). --define(PER,'%PER%'). --define(BER,'%BER%'). --define(ber_driver(Erule,Func), - case Erule of - ber_bin_v2 -> - Func; - _ -> ok - end). --define(per_optimize(Erule), - case Erule of - ber_bin_v2 ->[optimize]; - _ -> [] - end). --define(per_bit_opt(FuncCall), - case ?BER of - ber_bin_v2 -> FuncCall; -% _ -> {skip,"only for bit optimized per_bin"} - _ -> ok - end). --define(uper_bin(FuncCall), - case ?PER of - per -> FuncCall; - _ -> ok - end). - --compile(export_all). -%%-export([Function/Arity, ...]). - --include_lib("test_server/include/test_server.hrl"). - -%% records used by test-case default --record('Def1',{ -bool0, bool1 = asn1_DEFAULT, bool2 = asn1_DEFAULT, bool3 = asn1_DEFAULT}). - -%-record('Def2',{ -%bool10, bool11 = asn1_DEFAULT, bool12 = asn1_DEFAULT, bool13}). - -%-record('Def3',{ -%bool30 = asn1_DEFAULT, bool31 = asn1_DEFAULT, bool32 = asn1_DEFAULT, bool33 = asn1_DEFAULT}). - -suite() -> [{ct_hooks,[ts_install_cth]}]. - -all() -> [{group,compile},parse,default_per,default_ber,default_per_opt,per, - {group,ber},testPrim, - testPrimStrings, testPrimExternal, testChoPrim, - testChoExtension, testChoExternal, testChoOptional, - testChoOptionalImplicitTag, testChoRecursive, - testChoTypeRefCho, testChoTypeRefPrim, testChoTypeRefSeq, - testChoTypeRefSet, testDef, testOpt, testSeqDefault, - testSeqExtension, testSeqExternal, testSeqOptional, - testSeqPrim, testSeqTag, testSeqTypeRefCho, - testSeqTypeRefPrim, testSeqTypeRefSeq, testSeqTypeRefSet, - testSeqOf, testSeqOfIndefinite, testSeqOfCho, - testSeqOfExternal, testSetDefault, testSetExtension, - testExtensionAdditionGroup, - testSetExternal, testSeqOfTag, testSetOptional, testSetPrim, - testSetTag, testSetTypeRefCho, testSetTypeRefPrim, - testSetTypeRefSeq, testSetTypeRefSet, testSetOf, testSetOfCho, - testSetOfExternal, testSetOfTag, testEnumExt, value_test, - testSeq2738, constructed, ber_decode_error, - h323test, testSeqIndefinite, testSetIndefinite, - testChoiceIndefinite, - per_GeneralString, per_open_type, testInfObjectClass, - testParameterizedInfObj, testMergeCompile, testobj, - testDeepTConstr, testConstraints, - testInvokeMod, testExport, testImport, testCompactBitString, - testMegaco, testParamBasic, testMvrasn6, - testContextSwitchingTypes, testTypeValueNotation, - testOpenTypeImplicitTag,duplicate_tags,rtUI,testROSE, - testINSTANCE_OF,testTCAP,testDER,specialized_decodes, - special_decode_performance,test_driver_load, - test_ParamTypeInfObj, test_WS_ParamClass, - test_Defed_ObjectIdentifier, testSelectionType, - testSSLspecs, testNortel,test_undecoded_rest, - test_inline, testTcapsystem, testNBAPsystem, - test_compile_options,testDoubleEllipses, test_modified_x420, - testX420, test_x691,ticket_6143, testExtensionAdditionGroup, - test_OTP_9688 - ] ++ common() ++ particular(). - -groups() -> - [ - {compile, [], - [c_syntax, c_string_per, c_string_ber, - c_implicit_before_choice]}, - {ber, [], - [ber_choiceinseq, ber_optional, ber_optional_keyed_list, - ber_other]}, - {app_test, [], [{asn1_app_test, all}]}, - {appup_test, [], [{asn1_appup_test, all}]} - ]. - -init_per_suite(Config) -> - io:format("code:lib_dir(asn1) = ~p~n",[code:lib_dir(asn1)]), - Config. - -end_per_suite(_Config) -> - ok. - -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. - - -%all(suite) -> [test_inline,testNBAPsystem,test_compile_options,ticket_6143]. - - -init_per_testcase(Func,Config) -> - %%?line test_server:format("Func: ~p~n",[Func]), - ?line {ok, _} = file:read_file_info(filename:join([?config(priv_dir,Config)])), - ?line code:add_patha(?config(priv_dir,Config)), - Dog= - case Func of - testX420 -> - test_server:timetrap({minutes,60}); % 60 minutes - _ -> - test_server:timetrap({minutes,30}) % 60 minutes - end, -%% Dog=test_server:timetrap(1800000), % 30 minutes - [{watchdog, Dog}|Config]. - -end_per_testcase(_Func,Config) -> - Dog=?config(watchdog, Config), - test_server:timetrap_cancel(Dog). - - -testPrim(suite) -> []; -testPrim(Config) -> - ?line testPrim:compile(Config,?BER,[]), - ?line testPrim_cases(?BER), - ?line ?ber_driver(?BER,testPrim:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testPrim_cases(?BER)), - ?line testPrim:compile(Config,?PER,[]), - ?line testPrim_cases(?PER), - ?line ?per_bit_opt(testPrim:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testPrim_cases(?PER)), - ?line ?uper_bin(testPrim:compile(Config,uper_bin,[])), - ?line ?uper_bin(testPrim_cases(uper_bin)), - ?line testPrim:compile(Config,?PER,[optimize]), - ?line testPrim_cases(?PER). - -testPrim_cases(Rules) -> - ?line testPrim:bool(Rules), - ?line testPrim:int(Rules), - ?line testPrim:enum(Rules), - ?line testPrim:obj_id(Rules), - ?line testPrim:rel_oid(Rules), - ?line testPrim:null(Rules), - ?line testPrim:real(Rules). - - -testCompactBitString(suite) -> []; -testCompactBitString(Config) -> - - ?line testCompactBitString:compile(Config,?BER,[compact_bit_string]), - ?line testCompactBitString:compact_bit_string(?BER), - - ?line ?ber_driver(?BER,testCompactBitString:compile(Config,?BER,[compact_bit_string,driver])), - ?line ?ber_driver(?BER,testCompactBitString:compact_bit_string(?BER)), - - ?line testCompactBitString:compile(Config,?PER,[compact_bit_string]), - ?line testCompactBitString:compact_bit_string(?PER), - ?line testCompactBitString:bit_string_unnamed(?PER), - - ?line ?per_bit_opt(testCompactBitString:compile(Config,?PER, - [compact_bit_string,optimize])), - ?line ?per_bit_opt(testCompactBitString:compact_bit_string(?PER)), - ?line ?per_bit_opt(testCompactBitString:bit_string_unnamed(?PER)), - ?line ?per_bit_opt(testCompactBitString:ticket_7734(?PER)), - - ?line ?uper_bin(testCompactBitString:compile(Config,uper_bin, - [compact_bit_string])), - ?line ?uper_bin(testCompactBitString:compact_bit_string(uper_bin)), - ?line ?uper_bin(testCompactBitString:bit_string_unnamed(uper_bin)), - - ?line testCompactBitString:compile(Config,?PER,[optimize,compact_bit_string]), - ?line testCompactBitString:compact_bit_string(?PER), - ?line testCompactBitString:bit_string_unnamed(?PER), - - ?line testCompactBitString:otp_4869(?PER). - - -testPrimStrings(suite) -> []; -testPrimStrings(Config) -> - - ?line testPrimStrings:compile(Config,?BER,[]), - ?line testPrimStrings_cases(?BER), - ?line testPrimStrings:more_strings(?BER), %% these are not implemented in per yet - ?line ?ber_driver(?BER,testPrimStrings:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testPrimStrings_cases(?BER)), - ?line ?ber_driver(?BER,testPrimStrings:more_strings(?BER)), - - ?line testPrimStrings:compile(Config,?PER,[]), - ?line testPrimStrings_cases(?PER), - - ?line ?per_bit_opt(testPrimStrings:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testPrimStrings_cases(?PER)), - - ?line ?uper_bin(testPrimStrings:compile(Config,uper_bin,[])), - ?line ?uper_bin(testPrimStrings_cases(uper_bin)), - - ?line testPrimStrings:compile(Config,?PER,[optimize]), - ?line testPrimStrings_cases(?PER). - -testPrimStrings_cases(Rules) -> - ?line testPrimStrings:bit_string(Rules), - ?line testPrimStrings:bit_string_unnamed(Rules), - ?line testPrimStrings:octet_string(Rules), - ?line testPrimStrings:numeric_string(Rules), - ?line testPrimStrings:other_strings(Rules), - ?line testPrimStrings:universal_string(Rules), - ?line testPrimStrings:bmp_string(Rules), - ?line testPrimStrings:times(Rules), - ?line testPrimStrings:utf8_string(Rules). - - - -testPrimExternal(suite) -> []; -testPrimExternal(Config) -> - - ?line testExternal:compile(Config,?BER,[]), - ?line testPrimExternal:compile(Config,?BER,[]), - ?line testPrimExternal_cases(?BER), - - ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testPrimExternal:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testPrimExternal_cases(?BER)), - - ?line testExternal:compile(Config,?PER,[]), - ?line testPrimExternal:compile(Config,?PER,[]), - ?line testPrimExternal_cases(?PER), - - ?line ?per_bit_opt(testExternal:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testPrimExternal:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testPrimExternal_cases(?PER)), - - ?line ?uper_bin(testExternal:compile(Config,uper_bin,[])), - ?line ?uper_bin(testPrimExternal:compile(Config,uper_bin,[])), - ?line ?uper_bin(testPrimExternal_cases(uper_bin)), - - ?line testExternal:compile(Config,?PER,[optimize]), - ?line testPrimExternal:compile(Config,?PER,[optimize]), - ?line testPrimExternal_cases(?PER). - -testPrimExternal_cases(Rules) -> - ?line testPrimExternal:external(Rules). - - - - -testChoPrim(suite) -> []; -testChoPrim(Config) -> - - ?line testChoPrim:compile(Config,?BER,[]), - ?line testChoPrim_cases(?BER), - - ?line ?ber_driver(?BER,testChoPrim:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testChoPrim_cases(?BER)), - - ?line testChoPrim:compile(Config,?PER,[]), - ?line testChoPrim_cases(?PER), - - ?line ?per_bit_opt(testChoPrim:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testChoPrim_cases(?PER)), - - ?line ?uper_bin(testChoPrim:compile(Config,uper_bin,[])), - ?line ?uper_bin(testChoPrim_cases(uper_bin)), - - ?line testChoPrim:compile(Config,?PER,[optimize]), - ?line testChoPrim_cases(?PER). - -testChoPrim_cases(Rules) -> - ?line testChoPrim:bool(Rules), - ?line testChoPrim:int(Rules). - - - -testChoExtension(suite) -> []; -testChoExtension(Config) -> - - ?line testChoExtension:compile(Config,?BER,[]), - ?line testChoExtension_cases(?BER), - - ?line ?ber_driver(?BER,testChoExtension:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testChoExtension_cases(?BER)), - - ?line testChoExtension:compile(Config,?PER,[]), - ?line testChoExtension_cases(?PER), - - ?line ?per_bit_opt(testChoExtension:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testChoExtension_cases(?PER)), - - ?line ?uper_bin(testChoExtension:compile(Config,uper_bin,[])), - ?line ?uper_bin(testChoExtension_cases(uper_bin)), - - ?line testChoExtension:compile(Config,?PER,[optimize]), - ?line testChoExtension_cases(?PER). - -testChoExtension_cases(Rules) -> - ?line testChoExtension:extension(Rules). - - - -testChoExternal(suite) -> []; -testChoExternal(Config) -> - - ?line testExternal:compile(Config,?BER,[]), - ?line testChoExternal:compile(Config,?BER,[]), - ?line testChoExternal_cases(?BER), - - ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testChoExternal:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testChoExternal_cases(?BER)), - - ?line testExternal:compile(Config,?PER,[]), - ?line testChoExternal:compile(Config,?PER,[]), - ?line testChoExternal_cases(?PER), - - ?line ?per_bit_opt(testExternal:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testChoExternal:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testChoExternal_cases(?PER)), - - ?line ?uper_bin(testExternal:compile(Config,uper_bin,[])), - ?line ?uper_bin(testChoExternal:compile(Config,uper_bin,[])), - ?line ?uper_bin(testChoExternal_cases(uper_bin)), - - ?line testExternal:compile(Config,?PER,[optimize]), - ?line testChoExternal:compile(Config,?PER,[optimize]), - ?line testChoExternal_cases(?PER). - - -testChoExternal_cases(Rules) -> - ?line testChoExternal:external(Rules). - - - -testChoOptional(suite) -> []; -testChoOptional(Config) -> - - ?line testChoOptional:compile(Config,?BER,[]), - ?line testChoOptional_cases(?BER), - - ?line ?ber_driver(?BER,testChoOptional:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testChoOptional_cases(?BER)), - - ?line testChoOptional:compile(Config,?PER,[]), - ?line testChoOptional_cases(?PER), - - ?line ?per_bit_opt(testChoOptional:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testChoOptional_cases(?PER)), - - ?line ?uper_bin(testChoOptional:compile(Config,uper_bin,[])), - ?line ?uper_bin(testChoOptional_cases(uper_bin)), - - ?line testChoOptional:compile(Config,?PER,[optimize]), - ?line testChoOptional_cases(?PER). - -testChoOptional_cases(Rules) -> - ?line testChoOptional:optional(Rules). - -testChoOptionalImplicitTag(suite) -> []; -testChoOptionalImplicitTag(Config) -> - %% Only meaningful for ?BER - ?line testChoOptionalImplicitTag:compile(Config,?BER), - ?line testChoOptionalImplicitTag:optional(?BER). - - -testChoRecursive(suite) -> []; -testChoRecursive(Config) -> - - ?line testChoRecursive:compile(Config,?BER,[]), - ?line testChoRecursive_cases(?BER), - - ?line ?ber_driver(?BER,testChoRecursive:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testChoRecursive_cases(?BER)), - - ?line testChoRecursive:compile(Config,?PER,[]), - ?line testChoRecursive_cases(?PER), - - ?line ?per_bit_opt(testChoRecursive:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testChoRecursive_cases(?PER)), - - ?line ?uper_bin(testChoRecursive:compile(Config,uper_bin,[])), - ?line ?uper_bin(testChoRecursive_cases(uper_bin)), - - ?line testChoRecursive:compile(Config,?PER,[optimize]), - ?line testChoRecursive_cases(?PER). - -testChoRecursive_cases(Rules) -> - ?line testChoRecursive:recursive(Rules). - - - -testChoTypeRefCho(suite) -> []; -testChoTypeRefCho(Config) -> - - ?line testChoTypeRefCho:compile(Config,?BER,[]), - ?line testChoTypeRefCho_cases(?BER), - - ?line ?ber_driver(?BER,testChoTypeRefCho:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testChoTypeRefCho_cases(?BER)), - - ?line testChoTypeRefCho:compile(Config,?PER,[]), - ?line testChoTypeRefCho_cases(?PER), - - ?line ?per_bit_opt(testChoTypeRefCho:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testChoTypeRefCho_cases(?PER)), - - ?line ?uper_bin(testChoTypeRefCho:compile(Config,uper_bin,[])), - ?line ?uper_bin(testChoTypeRefCho_cases(uper_bin)), - - ?line testChoTypeRefCho:compile(Config,?PER,[optimize]), - ?line testChoTypeRefCho_cases(?PER). - -testChoTypeRefCho_cases(Rules) -> - ?line testChoTypeRefCho:choice(Rules). - - - -testChoTypeRefPrim(suite) -> []; -testChoTypeRefPrim(Config) -> - - ?line testChoTypeRefPrim:compile(Config,?BER,[]), - ?line testChoTypeRefPrim_cases(?BER), - - ?line ?ber_driver(?BER,testChoTypeRefPrim:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testChoTypeRefPrim_cases(?BER)), - - ?line testChoTypeRefPrim:compile(Config,?PER,[]), - ?line testChoTypeRefPrim_cases(?PER), - - ?line ?per_bit_opt(testChoTypeRefPrim:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testChoTypeRefPrim_cases(?PER)), - - ?line ?uper_bin(testChoTypeRefPrim:compile(Config,uper_bin,[])), - ?line ?uper_bin(testChoTypeRefPrim_cases(uper_bin)), - - ?line testChoTypeRefPrim:compile(Config,?PER,[optimize]), - ?line testChoTypeRefPrim_cases(?PER). - -testChoTypeRefPrim_cases(Rules) -> - ?line testChoTypeRefPrim:prim(Rules). - - - -testChoTypeRefSeq(suite) -> []; -testChoTypeRefSeq(Config) -> - - ?line testChoTypeRefSeq:compile(Config,?BER,[]), - ?line testChoTypeRefSeq_cases(?BER), - - ?line ?ber_driver(?BER,testChoTypeRefSeq:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testChoTypeRefSeq_cases(?BER)), - - ?line testChoTypeRefSeq:compile(Config,?PER,[]), - ?line testChoTypeRefSeq_cases(?PER), - - ?line ?per_bit_opt(testChoTypeRefSeq:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testChoTypeRefSeq_cases(?PER)), - - ?line ?uper_bin(testChoTypeRefSeq:compile(Config,uper_bin,[])), - ?line ?uper_bin(testChoTypeRefSeq_cases(uper_bin)), - - ?line testChoTypeRefSeq:compile(Config,?PER,[optimize]), - ?line testChoTypeRefSeq_cases(?PER). - -testChoTypeRefSeq_cases(Rules) -> - ?line testChoTypeRefSeq:seq(Rules). - - - -testChoTypeRefSet(suite) -> []; -testChoTypeRefSet(Config) -> - - ?line testChoTypeRefSet:compile(Config,?BER,[]), - ?line testChoTypeRefSet_cases(?BER), - - ?line ?ber_driver(?BER,testChoTypeRefSet:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testChoTypeRefSet_cases(?BER)), - - ?line testChoTypeRefSet:compile(Config,?PER,[]), - ?line testChoTypeRefSet_cases(?PER), - - ?line ?per_bit_opt(testChoTypeRefSet:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testChoTypeRefSet_cases(?PER)), - - ?line ?uper_bin(testChoTypeRefSet:compile(Config,uper_bin,[])), - ?line ?uper_bin(testChoTypeRefSet_cases(uper_bin)), - - ?line testChoTypeRefSet:compile(Config,?PER,[optimize]), - ?line testChoTypeRefSet_cases(?PER). - -testChoTypeRefSet_cases(Rules) -> - ?line testChoTypeRefSet:set(Rules). - - - -testDef(suite) -> []; -testDef(Config) -> - - ?line testDef:compile(Config,?BER,[]), - ?line testDef_cases(?BER), - - ?line ?ber_driver(?BER,testDef:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testDef_cases(?BER)), - - ?line testDef:compile(Config,?PER,[]), - ?line testDef_cases(?PER), - - ?line ?per_bit_opt(testDef:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testDef_cases(?PER)), - - ?line ?uper_bin(testDef:compile(Config,uper_bin,[])), - ?line ?uper_bin(testDef_cases(uper_bin)), - - ?line testDef:compile(Config,?PER,[optimize]), - ?line testDef_cases(?PER). - -testDef_cases(Rules) -> - ?line testDef:main(Rules). - - - -testOpt(suite) -> []; -testOpt(Config) -> - - ?line testOpt:compile(Config,?BER), - ?line testOpt_cases(?BER), - - ?line testOpt:compile(Config,?PER), - ?line testOpt_cases(?PER). - -testOpt_cases(Rules) -> - ?line testOpt:main(Rules). - - -testEnumExt(suite) -> []; -testEnumExt(Config) -> - - ?line testEnumExt:compile(Config,?BER,[]), - ?line testEnumExt:main(?BER), - - ?line ?ber_driver(?BER,testEnumExt:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testEnumExt:main(?BER)), - - ?line testEnumExt:compile(Config,?PER,[]), - ?line testEnumExt:main(?PER), - - ?line ?per_bit_opt(testEnumExt:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testEnumExt:main(?PER)), - - ?line ?uper_bin(testEnumExt:compile(Config,uper_bin,[])), - ?line ?uper_bin(testEnumExt:main(uper_bin)), - - ?line testEnumExt:compile(Config,?PER,[optimize]), - ?line testEnumExt:main(?PER). - -testSeqDefault(doc) -> ["Test of OTP-2523 ENUMERATED with extensionmark."]; -testSeqDefault(suite) -> []; -testSeqDefault(Config) -> - - ?line testSeqDefault:compile(Config,?BER,[]), - ?line testSeqDefault_cases(?BER), - - ?line ?ber_driver(?BER,testSeqDefault:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSeqDefault_cases(?BER)), - - ?line testSeqDefault:compile(Config,?PER,[]), - ?line testSeqDefault_cases(?PER), - - ?line ?per_bit_opt(testSeqDefault:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testSeqDefault_cases(?PER)), - - ?line ?uper_bin(testSeqDefault:compile(Config,uper_bin,[])), - ?line ?uper_bin(testSeqDefault_cases(uper_bin)), - - ?line testSeqDefault:compile(Config,?PER,[optimize]), - ?line testSeqDefault_cases(?PER). - -testSeqDefault_cases(Rules) -> - ?line testSeqDefault:main(Rules). - - - -testSeqExtension(suite) -> []; -testSeqExtension(Config) -> - - ?line testExternal:compile(Config,?BER,[]), - ?line testSeqExtension:compile(Config,?BER,[]), - ?line testSeqExtension_cases(?BER), - - ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSeqExtension:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSeqExtension_cases(?BER)). - -testSeqExtension_cases(Rules) -> - ?line testSeqExtension:main(Rules). - - - -testSeqExternal(suite) -> []; -testSeqExternal(Config) -> - - ?line testExternal:compile(Config,?BER,[]), - ?line testSeqExternal:compile(Config,?BER,[]), - ?line testSeqExternal_cases(?BER), - - ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSeqExternal:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSeqExternal_cases(?BER)). - -testSeqExternal_cases(Rules) -> - ?line testSeqExternal:main(Rules). - - -testSeqOptional(suite) -> []; -testSeqOptional(Config) -> - - ?line testSeqOptional:compile(Config,?BER,[]), - ?line testSeqOptional_cases(?BER), - - ?line ?ber_driver(?BER,testSeqOptional:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSeqOptional_cases(?BER)), - - ?line testSeqOptional:compile(Config,?PER,[]), - ?line testSeqOptional_cases(?PER), - - ?line ?per_bit_opt(testSeqOptional:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testSeqOptional_cases(?PER)), - - ?line ?uper_bin(testSeqOptional:compile(Config,uper_bin,[])), - ?line ?uper_bin(testSeqOptional_cases(uper_bin)), - - ?line testSeqOptional:compile(Config,?PER,[optimize]), - ?line testSeqOptional_cases(?PER). - -testSeqOptional_cases(Rules) -> - ?line testSeqOptional:main(Rules). - - - -testSeqPrim(suite) -> []; -testSeqPrim(Config) -> - - ?line testSeqPrim:compile(Config,?BER,[]), - ?line testSeqPrim_cases(?BER), - - ?line ?ber_driver(?BER,testSeqPrim:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSeqPrim_cases(?BER)), - - ?line testSeqPrim:compile(Config,?PER,[]), - ?line testSeqPrim_cases(?PER), - - ?line ?per_bit_opt(testSeqPrim:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testSeqPrim_cases(?PER)), - - ?line ?uper_bin(testSeqPrim:compile(Config,uper_bin,[])), - ?line ?uper_bin(testSeqPrim_cases(uper_bin)), - - ?line testSeqPrim:compile(Config,?PER,[optimize]), - ?line testSeqPrim_cases(?PER). - -testSeqPrim_cases(Rules) -> - ?line testSeqPrim:main(Rules). - - -testSeq2738(doc) -> ["Test of OTP-2738 Detect corrupt optional component."]; -testSeq2738(suite) -> []; -testSeq2738(Config) -> - - ?line testSeq2738:compile(Config,?BER,[]), - ?line testSeq2738_cases(?BER), - - ?line ?ber_driver(?BER,testSeq2738:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSeq2738_cases(?BER)), - - ?line testSeq2738:compile(Config,?PER,[]), - ?line testSeq2738_cases(?PER), - - ?line ?per_bit_opt(testSeq2738:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testSeq2738_cases(?PER)), - - ?line ?uper_bin(testSeq2738:compile(Config,uper_bin,[])), - ?line ?uper_bin(testSeq2738_cases(uper_bin)), - - ?line testSeq2738:compile(Config,?PER,[optimize]), - ?line testSeq2738_cases(?PER). - -testSeq2738_cases(Rules) -> - ?line testSeq2738:main(Rules). - - -testSeqTag(suite) -> []; -testSeqTag(Config) -> - - ?line testExternal:compile(Config,?BER,[]), - ?line testSeqTag:compile(Config,?BER,[]), - ?line testSeqTag_cases(?BER), - - ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSeqTag:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSeqTag_cases(?BER)), - - ?line testExternal:compile(Config,?PER,[]), - ?line testSeqTag:compile(Config,?PER,[]), - ?line testSeqTag_cases(?PER), - - ?line ?per_bit_opt(testExternal:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testSeqTag:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testSeqTag_cases(?PER)), - - ?line ?uper_bin(testExternal:compile(Config,uper_bin,[])), - ?line ?uper_bin(testSeqTag:compile(Config,uper_bin,[])), - ?line ?uper_bin(testSeqTag_cases(uper_bin)), - - ?line testExternal:compile(Config,?PER,[optimize]), - ?line testSeqTag:compile(Config,?PER,[optimize]), - ?line testSeqTag_cases(?PER). - -testSeqTag_cases(Rules) -> - ?line testSeqTag:main(Rules). - - - - -testSeqTypeRefCho(suite) -> []; -testSeqTypeRefCho(Config) -> - - ?line testSeqTypeRefCho:compile(Config,?BER,[]), - ?line testSeqTypeRefCho_cases(?BER), - - ?line ?ber_driver(?BER,testSeqTypeRefCho:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSeqTypeRefCho_cases(?BER)), - - ?line testSeqTypeRefCho:compile(Config,?PER,[]), - ?line testSeqTypeRefCho_cases(?PER), - - ?line ?per_bit_opt(testSeqTypeRefCho:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testSeqTypeRefCho_cases(?PER)), - - ?line ?uper_bin(testSeqTypeRefCho:compile(Config,uper_bin,[])), - ?line ?uper_bin(testSeqTypeRefCho_cases(uper_bin)), - - ?line testSeqTypeRefCho:compile(Config,?PER,[optimize]), - ?line testSeqTypeRefCho_cases(?PER). - -testSeqTypeRefCho_cases(Rules) -> - ?line testSeqTypeRefCho:main(Rules). - - - -testSeqTypeRefPrim(suite) -> []; -testSeqTypeRefPrim(Config) -> - - ?line testSeqTypeRefPrim:compile(Config,?BER,[]), - ?line testSeqTypeRefPrim_cases(?BER), - - ?line ?ber_driver(?BER,testSeqTypeRefPrim:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSeqTypeRefPrim_cases(?BER)), - - ?line testSeqTypeRefPrim:compile(Config,?PER,[]), - ?line testSeqTypeRefPrim_cases(?PER), - - ?line ?per_bit_opt(testSeqTypeRefPrim:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testSeqTypeRefPrim_cases(?PER)), - - ?line ?uper_bin(testSeqTypeRefPrim:compile(Config,uper_bin,[])), - ?line ?uper_bin(testSeqTypeRefPrim_cases(uper_bin)), - - ?line testSeqTypeRefPrim:compile(Config,?PER,[optimize]), - ?line testSeqTypeRefPrim_cases(?PER). - -testSeqTypeRefPrim_cases(Rules) -> - ?line testSeqTypeRefPrim:main(Rules). - - - -testSeqTypeRefSeq(suite) -> []; -testSeqTypeRefSeq(Config) -> - - ?line testSeqTypeRefSeq:compile(Config,?BER,[]), - ?line testSeqTypeRefSeq_cases(?BER), - - ?line ?ber_driver(?BER,testSeqTypeRefSeq:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSeqTypeRefSeq_cases(?BER)), - - ?line testSeqTypeRefSeq:compile(Config,?PER,[]), - ?line testSeqTypeRefSeq_cases(?PER), - - ?line ?per_bit_opt(testSeqTypeRefSeq:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testSeqTypeRefSeq_cases(?PER)), - - ?line ?uper_bin(testSeqTypeRefSeq:compile(Config,uper_bin,[])), - ?line ?uper_bin(testSeqTypeRefSeq_cases(uper_bin)), - - ?line testSeqTypeRefSeq:compile(Config,?PER,[optimize]), - ?line testSeqTypeRefSeq_cases(?PER). - -testSeqTypeRefSeq_cases(Rules) -> - ?line testSeqTypeRefSeq:main(Rules). - - - -testSeqTypeRefSet(suite) -> []; -testSeqTypeRefSet(Config) -> - - ?line testSeqTypeRefSet:compile(Config,?BER,[]), - ?line testSeqTypeRefSet_cases(?BER), - - ?line ?ber_driver(?BER,testSeqTypeRefSet:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSeqTypeRefSet_cases(?BER)), - - ?line testSeqTypeRefSet:compile(Config,?PER,[]), - ?line testSeqTypeRefSet_cases(?PER), - - ?line ?per_bit_opt(testSeqTypeRefSet:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testSeqTypeRefSet_cases(?PER)), - - ?line ?uper_bin(testSeqTypeRefSet:compile(Config,uper_bin,[])), - ?line ?uper_bin(testSeqTypeRefSet_cases(uper_bin)), - - ?line testSeqTypeRefSet:compile(Config,?PER,[optimize]), - ?line testSeqTypeRefSet_cases(?PER). - -testSeqTypeRefSet_cases(Rules) -> - ?line testSeqTypeRefSet:main(Rules). - - - - -testSeqOf(suite) -> []; -testSeqOf(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testSeqOf:compile(Config,?BER,[]), - ?line testSeqOf_cases(?BER), - - ?line ?ber_driver(?BER,testSeqOf:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSeqOf_cases(?BER)), - - ?line testSeqOf:compile(Config,?PER,[]), - ?line testSeqOf_cases(?PER), - - ?line ?per_bit_opt(testSeqOf:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testSeqOf_cases(?PER)), - - ?line ?uper_bin(testSeqOf:compile(Config,uper_bin,[])), - ?line ?uper_bin(testSeqOf_cases(uper_bin)), - - ?line testSeqOf:compile(Config,?PER,[optimize]), - ?line testSeqOf_cases(?PER). - -testSeqOf_cases(Rules) -> - ?line testSeqOf:main(Rules). - - - - -testSeqOfCho(suite) -> []; -testSeqOfCho(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testSeqOfCho:compile(Config,?BER,[]), - ?line testSeqOfCho_cases(?BER), - - ?line ?ber_driver(?BER,testSeqOfCho:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSeqOfCho_cases(?BER)), - - ?line testSeqOfCho:compile(Config,?PER,[]), - ?line testSeqOfCho_cases(?PER), - - ?line ?per_bit_opt(testSeqOfCho:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testSeqOfCho_cases(?PER)), - - ?line ?uper_bin(testSeqOfCho:compile(Config,uper_bin,[])), - ?line ?uper_bin(testSeqOfCho_cases(uper_bin)), - - ?line testSeqOfCho:compile(Config,?PER,[optimize]), - ?line testSeqOfCho_cases(?PER). - -testSeqOfIndefinite(suite) -> []; -testSeqOfIndefinite(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testSeqOfIndefinite:compile(Config,?BER,[]), - ?line testSeqOfIndefinite:main(), - - ?line ?ber_driver(?BER,testSeqOfIndefinite:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSeqOfIndefinite:main()). - -testSeqOfCho_cases(Rules) -> - ?line testSeqOfCho:main(Rules). - - -testSeqOfExternal(suite) -> []; -testSeqOfExternal(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testExternal:compile(Config,?BER,[]), - ?line testSeqOfExternal:compile(Config,?BER,[]), - ?line testSeqOfExternal_cases(?BER), - - ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSeqOfExternal:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSeqOfExternal_cases(?BER)), - - ?line testExternal:compile(Config,?PER,[]), - ?line testSeqOfExternal:compile(Config,?PER,[]), - ?line testSeqOfExternal_cases(?PER), - - ?line ?per_bit_opt(testExternal:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testSeqOfExternal:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testSeqOfExternal_cases(?PER)), - - ?line ?uper_bin(testExternal:compile(Config,uper_bin,[])), - ?line ?uper_bin(testSeqOfExternal:compile(Config,uper_bin,[])), - ?line ?uper_bin(testSeqOfExternal_cases(uper_bin)), - - ?line testExternal:compile(Config,?PER,[optimize]), - ?line testSeqOfExternal:compile(Config,?PER,[optimize]), - ?line testSeqOfExternal_cases(?PER). - -testSeqOfExternal_cases(Rules) -> - ?line testSeqOfExternal:main(Rules). - - - -testSeqOfTag(suite) -> []; -testSeqOfTag(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testExternal:compile(Config,?BER,[]), - ?line testSeqOfTag:compile(Config,?BER,[]), - ?line testSeqOfTag_cases(?BER), - - ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSeqOfTag:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSeqOfTag_cases(?BER)), - - ?line testExternal:compile(Config,?PER,[]), - ?line testSeqOfTag:compile(Config,?PER,[]), - ?line testSeqOfTag_cases(?PER), - - ?line ?per_bit_opt(testExternal:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testSeqOfTag:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testSeqOfTag_cases(?PER)), - - ?line ?uper_bin(testExternal:compile(Config,uper_bin,[])), - ?line ?uper_bin(testSeqOfTag:compile(Config,uper_bin,[])), - ?line ?uper_bin(testSeqOfTag_cases(uper_bin)), - - ?line testExternal:compile(Config,?PER,[optimize]), - ?line testSeqOfTag:compile(Config,?PER,[optimize]), - ?line testSeqOfTag_cases(?PER). - -testSeqOfTag_cases(Rules) -> - ?line testSeqOfTag:main(Rules). - - - - -testSetDefault(suite) -> []; -testSetDefault(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testSetDefault:compile(Config,?BER,[]), - ?line testSetDefault_cases(?BER), - - ?line ?ber_driver(?BER,testSetDefault:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSetDefault_cases(?BER)), - - ?line testSetDefault:compile(Config,?PER,[]), - ?line testSetDefault_cases(?PER), - - ?line ?per_bit_opt(testSetDefault:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testSetDefault_cases(?PER)), - - ?line ?uper_bin(testSetDefault:compile(Config,uper_bin,[])), - ?line ?uper_bin(testSetDefault_cases(uper_bin)), - - ?line testSetDefault:compile(Config,?PER,[optimize]), - ?line testSetDefault_cases(?PER). - -testSetDefault_cases(Rules) -> - ?line testSetDefault:main(Rules). - - -testParamBasic(suite) -> []; -testParamBasic(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testParamBasic:compile(Config,?BER,[]), - ?line testParamBasic_cases(?BER), - - ?line ?ber_driver(?BER,testParamBasic:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testParamBasic_cases(?BER)), - - ?line testParamBasic:compile(Config,?PER,[]), - ?line testParamBasic_cases(?PER), - - ?line ?per_bit_opt(testParamBasic:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testParamBasic_cases(?PER)), - - ?line ?uper_bin(testParamBasic:compile(Config,uper_bin,[])), - ?line ?uper_bin(testParamBasic_cases(uper_bin)), - - ?line testParamBasic:compile(Config,?PER,[optimize]), - ?line testParamBasic_cases(?PER). - - -testParamBasic_cases(Rules) -> - ?line testParamBasic:main(Rules). - -testSetExtension(suite) -> []; -testSetExtension(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testExternal:compile(Config,?BER,[]), - ?line testSetExtension:compile(Config,?BER,[]), - ?line testSetExtension_cases(?BER), - - ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSetExtension:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSetExtension_cases(?BER)). - -testSetExtension_cases(Rules) -> - ?line testSetExtension:main(Rules). - - -testSetExternal(suite) -> []; -testSetExternal(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testExternal:compile(Config,?BER,[]), - ?line testSetExternal:compile(Config,?BER,[]), - ?line testSetExternal_cases(?BER), - - ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSetExternal:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSetExternal_cases(?BER)). - -testSetExternal_cases(Rules) -> - ?line testSetExternal:main(Rules). - - -testSetOptional(suite) -> []; -testSetOptional(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testSetOptional:compile(Config,?BER,[]), - ?line testSetOptional_cases(?BER), - - ?line ?ber_driver(?BER,testSetOptional:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSetOptional_cases(?BER)), - - ?line testSetOptional:compile(Config,?PER,[]), - ?line testSetOptional_cases(?PER), - - ?line ?per_bit_opt(testSetOptional:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testSetOptional_cases(?PER)), - - ?line ?uper_bin(testSetOptional:compile(Config,uper_bin,[])), - ?line ?uper_bin(testSetOptional_cases(uper_bin)), - - ?line testSetOptional:compile(Config,?PER,[optimize]), - ?line testSetOptional_cases(?PER). - -testSetOptional_cases(Rules) -> - ?line ok = testSetOptional:ticket_7533(Rules), - ?line ok = testSetOptional:main(Rules). - - - - -testSetPrim(suite) -> []; -testSetPrim(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testSetPrim:compile(Config,?BER,[]), - ?line testSetPrim_cases(?BER), - - ?line ?ber_driver(?BER,testSetPrim:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSetPrim_cases(?BER)), - - ?line testSetPrim:compile(Config,?PER,[]), - ?line testSetPrim_cases(?PER), - - ?line ?per_bit_opt(testSetPrim:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testSetPrim_cases(?PER)), - - ?line ?uper_bin(testSetPrim:compile(Config,uper_bin,[])), - ?line ?uper_bin(testSetPrim_cases(uper_bin)), - - ?line testSetPrim:compile(Config,?PER,[optimize]), - ?line testSetPrim_cases(?PER). - -testSetPrim_cases(Rules) -> - ?line testSetPrim:main(Rules). - - - -testSetTag(suite) -> []; -testSetTag(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testExternal:compile(Config,?BER,[]), - ?line testSetTag:compile(Config,?BER,[]), - ?line testSetTag_cases(?BER), - - ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSetTag:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSetTag_cases(?BER)), - - ?line testExternal:compile(Config,?PER,[]), - ?line testSetTag:compile(Config,?PER,[]), - ?line testSetTag_cases(?PER), - - ?line ?per_bit_opt(testExternal:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testSetTag:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testSetTag_cases(?PER)), - - ?line ?uper_bin(testExternal:compile(Config,uper_bin,[])), - ?line ?uper_bin(testSetTag:compile(Config,uper_bin,[])), - ?line ?uper_bin(testSetTag_cases(uper_bin)), - - ?line testExternal:compile(Config,?PER,[optimize]), - ?line testSetTag:compile(Config,?PER,[optimize]), - ?line testSetTag_cases(?PER). - -testSetTag_cases(Rules) -> - ?line testSetTag:main(Rules). - - - -testSetTypeRefCho(suite) -> []; -testSetTypeRefCho(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testSetTypeRefCho:compile(Config,?BER,[]), - ?line testSetTypeRefCho_cases(?BER), - - ?line ?ber_driver(?BER,testSetTypeRefCho:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSetTypeRefCho_cases(?BER)), - - ?line testSetTypeRefCho:compile(Config,?PER,[]), - ?line testSetTypeRefCho_cases(?PER), - - ?line ?per_bit_opt(testSetTypeRefCho:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testSetTypeRefCho_cases(?PER)), - - ?line ?uper_bin(testSetTypeRefCho:compile(Config,uper_bin,[])), - ?line ?uper_bin(testSetTypeRefCho_cases(uper_bin)), - - ?line testSetTypeRefCho:compile(Config,?PER,[optimize]), - ?line testSetTypeRefCho_cases(?PER). - -testSetTypeRefCho_cases(Rules) -> - ?line testSetTypeRefCho:main(Rules). - - - -testSetTypeRefPrim(suite) -> []; -testSetTypeRefPrim(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testSetTypeRefPrim:compile(Config,?BER,[]), - ?line testSetTypeRefPrim_cases(?BER), - - ?line ?ber_driver(?BER,testSetTypeRefPrim:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSetTypeRefPrim_cases(?BER)), - - ?line testSetTypeRefPrim:compile(Config,?PER,[]), - ?line testSetTypeRefPrim_cases(?PER), - - ?line ?per_bit_opt(testSetTypeRefPrim:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testSetTypeRefPrim_cases(?PER)), - - ?line ?uper_bin(testSetTypeRefPrim:compile(Config,uper_bin,[])), - ?line ?uper_bin(testSetTypeRefPrim_cases(uper_bin)), - - ?line testSetTypeRefPrim:compile(Config,?PER,[optimize]), - ?line testSetTypeRefPrim_cases(?PER). - -testSetTypeRefPrim_cases(Rules) -> - ?line testSetTypeRefPrim:main(Rules). - - - -testSetTypeRefSeq(suite) -> []; -testSetTypeRefSeq(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testSetTypeRefSeq:compile(Config,?BER,[]), - ?line testSetTypeRefSeq_cases(?BER), - - ?line ?ber_driver(?BER,testSetTypeRefSeq:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSetTypeRefSeq_cases(?BER)), - - ?line testSetTypeRefSeq:compile(Config,?PER,[]), - ?line testSetTypeRefSeq_cases(?PER), - - ?line ?per_bit_opt(testSetTypeRefSeq:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testSetTypeRefSeq_cases(?PER)), - - ?line ?uper_bin(testSetTypeRefSeq:compile(Config,uper_bin,[])), - ?line ?uper_bin(testSetTypeRefSeq_cases(uper_bin)), - - ?line testSetTypeRefSeq:compile(Config,?PER,[optimize]), - ?line testSetTypeRefSeq_cases(?PER). - -testSetTypeRefSeq_cases(Rules) -> - ?line testSetTypeRefSeq:main(Rules). - - - -testSetTypeRefSet(suite) -> []; -testSetTypeRefSet(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testSetTypeRefSet:compile(Config,?BER,[]), - ?line testSetTypeRefSet_cases(?BER), - - ?line ?ber_driver(?BER,testSetTypeRefSet:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSetTypeRefSet_cases(?BER)), - - ?line testSetTypeRefSet:compile(Config,?PER,[]), - ?line testSetTypeRefSet_cases(?PER), - - ?line ?per_bit_opt(testSetTypeRefSet:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testSetTypeRefSet_cases(?PER)), - - ?line ?uper_bin(testSetTypeRefSet:compile(Config,uper_bin,[])), - ?line ?uper_bin(testSetTypeRefSet_cases(uper_bin)), - - ?line testSetTypeRefSet:compile(Config,?PER,[optimize]), - ?line testSetTypeRefSet_cases(?PER). - -testSetTypeRefSet_cases(Rules) -> - ?line testSetTypeRefSet:main(Rules). - - - -testSetOf(suite) -> []; -testSetOf(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testSetOf:compile(Config,?BER,[]), - ?line testSetOf_cases(?BER), - - ?line ?ber_driver(?BER,testSetOf:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSetOf_cases(?BER)), - - ?line testSetOf:compile(Config,?PER,[]), - ?line testSetOf_cases(?PER), - - ?line ?per_bit_opt(testSetOf:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testSetOf_cases(?PER)), - - ?line ?uper_bin(testSetOf:compile(Config,uper_bin,[])), - ?line ?uper_bin(testSetOf_cases(uper_bin)), - - ?line testSetOf:compile(Config,?PER,[optimize]), - ?line testSetOf_cases(?PER). - -testSetOf_cases(Rules) -> - ?line testSetOf:main(Rules). - - - -testSetOfCho(suite) -> []; -testSetOfCho(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testSetOfCho:compile(Config,?BER,[]), - ?line testSetOfCho_cases(?BER), - - ?line ?ber_driver(?BER,testSetOfCho:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSetOfCho_cases(?BER)), - - ?line testSetOfCho:compile(Config,?PER,[]), - ?line testSetOfCho_cases(?PER), - - ?line ?per_bit_opt(testSetOfCho:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testSetOfCho_cases(?PER)), - - ?line ?uper_bin(testSetOfCho:compile(Config,uper_bin,[])), - ?line ?uper_bin(testSetOfCho_cases(uper_bin)), - - ?line testSetOfCho:compile(Config,?PER,[optimize]), - ?line testSetOfCho_cases(?PER). - -testSetOfCho_cases(Rules) -> - ?line testSetOfCho:main(Rules). - - -testSetOfExternal(suite) -> []; -testSetOfExternal(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testExternal:compile(Config,?BER,[]), - ?line testSetOfExternal:compile(Config,?BER,[]), - ?line testSetOfExternal_cases(?BER), - - ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSetOfExternal:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSetOfExternal_cases(?BER)), - - ?line testExternal:compile(Config,?PER,[]), - ?line testSetOfExternal:compile(Config,?PER,[]), - ?line testSetOfExternal_cases(?PER), - - ?line ?per_bit_opt(testExternal:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testSetOfExternal:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testSetOfExternal_cases(?PER)), - - ?line ?uper_bin(testExternal:compile(Config,uper_bin,[])), - ?line ?uper_bin(testSetOfExternal:compile(Config,uper_bin,[])), - ?line ?uper_bin(testSetOfExternal_cases(uper_bin)), - - ?line testExternal:compile(Config,?PER,[optimize]), - ?line testSetOfExternal:compile(Config,?PER,[optimize]), - ?line testSetOfExternal_cases(?PER). - -testSetOfExternal_cases(Rules) -> - ?line testSetOfExternal:main(Rules). - - - - -testSetOfTag(suite) -> []; -testSetOfTag(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testExternal:compile(Config,?BER,[]), - ?line testSetOfTag:compile(Config,?BER,[]), - ?line testSetOfTag_cases(?BER), - - ?line ?ber_driver(?BER,testExternal:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSetOfTag:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSetOfTag_cases(?BER)), - - ?line testExternal:compile(Config,?PER,[]), - ?line testSetOfTag:compile(Config,?PER,[]), - ?line testSetOfTag_cases(?PER), - - ?line ?per_bit_opt(testExternal:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testSetOfTag:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testSetOfTag_cases(?PER)), - - ?line ?uper_bin(testExternal:compile(Config,uper_bin,[])), - ?line ?uper_bin(testSetOfTag:compile(Config,uper_bin,[])), - ?line ?uper_bin(testSetOfTag_cases(uper_bin)), - - ?line testExternal:compile(Config,?PER,[optimize]), - ?line testSetOfTag:compile(Config,?PER,[optimize]), - ?line testSetOfTag_cases(?PER). - -testSetOfTag_cases(Rules) -> - ?line testSetOfTag:main(Rules). - - -sequence(suite) -> [{sequence,all}]. - -c_syntax(suite) -> []; -c_syntax(Config) -> - ?line DataDir% ?line testExternal:compile(Config,?PER), -% ?line testPrimExternal:compile(Config,?PER), -% ?line testPrimExternal_cases(?PER). - = ?config(data_dir,Config), - ?line _TempDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line {error,_R1} = asn1ct:compile(filename:join(DataDir,"Syntax")), - ?line {error,_R2} = asn1ct:compile(filename:join(DataDir,"BadTypeEnding")), - ?line {error,_R3} = asn1ct:compile(filename:join(DataDir, - "BadValueAssignment1")), - ?line {error,_R4} = asn1ct:compile(filename:join(DataDir, - "BadValueAssignment2")), - ?line {error,_R5} = asn1ct:compile(filename:join(DataDir, - "BadValueSet")), - ?line {error,_R6} = asn1ct:compile(filename:join(DataDir, - "ChoiceBadExtension")), - ?line {error,_R7} = asn1ct:compile(filename:join(DataDir, - "EnumerationBadExtension")), - ?line {error,_R8} = asn1ct:compile(filename:join(DataDir, - "Example")), - ?line {error,_R9} = asn1ct:compile(filename:join(DataDir, - "Export1")), - ?line {error,_R10} = asn1ct:compile(filename:join(DataDir, - "MissingEnd")), - ?line {error,_R11} = asn1ct:compile(filename:join(DataDir, - "SequenceBadComma")), - ?line {error,_R12} = asn1ct:compile(filename:join(DataDir, - "SequenceBadComponentName")), - ?line {error,_R13} = asn1ct:compile(filename:join(DataDir, - "SequenceBadComponentType")), - ?line {error,_R14} = asn1ct:compile(filename:join(DataDir, - "SeqBadComma")). - - -c_string_per(suite) -> []; -c_string_per(Config) -> - ?line DataDir = ?config(data_dir,Config), - ?line TempDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(filename:join(DataDir,"String"),[?PER,{outdir,TempDir}]). - -c_string_ber(suite) -> []; -c_string_ber(Config) -> - ?line DataDir = ?config(data_dir,Config), - ?line TempDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(filename:join(DataDir,"String"),[?BER,{outdir,TempDir}]). - - -c_implicit_before_choice(suite) -> []; -c_implicit_before_choice(Config) -> - ?line DataDir = ?config(data_dir,Config), - ?line TempDir = ?config(priv_dir,Config), - ?line {error,_R2} = asn1ct:compile(filename:join(DataDir,"CCSNARG3"),[?BER,{outdir,TempDir}]). - -parse(suite) -> []; -parse(Config) -> - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - M1 = test_modules(), -% M2 = parse_modules(), - ?line ok = parse1(M1,DataDir,OutDir). - -parse1([M|T],DataDir,OutDir) -> - ?line ok = asn1ct:compile(DataDir ++ M,[abs,{outdir,OutDir}]), - parse1(T,DataDir,OutDir); -parse1([],_,_) -> - ok. - -per(suite) -> []; -per(Config) -> - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = per1(per_modules(),DataDir,OutDir), - ?line ?per_bit_opt(per1_bit_opt(per_modules(),DataDir,OutDir)), - ?line ok = per1_opt(per_modules(),DataDir,OutDir). - - -per1([M|T],DataDir,OutDir) -> - ?line ok = asn1ct:compile(DataDir ++ M,[?PER,{outdir,OutDir}]), - ?line ok = asn1ct:test(list_to_atom(M)), - per1(T,DataDir,OutDir); -per1([],_,_) -> - ok. - -per1_bit_opt([M|T],DataDir,OutDir) -> - ?line ok = asn1ct:compile(DataDir ++ M,[?PER,optimize,{outdir,OutDir}]), - ?line ok = asn1ct:test(list_to_atom(M)), - per1_bit_opt(T,DataDir,OutDir); -per1_bit_opt([],_,_) -> - ok. - -per1_opt([M|T],DataDir,OutDir) -> - ?line ok = asn1ct:compile(DataDir ++ M,[?PER,optimized,{outdir,OutDir}]), - ?line ok = asn1ct:test(list_to_atom(M)), - per1_opt(T,DataDir,OutDir); -per1_opt([],_,_) -> - ok. - -ber_choiceinseq(suite) ->[]; -ber_choiceinseq(Config) -> - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(filename:join(DataDir,"ChoiceInSeq"),[?BER,{outdir,OutDir}]). - -ber_optional(suite) ->[]; -ber_optional(Config) -> - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(filename:join(DataDir,"SOpttest"),[?BER,{outdir,OutDir}]), - ?line V = {'S',{'A',10,asn1_NOVALUE,asn1_NOVALUE}, - {'B',asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE}, - {'C',asn1_NOVALUE,111,asn1_NOVALUE}}, - ?line {ok,B} = asn1_wrapper:encode('SOpttest','S',V), - ?line Bytes = lists:flatten(B), - ?line V2 = asn1_wrapper:decode('SOpttest','S',Bytes), - ?line ok = eq(V,element(2,V2)). - -ber_optional_keyed_list(suite) ->[]; -ber_optional_keyed_list(Config) -> - case ?BER of - ber_bin_v2 -> ok; - _ -> - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(filename:join(DataDir,"SOpttest"), - [?BER,keyed_list,{outdir,OutDir}]), - ?line Vrecord = {'S',{'A',10,asn1_NOVALUE,asn1_NOVALUE}, - {'B',asn1_NOVALUE,asn1_NOVALUE,asn1_NOVALUE}, - {'C',asn1_NOVALUE,111,asn1_NOVALUE}}, - ?line V = [ {a,[{scriptKey,10}]}, - {b,[]}, - {c,[{callingPartysCategory,111}]} ], - ?line {ok,B} = asn1_wrapper:encode('SOpttest','S',V), - ?line Bytes = lists:flatten(B), - ?line V2 = asn1_wrapper:decode('SOpttest','S',Bytes), - ?line ok = eq(Vrecord,element(2,V2)) - end. - - -eq(V,V) -> - ok. - - -ber_other(suite) ->[]; -ber_other(Config) -> - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = ber1(ber_modules(),DataDir,OutDir). - - -ber1([M|T],DataDir,OutDir) -> - ?line ok = asn1ct:compile(DataDir ++ M,[?BER,{outdir,OutDir}]), - ?line ok = asn1ct:test(list_to_atom(M)), - ber1(T,DataDir,OutDir); -ber1([],_,_) -> - ok. - -default_per(suite) ->[]; -default_per(Config) -> - default1(?PER,Config,[]). - -default_per_opt(suite) -> []; -default_per_opt(Config) -> - ?per_bit_opt(default1(?PER,Config,[optimize])), - default1(?PER,Config,[optimize]). - -default_ber(suite) ->[]; -default_ber(Config) -> - default1(?BER,Config,[]). - -default1(Rule,Config,Options) -> - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "Def",[Rule,{outdir,OutDir}]++Options), - ?line {ok,Bytes1} = asn1_wrapper:encode('Def','Def1',#'Def1'{bool0 = true, - bool1 = true, - bool2 = true, - bool3 = true}), - ?line {ok,{'Def1',true,true,true,true}} = asn1_wrapper:decode('Def','Def1',lists:flatten(Bytes1)), - - ?line {ok,Bytes2} = asn1_wrapper:encode('Def','Def1',#'Def1'{bool0 = true}), - ?line {ok,{'Def1',true,false,false,false}} = asn1_wrapper:decode('Def','Def1',lists:flatten(Bytes2)), - - ?line {ok,Bytes3} = asn1_wrapper:encode('Def','Def1',#'Def1'{bool0 = true,bool2=false}), - ?line {ok,{'Def1',true,false,false,false}} = asn1_wrapper:decode('Def','Def1',lists:flatten(Bytes3)). - - -value_test(suite) ->[]; -value_test(Config) -> - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "ObjIdValues",[?BER,{outdir,OutDir}]), - ?line {ok,_} = asn1_wrapper:encode('ObjIdValues','ObjIdType','ObjIdValues':'mobileDomainId'()), - ?line ok = asn1ct:compile(DataDir ++ "ObjIdValues",[?PER,{outdir,OutDir}]), - ?line {ok,_} = asn1_wrapper:encode('ObjIdValues','ObjIdType','ObjIdValues':'mobileDomainId'()), - ?line ok = test_bad_values:tests(Config), - ok. - - -constructed(suite) -> - []; -constructed(Config) -> - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "Constructed",[?BER,{outdir,OutDir}]), - ?line {ok,B} = asn1_wrapper:encode('Constructed','S',{'S',false}), - ?line [40,3,1,1,0] = lists:flatten(B), - ?line {ok,B1} = asn1_wrapper:encode('Constructed','S2',{'S2',false}), - ?line [40,5,48,3,1,1,0] = lists:flatten(B1), - ?line {ok,B2} = asn1_wrapper:encode('Constructed','I',10), - ?line [136,1,10] = lists:flatten(B2), - ok. - -ber_decode_error(suite) -> []; -ber_decode_error(Config) -> - ?line ok = ber_decode_error:compile(Config,?BER,[]), - ?line ok = ber_decode_error:run([]), - - ?line ok = ?ber_driver(?BER,ber_decode_error:compile(Config,?BER,[driver])), - ?line ok = ?ber_driver(?BER,ber_decode_error:run([driver])), - ok. - -h323test(suite) -> - []; -h323test(Config) -> - ?line ok = h323test:compile(Config,?PER,[]), - ?line ok = h323test:run(?PER), - ?line ?per_bit_opt(h323test:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(h323test:run(?PER)), - ?line ?uper_bin(h323test:compile(Config,uper_bin,[])), - ?line ?uper_bin(h323test:run(uper_bin)), - ?line ok = h323test:compile(Config,?PER,[optimize]), - ?line ok = h323test:run(?PER), - ok. - -per_GeneralString(suite) -> - []; -per_GeneralString(Config) -> - case erlang:module_loaded('MULTIMEDIA-SYSTEM-CONTROL') of - true -> - ok; - false -> - h323test:compile(Config,?PER,[]) - end, - UI = [109,64,1,57], - ?line {ok,_V} = asn1_wrapper:decode('MULTIMEDIA-SYSTEM-CONTROL', - 'MultimediaSystemControlMessage',UI). - -per_open_type(suite) -> - []; -per_open_type(Config) -> - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line ok = asn1ct:compile(DataDir ++ "OpenType",[?PER,{outdir,OutDir}]), - Stype = {'Stype',10,true}, - ?line {ok,Bytes} = asn1_wrapper:encode('OpenType','Ot',Stype), - ?line {ok,Stype} = asn1_wrapper:decode('OpenType','Ot',Bytes), - - ?line ?per_bit_opt(ok = asn1ct:compile(DataDir ++ "OpenType", - [?PER,optimize,{outdir,OutDir}])), - ?line ?per_bit_opt({ok,Bytes}=asn1_wrapper:encode('OpenType','Ot',Stype)), - ?line ?per_bit_opt({ok,Stype}=asn1_wrapper:decode('OpenType','Ot',Bytes)), - - ?line ?uper_bin(ok = asn1ct:compile(DataDir ++ "OpenType", - [uper_bin,{outdir,OutDir}])), - ?line ?uper_bin({ok,Bytes}=asn1_wrapper:encode('OpenType','Ot',Stype)), - ?line ?uper_bin({ok,Stype}=asn1_wrapper:decode('OpenType','Ot',Bytes)), - - ?line ok = asn1ct:compile(DataDir ++ "OpenType", - [?PER,optimize,{outdir,OutDir}]), - ?line {ok,Bytes} = asn1_wrapper:encode('OpenType','Ot',Stype), - ?line {ok,Stype} = asn1_wrapper:decode('OpenType','Ot',Bytes). - -testConstraints(suite) -> - []; -testConstraints(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testConstraints:compile(Config,?BER,[]), - ?line testConstraints:int_constraints(?BER), - - ?line ?ber_driver(?BER,testConstraints:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testConstraints:int_constraints(?BER)), - - ?line testConstraints:compile(Config,?PER,[]), - ?line testConstraints:int_constraints(?PER), - ?line testConstraints:refed_NNL_name(?PER), - - ?line ?per_bit_opt(testConstraints:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testConstraints:int_constraints(?PER)), - ?line ?per_bit_opt(testConstraints:refed_NNL_name(?PER)), - - ?line ?uper_bin(testConstraints:compile(Config,uper_bin,[])), - ?line ?uper_bin(testConstraints:int_constraints(uper_bin)), - ?line ?uper_bin(testConstraints:refed_NNL_name(uper_bin)), - - ?line testConstraints:compile(Config,?PER,[optimize]), - ?line testConstraints:int_constraints(?PER), - ?line testConstraints:refed_NNL_name(?PER). - -testSeqIndefinite(suite) -> []; -testSeqIndefinite(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testSeqIndefinite:compile(Config,?BER,[]), - ?line testSeqIndefinite:main(?BER), - - ?line ?ber_driver(?BER,testSeqIndefinite:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSeqIndefinite:main(?BER)). - -testSetIndefinite(suite) -> []; -testSetIndefinite(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testSetIndefinite:compile(Config,?BER,[]), - ?line testSetIndefinite:main(?BER), - - ?line ?ber_driver(?BER,testSetIndefinite:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testSetIndefinite:main(?BER)). - -testChoiceIndefinite(suite) -> []; -testChoiceIndefinite(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testChoiceIndefinite:compile(Config,?BER,[]), - ?line testChoiceIndefinite:main(?BER), - - ?line ?ber_driver(?BER,testChoiceIndefinite:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testChoiceIndefinite:main(?BER)). - -testInfObjectClass(suite) -> - []; -testInfObjectClass(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testInfObjectClass:compile(Config,?PER,[]), - ?line testInfObjectClass:main(?PER), - ?line testInfObj:compile(Config,?PER,[]), - ?line testInfObj:main(?PER), - - ?line ?per_bit_opt(testInfObjectClass:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testInfObjectClass:main(?PER)), - ?line ?per_bit_opt(testInfObj:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testInfObj:main(?PER)), - - ?line ?uper_bin(testInfObjectClass:compile(Config,uper_bin,[])), - ?line ?uper_bin(testInfObjectClass:main(uper_bin)), - ?line ?uper_bin(testInfObj:compile(Config,uper_bin,[])), - ?line ?uper_bin(testInfObj:main(uper_bin)), - - ?line testInfObjectClass:compile(Config,?PER,[optimize]), - ?line testInfObjectClass:main(?PER), - ?line testInfObj:compile(Config,?PER,[optimize]), - ?line testInfObj:main(?PER), - - ?line testInfObjectClass:compile(Config,?BER,[]), - ?line testInfObjectClass:main(?BER), - ?line testInfObj:compile(Config,?BER,[]), - ?line testInfObj:main(?BER), - - ?line ?ber_driver(?BER,testInfObjectClass:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testInfObjectClass:main(?BER)), - ?line ?ber_driver(?BER,testInfObj:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testInfObj:main(?BER)), - - ?line testInfObj:compile_RANAPfiles(Config,?PER,[]), - - ?line ?per_bit_opt(testInfObj:compile_RANAPfiles(Config,?PER,[optimize])), - - ?line ?uper_bin(testInfObj:compile_RANAPfiles(Config,uper_bin,[])), - - ?line testInfObj:compile_RANAPfiles(Config,?PER,[optimize]), - - ?line testInfObj:compile_RANAPfiles(Config,?BER,[]). - -testParameterizedInfObj(suite) -> - []; -testParameterizedInfObj(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testParameterizedInfObj:compile(Config,?PER,[]), - ?line testParameterizedInfObj:main(?PER), - - ?line ?per_bit_opt(testParameterizedInfObj:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testParameterizedInfObj:main(?PER)), - - ?line ?uper_bin(testParameterizedInfObj:compile(Config,uper_bin,[])), - ?line ?uper_bin(testParameterizedInfObj:main(uper_bin)), - - ?line testParameterizedInfObj:compile(Config,?PER,[optimize]), - ?line testParameterizedInfObj:main(?PER), - - ?line testParameterizedInfObj:compile(Config,?BER,[]), - ?line testParameterizedInfObj:main(?BER), - - ?line ?ber_driver(?BER,testParameterizedInfObj:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testParameterizedInfObj:main(?BER)). - -testMergeCompile(suite) -> - []; -testMergeCompile(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testMergeCompile:compile(Config,?PER,[]), - ?line testMergeCompile:main(?PER), - ?line testMergeCompile:mvrasn(?PER), - - ?line ?per_bit_opt(testMergeCompile:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testMergeCompile:main(?PER)), - ?line ?per_bit_opt(testMergeCompile:mvrasn(?PER)), - - ?line ?uper_bin(testMergeCompile:compile(Config,uper_bin,[])), - ?line ?uper_bin(testMergeCompile:main(uper_bin)), - ?line ?uper_bin(testMergeCompile:mvrasn(uper_bin)), - - ?line testMergeCompile:compile(Config,?BER,[]), - ?line testMergeCompile:main(?BER), - ?line testMergeCompile:mvrasn(?BER), - - ?line ?ber_driver(?BER,testMergeCompile:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testMergeCompile:main(?BER)), - ?line ?ber_driver(?BER,testMergeCompile:mvrasn(?BER)). - -testobj(suite) -> - []; -testobj(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line ok = testRANAP:compile(Config,?PER,[]), - ?line ok = testRANAP:testobj(?PER), - ?line ok = testParameterizedInfObj:ranap(?PER), - - ?line ?per_bit_opt(ok = testRANAP:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(ok = testRANAP:testobj(?PER)), - ?line ?per_bit_opt(ok = testParameterizedInfObj:ranap(?PER)), - - ?line ?uper_bin(ok = testRANAP:compile(Config,uper_bin,[])), - ?line ?uper_bin(ok = testRANAP:testobj(uper_bin)), - ?line ?uper_bin(ok = testParameterizedInfObj:ranap(uper_bin)), - - ?line ok = testRANAP:compile(Config,?PER,[optimize]), - ?line ok = testRANAP:testobj(?PER), - ?line ok = testParameterizedInfObj:ranap(?PER), - - ?line ok = testRANAP:compile(Config,?BER,[]), - ?line ok = testRANAP:testobj(?BER), - ?line ok = testParameterizedInfObj:ranap(?BER), - - ?line ?ber_driver(?BER,testRANAP:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testRANAP:testobj(?BER)), - ?line ?ber_driver(?BER,testParameterizedInfObj:ranap(?BER)). - - -testDeepTConstr(suite) -> - []; -testDeepTConstr(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testDeepTConstr:compile(Config,?PER,[]), - ?line testDeepTConstr:main(?PER), - - ?line ?per_bit_opt(testDeepTConstr:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testDeepTConstr:main(?PER)), - - ?line ?uper_bin(testDeepTConstr:compile(Config,uper_bin,[])), - ?line ?uper_bin(testDeepTConstr:main(uper_bin)), - - ?line testDeepTConstr:compile(Config,?PER,[optimize]), - ?line testDeepTConstr:main(?PER), - - ?line testDeepTConstr:compile(Config,?BER,[]), - ?line testDeepTConstr:main(?BER), - - ?line ?ber_driver(?BER,testDeepTConstr:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testDeepTConstr:main(?BER)). - -testInvokeMod(suite) -> - []; -testInvokeMod(Config) -> - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line ok = asn1ct:compile(filename:join(DataDir,"PrimStrings"),[{outdir,OutDir}]), - ?line {ok,_Result1} = 'PrimStrings':encode('Bs1',[1,0,1,0]), - ?line ok = asn1ct:compile(filename:join(DataDir,"PrimStrings"),[?PER,{outdir,OutDir}]), - ?line {ok,_Result2} = 'PrimStrings':encode('Bs1',[1,0,1,0]). - -testExport(suite) -> - []; -testExport(Config) -> - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line {error,{asn1,_Reason}} = asn1ct:compile(filename:join(DataDir,"IllegalExport"),[{outdir,OutDir}]). - -testImport(suite) -> - []; -testImport(Config) -> - ?line DataDir = ?config(data_dir,Config), - ?line _OutDir = ?config(priv_dir,Config), - ?line {error,_} = asn1ct:compile(filename:join(DataDir,"ImportsFrom"),[?BER]), - ok. - -testMegaco(suite) -> - []; -testMegaco(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - io:format("Config: ~p~n",[Config]), - ?line {ok,ModuleName1,ModuleName2} = testMegaco:compile(Config,?BER,[]), - ?line ok = testMegaco:main(ModuleName1,Config), - ?line ok = testMegaco:main(ModuleName2,Config), - - case ?BER of - ber_bin_v2 -> - ?line {ok,ModuleName3,ModuleName4} = testMegaco:compile(Config,?BER,[driver]), - ?line ok = testMegaco:main(ModuleName3,Config), - ?line ok = testMegaco:main(ModuleName4,Config); - _-> ok - end, - - ?line {ok,ModuleName5,ModuleName6} = testMegaco:compile(Config,?PER,[]), - ?line ok = testMegaco:main(ModuleName5,Config), - ?line ok = testMegaco:main(ModuleName6,Config), - - ?line ?per_bit_opt({ok,ModuleName5,ModuleName6} = testMegaco:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(ok = testMegaco:main(ModuleName5,Config)), - ?line ?per_bit_opt(ok = testMegaco:main(ModuleName6,Config)), - - ?line ?uper_bin({ok,ModuleName5,ModuleName6} = testMegaco:compile(Config,uper_bin,[])), - ?line ?uper_bin(ok = testMegaco:main(ModuleName5,Config)), - ?line ?uper_bin(ok = testMegaco:main(ModuleName6,Config)), - - ?line {ok,ModuleName7,ModuleName8} = testMegaco:compile(Config,?PER,[optimize]), - ?line ok = testMegaco:main(ModuleName7,Config), - ?line ok = testMegaco:main(ModuleName8,Config). - - -testMvrasn6(suite) -> []; -testMvrasn6(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testMvrasn6:compile(Config,?BER), - ?line testMvrasn6:main(). - -testContextSwitchingTypes(suite) -> []; -testContextSwitchingTypes(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testContextSwitchingTypes:compile(Config,?BER,[]), - ?line testContextSwitchingTypes:test(), - - ?line ?ber_driver(?BER,testContextSwitchingTypes:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testContextSwitchingTypes:test()), - - ?line testContextSwitchingTypes:compile(Config,?PER,[]), - ?line testContextSwitchingTypes:test(), - - ?line ?per_bit_opt(testContextSwitchingTypes:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testContextSwitchingTypes:test()), - - ?line ?uper_bin(testContextSwitchingTypes:compile(Config,uper_bin,[])), - ?line ?uper_bin(testContextSwitchingTypes:test()), - - ?line testContextSwitchingTypes:compile(Config,?PER,[optimize]), - ?line testContextSwitchingTypes:test(). - -testTypeValueNotation(suite) -> []; -testTypeValueNotation(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - case ?BER of - Ber when Ber == ber; Ber == ber_bin -> - ?line testTypeValueNotation:compile(Config,?BER,[]), - ?line testTypeValueNotation:main(?BER,dummy); - _ -> - ok - end, - - ?line ?ber_driver(?BER,testTypeValueNotation:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testTypeValueNotation:main(?BER,optimize)), - - case ?BER of - Ber2 when Ber2 == ber; Ber2 == ber_bin -> - ?line testTypeValueNotation:compile(Config,?PER,[]), - ?line testTypeValueNotation:main(?PER,dummy); - _ -> - ok - end, - - ?line ?per_bit_opt(testTypeValueNotation:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testTypeValueNotation:main(?PER,optimize)), - - ?line ?uper_bin(testTypeValueNotation:compile(Config,uper_bin,[])), - ?line ?uper_bin(testTypeValueNotation:main(uper_bin,optimize)), - case ?BER of - Ber3 when Ber3 == ber; Ber3 == ber_bin -> - ?line testTypeValueNotation:compile(Config,?PER,[optimize]), - ?line testTypeValueNotation:main(?PER,optimize); - _ -> - ok - end. - -testOpenTypeImplicitTag(suite) -> []; -testOpenTypeImplicitTag(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testOpenTypeImplicitTag:compile(Config,?BER,[]), - ?line testOpenTypeImplicitTag:main(?BER), - - ?line ?ber_driver(?BER,testOpenTypeImplicitTag:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testOpenTypeImplicitTag:main(?BER)), - - ?line testOpenTypeImplicitTag:compile(Config,?PER,[]), - ?line testOpenTypeImplicitTag:main(?PER), - - ?line ?per_bit_opt(testOpenTypeImplicitTag:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testOpenTypeImplicitTag:main(?PER)), - - ?line ?uper_bin(testOpenTypeImplicitTag:compile(Config,uper_bin,[])), - ?line ?uper_bin(testOpenTypeImplicitTag:main(uper_bin)), - - ?line testOpenTypeImplicitTag:compile(Config,?PER,[optimize]), - ?line testOpenTypeImplicitTag:main(?PER). - -duplicate_tags(suite) -> []; -duplicate_tags(Config) -> - ?line DataDir = ?config(data_dir,Config), - {error,{asn1,[{error,{type,_,_,'SeqOpt1Imp',{asn1,{duplicates_of_the_tags,_}}}}]}} = - asn1ct:compile(filename:join(DataDir,"SeqOptional2"),[abs]), - ok. - -rtUI(suite) -> []; -rtUI(Config) -> - ?line DataDir = ?config(data_dir,Config), - ?line ok = asn1ct:compile(filename:join(DataDir,"Prim"),[?BER]), - ?line {ok,_} = asn1rt:info('Prim'), - - ?line ok = asn1ct:compile(filename:join(DataDir,"Prim"),[?PER]), - ?line {ok,_} = asn1rt:info('Prim'). - -testROSE(suite) -> []; -testROSE(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testROSE:compile(Config,?BER,[]), - - ?line testROSE:compile(Config,?PER,[]), - ?line ?per_bit_opt(testROSE:compile(Config,?PER,[optimize])), - ?line ?uper_bin(testROSE:compile(Config,uper_bin,[])), - ?line testROSE:compile(Config,?PER,[optimize]). - -testINSTANCE_OF(suite) -> []; -testINSTANCE_OF(Config) -> - ?line testINSTANCE_OF:compile(Config,?BER,[]), - ?line testINSTANCE_OF:main(?BER), - - ?line ?ber_driver(?BER,testINSTANCE_OF:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testINSTANCE_OF:main(?BER)), - - ?line testINSTANCE_OF:compile(Config,?PER,[]), - ?line testINSTANCE_OF:main(?PER), - - ?line ?per_bit_opt(testINSTANCE_OF:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testINSTANCE_OF:main(?PER)), - - ?line ?uper_bin(testINSTANCE_OF:compile(Config,uper_bin,[])), - ?line ?uper_bin(testINSTANCE_OF:main(uper_bin)), - - ?line testINSTANCE_OF:compile(Config,?PER,[optimize]), - ?line testINSTANCE_OF:main(?PER). - -testTCAP(suite) -> []; -testTCAP(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testTCAP:compile(Config,?BER,[]), - ?line testTCAP:test(?BER,Config), - - ?line ?ber_driver(?BER,testTCAP:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testTCAP:test(?BER,Config)), - - ?line ?ber_driver(?BER,testTCAP:compile_asn1config(Config,?BER,[asn1config])), - ?line ?ber_driver(?BER,testTCAP:test_asn1config()). - -testDER(suite) ->[]; -testDER(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line testDER:compile(Config,?BER,[]), - ?line testDER:test(), - - ?line ?ber_driver(?BER,testDER:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testDER:test()), - - ?line testParamBasic:compile_der(Config,?BER), - ?line testParamBasic_cases(der), - - - ?line testSeqSetDefaultVal:compile(Config,?BER), - ?line testSeqSetDefaultVal_cases(?BER). - -testSeqSetDefaultVal_cases(?BER) -> - ?line testSeqSetDefaultVal:main(?BER). - - -specialized_decodes(suite) -> []; -specialized_decodes(Config) -> - ?line test_partial_incomplete_decode:compile(Config,?BER,[optimize]), - ?line test_partial_incomplete_decode:test(?BER,Config), - ?line test_selective_decode:test(?BER,Config). - -special_decode_performance(suite) ->[]; -special_decode_performance(Config) -> - ?line ?ber_driver(?BER,test_special_decode_performance:compile(Config,?BER)), - ?line ?ber_driver(?BER,test_special_decode_performance:go(all)). - - -test_driver_load(suite) -> []; -test_driver_load(Config) -> - ?line test_driver_load:compile(Config,?PER), - ?line test_driver_load:test(?PER,5). - -test_ParamTypeInfObj(suite) -> []; -test_ParamTypeInfObj(Config) -> - ?line DataDir = ?config(data_dir,Config), - ?line ok = asn1ct:compile(filename:join(DataDir,"IN-CS-1-Datatypes"),[ber_bin]). - -test_WS_ParamClass(suite) -> []; -test_WS_ParamClass(Config) -> - ?line DataDir = ?config(data_dir,Config), - ?line ok = asn1ct:compile(filename:join(DataDir,"InformationFramework"), - [ber_bin]). - -test_Defed_ObjectIdentifier(suite) -> []; -test_Defed_ObjectIdentifier(Config) -> - ?line DataDir = ?config(data_dir,Config), - ?line ok = asn1ct:compile(filename:join(DataDir,"UsefulDefinitions"), - [ber_bin]). - -testSelectionType(suite) -> []; -testSelectionType(Config) -> - - ?line ok = testSelectionTypes:compile(Config,?BER,[]), - ?line {ok,_} = testSelectionTypes:test(), - - ?line ok = testSelectionTypes:compile(Config,?PER,[]), - ?line {ok,_} = testSelectionTypes:test(). - -testSSLspecs(suite) -> []; -testSSLspecs(Config) -> - - ?line ok = testSSLspecs:compile(Config,?BER, - [optimize,compact_bit_string,der]), - ?line testSSLspecs:run(?BER), - - case code:which(asn1ct) of - cover_compiled -> - ok; - _ -> - ?line ok = testSSLspecs:compile_inline(Config,?BER), - ?line ok = testSSLspecs:run_inline(?BER) - end. - -testNortel(suite) -> []; -testNortel(Config) -> - ?line DataDir = ?config(data_dir,Config), - - ?line ok = asn1ct:compile(filename:join(DataDir,"Nortel"),[?BER]), - ?line ok = asn1ct:compile(filename:join(DataDir,"Nortel"), - [?BER,optimize]), - ?line ok = asn1ct:compile(filename:join(DataDir,"Nortel"), - [?BER,optimize,driver]), - ?line ok = asn1ct:compile(filename:join(DataDir,"Nortel"),[?PER]), - ?line ?per_bit_opt(ok = asn1ct:compile(filename:join(DataDir,"Nortel"), - [?PER,optimize])), - ?line ?uper_bin(ok = asn1ct:compile(filename:join(DataDir,"Nortel"),[uper_bin])), - ?line ok = asn1ct:compile(filename:join(DataDir,"Nortel"), - [?PER,optimize]). -test_undecoded_rest(suite) -> []; -test_undecoded_rest(Config) -> - - ?line ok = test_undecoded_rest:compile(Config,?BER,[]), - ?line ok = test_undecoded_rest:test([]), - - ?line ok = test_undecoded_rest:compile(Config,?BER,[undec_rest]), - ?line ok = test_undecoded_rest:test(undec_rest), - - ?line ok = test_undecoded_rest:compile(Config,?PER,[]), - ?line ok = test_undecoded_rest:test([]), - - ?line ?per_bit_opt(ok = test_undecoded_rest:compile(Config,?PER,[optimize,undec_rest])), - ?line ?per_bit_opt(ok = test_undecoded_rest:test(undec_rest)), - - ?line ?uper_bin(ok = test_undecoded_rest:compile(Config,uper_bin,[undec_rest])), - ?line ?uper_bin(ok = test_undecoded_rest:test(undec_rest)), - - ?line ok = test_undecoded_rest:compile(Config,?PER,[undec_rest]), - ?line ok = test_undecoded_rest:test(undec_rest). - -test_inline(suite) -> []; -test_inline(Config) -> - case code:which(asn1ct) of - cover_compiled -> - {skip,"Not runnable when cover compiled"}; - _ -> - ?line ok=test_inline:compile(Config,?BER,[]), - ?line test_inline:main(?BER), - ?line test_inline:inline1(Config,?BER,[]), - ?line test_inline:performance2() - end. - -%test_inline_prf(suite) -> []; -%test_inline_prf(Config) -> -% ?line test_inline:performance(Config). - -testTcapsystem(suite) -> []; -testTcapsystem(Config) -> - ?line ok=testTcapsystem:compile(Config,?BER,[]). - -testNBAPsystem(suite) -> []; -testNBAPsystem(Config) -> - ?line ok=testNBAPsystem:compile(Config,?PER,?per_optimize(?BER)), - ?line ok=testNBAPsystem:test(?PER,Config). - -test_compile_options(suite) -> []; -test_compile_options(Config) -> - case code:which(asn1ct) of - cover_compiled -> - {skip,"Not runnable when cover compiled"}; - _ -> - ?line ok = test_compile_options:wrong_path(Config), - ?line ok = test_compile_options:path(Config), - ?line ok = test_compile_options:noobj(Config), - ?line ok = test_compile_options:record_name_prefix(Config), - ?line ok = test_compile_options:verbose(Config), - ?line ok = test_compile_options:warnings_as_errors(Config) - end. - -testDoubleEllipses(suite) -> []; -testDoubleEllipses(Config) -> - ?line testDoubleEllipses:compile(Config,?BER,[]), - ?line testDoubleEllipses:main(?BER), - ?line ?ber_driver(?BER,testDoubleEllipses:compile(Config,?BER,[driver])), - ?line ?ber_driver(?BER,testDoubleEllipses:main(?BER)), - ?line ?per_bit_opt(testDoubleEllipses:compile(Config,?PER,[optimize])), - ?line ?per_bit_opt(testDoubleEllipses:main(?PER)), - ?line ?uper_bin(testDoubleEllipses:compile(Config,uper_bin,[])), - ?line ?uper_bin(testDoubleEllipses:main(uper_bin)), - ?line testDoubleEllipses:compile(Config,?PER,?per_optimize(?BER)), - ?line testDoubleEllipses:main(?PER). - -test_modified_x420(suite) -> []; -test_modified_x420(Config) -> - ?line test_modified_x420:compile(Config), - ?line test_modified_x420:test_io(Config). - -testX420(suite) -> []; -testX420(Config) -> - ?line testX420:compile(?BER,[der],Config), - ?line ok = testX420:ticket7759(?BER,Config), - ?line testX420:compile(?PER,[],Config). - -test_x691(suite) -> []; -test_x691(Config) -> - case ?PER of - per -> - ?line ok = test_x691:compile(Config,uper_bin,[]), - ?line true = test_x691:cases(uper_bin,unaligned), - ?line ok = test_x691:compile(Config,?PER,[]), - ?line true = test_x691:cases(?PER,aligned), -%% ?line ok = asn1_test_lib:ticket_7678(Config,[]), - ?line ok = asn1_test_lib:ticket_7708(Config,[]), - ?line ok = asn1_test_lib:ticket_7763(Config); - _ -> - ?line ok = test_x691:compile(Config,?PER,?per_optimize(?BER)), - ?line true = test_x691:cases(?PER,aligned) - end. -%% ?line ok = asn1_test_lib:ticket_7876(Config,?PER,[]), -%% ?line ok = asn1_test_lib:ticket_7876(Config,?PER,[compact_bit_string]), -%% ?line ok = asn1_test_lib:ticket_7876(Config,?PER,[optimize]), -%% ?line ok = asn1_test_lib:ticket_7876(Config,?PER,[optimize,compact_bit_string]). - - -ticket_6143(suite) -> []; -ticket_6143(Config) -> - ?line ok = test_compile_options:ticket_6143(Config). - -testExtensionAdditionGroup(suite) -> []; -testExtensionAdditionGroup(Config) -> - ?line DataDir = ?config(data_dir,Config), - ?line PrivDir = ?config(priv_dir,Config), - ?line Path = code:get_path(), - ?line code:add_patha(PrivDir), - DoIt = fun(Erule) -> - ?line ok = asn1ct:compile(filename:join(DataDir,"Extension-Addition-Group"),Erule ++ [{outdir,PrivDir}]), - ?line {ok,_M} = compile:file(filename:join(DataDir,"extensionAdditionGroup"),[{i,PrivDir},{outdir,PrivDir},debug_info]), - ?line ok = extensionAdditionGroup:run(Erule), - ?line ok = extensionAdditionGroup:run2(Erule), - ?line ok = asn1ct:compile(filename:join(DataDir,"EUTRA-RRC-Definitions"),Erule ++ [{record_name_prefix,"RRC-"},{outdir,PrivDir}]), - ?line ok = extensionAdditionGroup:run3(Erule) - end, - ?line [DoIt(Rule)|| Rule <- [[per_bin],[per_bin,optimize],[uper_bin]]], - %% FIXME problems with automatic tags [ber_bin],[ber_bin,optimize] - ?line code:set_path(Path). - - - -% parse_modules() -> -% ["ImportsFrom"]. - -per_modules() -> - [X || X <- test_modules()]. -ber_modules() -> - [X || X <- test_modules(), - X =/= "CommonDataTypes", - X =/= "DS-EquipmentUser-CommonFunctionOrig-TransmissionPath", - X =/= "H323-MESSAGES", - X =/= "H235-SECURITY-MESSAGES", - X =/= "MULTIMEDIA-SYSTEM-CONTROL"]. -test_modules() -> - _Modules = [ - "BitStr", - "CAP", - "CommonDataTypes", - "Constraints", - "ContextSwitchingTypes", - "DS-EquipmentUser-CommonFunctionOrig-TransmissionPath", - "Enum", - "From", - "H235-SECURITY-MESSAGES", - "H323-MESSAGES", - %%"MULTIMEDIA-SYSTEM-CONTROL", recursive type , problem for asn1ct:value - "Import", - "Int", - "MAP-commonDataTypes", -% ambigous tags "MAP-insertSubscriberData-def", - "Null", - "Octetstr", - "One", - "P-Record", - "P", -% "PDUs", - "Person", - "PrimStrings", - "Real", - "XSeq", - "XSeqOf", - "XSet", - "XSetOf", - "String", - "SwCDR", -% "Syntax", - "Time" -% ANY "Tst", -% "Two", -% errors that should be detected "UndefType" -] ++ - [ - "SeqSetLib", % must be compiled before Seq and Set - "Seq", - "Set", - "SetOf", - "SeqOf", - "Prim", - "Cho", - "Def", - "Opt", - "ELDAPv3", - "LDAP" - ]. - -test_OTP_9688(Config) -> - Asn1Mod = "OTP-9688.asn1", - %%DataDir = ?config(data_dir,Config), - PrivDir = ?config(priv_dir,Config), - Data = " -OTP-9688 DEFINITIONS ::= BEGIN - - foo INTEGER ::= 1 - bar INTEGER ::= 42 - - Baz ::= INTEGER {x-y-z1(foo), x-y-z2(bar)} - Qux ::= SEQUENCE {flerpInfo SEQUENCE {x INTEGER (-10 | -9 | (0..4))} OPTIONAL} - -END -", - File = filename:join(PrivDir,Asn1Mod), - ok = file:write_file(File, Data), - %% Does it compile with changes to asn1ct_check and asn1ct_gen_per_rt2ct? - %% (see ticket) - ok = asn1ct:compile(File, [{outdir, PrivDir}]). diff --git a/lib/asn1/test/asn1_app_test.erl b/lib/asn1/test/asn1_app_test.erl index c3797f08b2..2c31c3259d 100644 --- a/lib/asn1/test/asn1_app_test.erl +++ b/lib/asn1/test/asn1_app_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2010. All Rights Reserved. +%% Copyright Ericsson AB 2005-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -138,7 +138,7 @@ check_asn1ct_modules(Extra) -> asn1ct_name,asn1ct_constructed_per,asn1ct_constructed_ber, asn1ct_gen_ber,asn1ct_constructed_ber_bin_v2, asn1ct_gen_ber_bin_v2,asn1ct_value, - asn1ct_tok,asn1ct_parser2], + asn1ct_tok,asn1ct_parser2,asn1ct_table], case Extra -- ASN1CTMods of [] -> ok; diff --git a/lib/asn1/test/asn1_bin_particular_SUITE.erl.src b/lib/asn1/test/asn1_bin_particular_SUITE.erl.src deleted file mode 100644 index 0e153238ad..0000000000 --- a/lib/asn1/test/asn1_bin_particular_SUITE.erl.src +++ /dev/null @@ -1,2 +0,0 @@ - -particular() -> []. diff --git a/lib/asn1/test/asn1_common_SUITE.erl.src b/lib/asn1/test/asn1_common_SUITE.erl.src deleted file mode 100644 index 12512606d8..0000000000 --- a/lib/asn1/test/asn1_common_SUITE.erl.src +++ /dev/null @@ -1,95 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2005-2011. All Rights Reserved. -%% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%% -%% %CopyrightEnd% -%% -%% - -common() -> [{group,app_test}, {group,appup_test},testTimer_ber,testTimer_ber_bin, - testTimer_ber_bin_opt, testTimer_ber_bin_opt_driver, testTimer_per, - testTimer_per_bin, testTimer_per_bin_opt, testTimer_uper_bin, - testComment,testName2Number]. - - -testTimer_ber(suite) -> []; -testTimer_ber(Config) -> - ?line testTimer:compile(Config,ber,[]), - ?line testTimer:go(Config,ber). - -testTimer_ber_bin(suite) -> []; -testTimer_ber_bin(Config) -> - ?line testTimer:compile(Config,ber_bin,[]), - ?line testTimer:go(Config,ber_bin). - -testTimer_ber_bin_opt(suite) -> []; -testTimer_ber_bin_opt(Config) -> - ?line testTimer:compile(Config,ber_bin,[optimize]), - ?line testTimer:go(Config,ber_bin). - -testTimer_ber_bin_opt_driver(suite) -> []; -testTimer_ber_bin_opt_driver(Config) -> - ?line testTimer:compile(Config,ber_bin,[optimize,driver]), - ?line testTimer:go(Config,ber_bin). - -testTimer_per(suite) -> []; -testTimer_per(Config) -> - ?line testTimer:compile(Config,per,[]), - ?line testTimer:go(Config,per). - -testTimer_per_bin(suite) -> []; -testTimer_per_bin(Config) -> - ?line testTimer:compile(Config,per_bin,[]), - ?line testTimer:go(Config,per_bin). - -testTimer_per_bin_opt(suite) -> []; -testTimer_per_bin_opt(Config) -> - ?line testTimer:compile(Config,per_bin,[optimize]), - ?line testTimer:go(Config,per_bin). - - -testTimer_uper_bin(suite) -> []; -testTimer_uper_bin(Config) -> - ?line ok=testTimer:compile(Config,uper_bin,[]), - ?line {comment,_} = testTimer:go(Config,uper_bin). - -%% Test of multiple-line comment, OTP-8043 -testComment(suite) -> []; -testComment(Config) -> - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - - ?line ok = asn1ct:compile(DataDir ++ "Comment",[{outdir,OutDir}]), - - ?line {ok,Enc} = asn1_wrapper:encode('Comment','Seq',{'Seq',12,true}), - ?line {ok,{'Seq',12,true}} = asn1_wrapper:decode('Comment','Seq',Enc), - ok. - -testName2Number(suite) -> []; -testName2Number(Config) -> - DataDir = ?config(data_dir,Config), - OutDir = ?config(priv_dir,Config), - N2NOptions = [{n2n,Type}|| Type <- - ['CauseMisc','CauseProtocol', - %% 'CauseNetwork', - 'CauseRadioNetwork', - 'CauseTransport','CauseNas']], - ?line ok = asn1ct:compile(DataDir ++ "S1AP-IEs",[{outdir,OutDir}]++N2NOptions), - ?line true = code:add_patha(OutDir), - - ?line 0 = 'S1AP-IEs':name2num_CauseMisc('control-processing-overload'), - ?line 'unknown-PLMN' = 'S1AP-IEs':num2name_CauseMisc(5), - ok. - diff --git a/lib/asn1/test/asn1_particular_SUITE.erl.src b/lib/asn1/test/asn1_particular_SUITE.erl.src deleted file mode 100644 index df76de914d..0000000000 --- a/lib/asn1/test/asn1_particular_SUITE.erl.src +++ /dev/null @@ -1,10 +0,0 @@ - -particular() -> [ticket_7407]. - -ticket_7407(suite) -> []; -ticket_7407(Config) -> - ?line ok = asn1_test_lib:ticket_7407_compile(Config,[]), - ?line ok = asn1_test_lib:ticket_7407_code(true), - - ?line ok = asn1_test_lib:ticket_7407_compile(Config,[no_final_padding]), - ?line ok = asn1_test_lib:ticket_7407_code(false).
\ No newline at end of file diff --git a/lib/asn1/test/asn1_test_lib.erl b/lib/asn1/test/asn1_test_lib.erl index 26cbdeb940..96c04a9436 100644 --- a/lib/asn1/test/asn1_test_lib.erl +++ b/lib/asn1/test/asn1_test_lib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2010. All Rights Reserved. +%% Copyright Ericsson AB 2008-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,11 +19,67 @@ %% -module(asn1_test_lib). +-export([compile/3]). +-export([compile_all/3]). +-export([compile_erlang/3]). + -export([ticket_7407_compile/2,ticket_7407_code/1, ticket_7678/2, - ticket_7708/2, ticket_7763/1, ticket_7876/3]). + ticket_7708/2, ticket_7763/1, ticket_7876/3]). -include_lib("test_server/include/test_server.hrl"). +compile(File, Config, Options) -> compile_all([File], Config, Options). + +compile_all(Files, Config, Options) -> + DataDir = ?config(data_dir, Config), + CaseDir = ?config(case_dir, Config), + [compile_file(filename:join(DataDir, F), [{outdir, CaseDir}|Options]) + || F <- Files], + ok. + +compile_file(File, Options) -> + try + ok = asn1ct:compile(File, Options), + case should_load(File, Options) of + false -> + ok; + {module, Module} -> + code:purge(Module), + true = code:soft_purge(Module), + {module, Module} = code:load_file(Module) + end + catch + Class:Reason -> + erlang:error({compile_failed, {File, Options}, {Class, Reason}}) + end. + +compile_erlang(Mod, Config, Options) -> + DataDir = ?config(data_dir, Config), + CaseDir = ?config(case_dir, Config), + M = list_to_atom(Mod), + {ok, M} = compile:file(filename:join(DataDir, Mod), + [{i, CaseDir}, {outdir, CaseDir}|Options]). + +should_load(File, Options) -> + should_load(File, lists:member(abs, Options), + proplists:lookup(inline, Options)). + +should_load(_File, true, _Inline) -> + false; +should_load(_File, _Abs, {inline, Module}) when Module /= true -> + {module, Module}; +should_load(File, _Abs, _Inline) -> + {module, list_to_atom(strip_extension(filename:basename(File)))}. + +strip_extension(File) -> + strip_extension(File, filename:extension(File)). + +strip_extension(File, "") -> + File; +strip_extension(File, Ext) when Ext == ".asn"; Ext == ".set"; Ext == ".asn1"-> + strip_extension(filename:rootname(File)); +strip_extension(File, _Ext) -> + File. ticket_7407_compile(Config,Option) -> diff --git a/lib/asn1/test/ber_decode_error.erl b/lib/asn1/test/ber_decode_error.erl index a566e0b07f..ff6e386a88 100644 --- a/lib/asn1/test/ber_decode_error.erl +++ b/lib/asn1/test/ber_decode_error.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2011. All Rights Reserved. +%% Copyright Ericsson AB 1999-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,19 +19,10 @@ %% -module(ber_decode_error). --export([run/1, compile/3]). +-export([run/1]). -include_lib("test_server/include/test_server.hrl"). -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "Constructed", - [Rules,{outdir,OutDir}]++Options). - - run([]) -> ?line {ok,B} = asn1_wrapper:encode('Constructed','S3',{'S3',17}), ?line [T,L|V] = lists:flatten(B), diff --git a/lib/asn1/test/h323test.erl b/lib/asn1/test/h323test.erl index 5545dd45b9..b7a7d6e4df 100644 --- a/lib/asn1/test/h323test.erl +++ b/lib/asn1/test/h323test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2010. All Rights Reserved. +%% Copyright Ericsson AB 1999-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,58 +19,20 @@ %% -module(h323test). --compile(export_all). --export([compile/3,run/1]). +-export([run/1]). -include_lib("test_server/include/test_server.hrl"). -compile(Config,Rules,Options) -> - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "H235-SECURITY-MESSAGES",[Rules,{outdir,OutDir}]++Options), - ?line ok = asn1ct:compile(DataDir ++ "H323-MESSAGES",[Rules,{outdir,OutDir}]++Options), - ?line ok = asn1ct:compile(DataDir ++ "MULTIMEDIA-SYSTEM-CONTROL",[Rules,{outdir,OutDir}]++Options). - -run(per_bin) -> - run(); -run(per) -> - run(); -run(_Rules) -> - ok. +run(per_bin) -> run(); +run(per) -> run(); +run(_Rules) -> ok. run() -> - ?line alerting(), - ?line connect(), + alerting(), + connect(), ok. -arq() -> - _AdmissionRequest = "27900007086000340036003300320038003700370101805337010180533600AC1F38C60693000D000445367AE75C5740120300AC1F38C6415004E0200100110000D7D22EA88D511C0200AC1F38C6C0580100". - - -t0() -> - Setup = "00B8060008914A0001010180533622C000000000074572696373736F6E0356302E3100010180533700AC1F38C206B80045367AE75C5740120300AC1F38C6415000411C110000D7D22EA88D511C0200AC1F3806C0583802150000080E1403001E80800A04000100AC1F38C661A820400000060401004E1403001E80801114000100AC1F38C72EE000AC1F38C72EE00100010063AA34AB" -, - ByteList = hexstr2bytes(Setup), - asn1_wrapper:decode('H323-MESSAGES','H323-UU-PDU',ByteList). - -t1() -> - AdmissionRequest = "27900007086000340036003300320038003700370101805337010180533600AC1F38C60693000D000445367AE75C5740120300AC1F38C6415004E0200100110000D7D22EA88D511C0200AC1F38C6C0580100", - ByteList = hexstr2bytes(AdmissionRequest), - asn1_wrapper:decode('H323-MESSAGES','RasMessage',ByteList). - -t2() -> - Cs = "080200040504038090A56C059132303033700591323030347E00930500B8060008914A0001010180533622C000000000074572696373736F6E0356302E3100010180533700AC1F38C206B80045367AE75C5740120300AC1F38C6415000411C110000D7D22EA88D511C0200AC1F3806C0583802150000080E1403001E80800A04000100AC1F38C661A820400000060401004E1403001E80801114000100AC1F38C72EE000AC1F38C72EE00100010063AA34AB", - ByteList = hexstr2bytes(Cs), - asn1_wrapper:decode('H323-MESSAGES','H323-UU-PDU',ByteList). - -t3() -> - Cs = "10b8060008914a0002044003004d0067006f006e018085cc22c0b500534c164d6963726f736f6674ae204e65744d656574696e67ae0003332e3000000101808c990088e1293a06b8001689edc5bf23d3118c2d00c04f4b1cd0000c07000a00000204dc40b500534c3c0200000028000000000000001b0000008138427484ccd211b4e300a0c90d0660100000001289edc5bf23d3118c2d00c04f4b1cd00000000000000000a615d9ee", - ByteList = hexstr2bytes(Cs), - asn1_wrapper:decode('H323-MESSAGES','H323-UU-PDU',ByteList). - dec_alerting() -> Cs = "0380060008914a0002020120110000000000000000000000000000000000", - _Slask="E83AE983", ByteList = hexstr2bytes(Cs), asn1_wrapper:decode('H323-MESSAGES','H323-UserInformation',ByteList). @@ -78,95 +40,31 @@ enc_alerting(V) -> asn1_wrapper:encode('H323-MESSAGES','H323-UserInformation',V). alerting() -> - ?line {ok,V} = dec_alerting(), - ?line {ok,B} = enc_alerting(V), - ?line ByteList = lists:flatten(B), - ?line {ok,V} = asn1_wrapper:decode('H323-MESSAGES','H323-UserInformation',ByteList). + {ok,V} = dec_alerting(), + {ok,B} = enc_alerting(V), + ByteList = lists:flatten(B), + {ok,V} = asn1_wrapper:decode('H323-MESSAGES','H323-UserInformation',ByteList). dec_connect() -> Cs = "02c0060008914a00020088e1293a04a322c0b500534c164d6963726f736f6674ae204e65744d656474696e67ae0003332e3000001689edc5bf23d3118c2d00c04f4b1cd00900110000000000000000000000000000000000", - _Slask="2f530a3f", ByteList = hexstr2bytes(Cs), asn1_wrapper:decode('H323-MESSAGES','H323-UserInformation',ByteList). - + enc_connect(V) -> asn1_wrapper:encode('H323-MESSAGES','H323-UserInformation',V). connect() -> - ?line {ok,V} = dec_connect(), - ?line {ok,B} = enc_connect(V), - ?line ByteList = lists:flatten(B), - ?line {ok,V} = asn1_wrapper:decode('H323-MESSAGES','H323-UserInformation',ByteList). + {ok,V} = dec_connect(), + {ok,B} = enc_connect(V), + ByteList = lists:flatten(B), + {ok,V} = asn1_wrapper:decode('H323-MESSAGES','H323-UserInformation',ByteList). -dec_h245_TCS() -> - Cs ="02700106000881750003" - "800d00003c000100000100000100000e" - "807fff04b5428080010180000e483060" - "0100800c96a88000002020b500534c48" - "020000000000f4010000f40101000400" - "0000000002000100401f000000100000" - "000104002000f4010700000100000002" - "00ff00000000c0004000f0000000cc01" - "30ff880118ff00008000012040b38000" - "0220c0b38000032020b500534c280200" - "00000000a0000000a000040010000000" - "000070000100401f0000580200000c00" - "1000000000008000042020b500534c28" - "020000000000a0000000a00004001000" - "0000000071000100401f00003a070000" - "25001000000000008000052020b50053" - "4c280200000000008000000080000500" - "14000000000072000100401f00000809" - "000025001000000000008000062020b5" - "00534c28020000000000800000008000" - "050014000000000073000100401f0000" - "7f0a00002b0010000000000080000722" - "000b40000909a00120390c000a099001" - "20390c000b09880120390c000c08a220" - "3940000d089220390004800602070007" - "00060004000500020001000000030000" - "0a00000e800702070007000600040005" - "000200010000000300000900000e8008" - "02070007000600040005000200010000" - "000300000c00000e8009020700070006" - "00040005000200010000000300000b00" - "000e800a020700070006000400050002" - "00010000000300000d00000e0300000b" - "01003280299d93369631bc", - ByteList = hexstr2bytes(Cs), - asn1_wrapper:decode('MULTIMEDIA-SYSTEM-CONTROL', - 'MultimediaSystemControlMessage',ByteList). - - hexstr2bytes([D1,D2|T]) -> +hexstr2bytes([D1,D2|T]) -> [dig2num(D1)*16+dig2num(D2)|hexstr2bytes(T)]; hexstr2bytes([]) -> []. -dig2num(D) when D >= $0, D =< $9 -> - D - $0; -dig2num(D) when D >= $a, D =< $f -> - 10 + D - $a; -dig2num(D) when D >= $A, D =< $F -> - 10 + D - $A. - -bytes2hexstr(Bytes) -> - bytes2hexstr(Bytes,[]). - -bytes2hexstr([B|Bytes],Acc) -> - D1 = num2dig(B bsr 4), - D2 = num2dig(B band 15), - bytes2hexstr(Bytes,[D2,D1|Acc]); -bytes2hexstr([],Acc) -> - lists:reverse(Acc). - -num2dig(Num) when Num =< 9 -> - $0 + Num; -num2dig(Num) -> - $a + Num - 10. - - - - - - +dig2num(D) when D >= $0, D =< $9 -> D - $0; +dig2num(D) when D >= $a, D =< $f -> 10 + D - $a; +dig2num(D) when D >= $A, D =< $F -> 10 + D - $A. diff --git a/lib/asn1/test/asn1_bin_v2_particular_SUITE.erl.src b/lib/asn1/test/pem_performance.erl index 4c3c8c7808..87b8cbd61d 100644 --- a/lib/asn1/test/asn1_bin_v2_particular_SUITE.erl.src +++ b/lib/asn1/test/pem_performance.erl @@ -1,276 +1,22 @@ - -particular() -> [smp, ticket7904]. - - -smp(suite) -> []; -smp(Config) -> - case erlang:system_info(smp_support) of - true -> - NumOfProcs = erlang:system_info(schedulers), - io:format("smp starting ~p workers\n",[NumOfProcs]), - - ?line Msg = {initiatingMessage, testNBAPsystem:cell_setup_req_msg()}, - ?line ok = testNBAPsystem:compile(Config,per_bin,[optimize]), - - enc_dec(NumOfProcs,Msg,2), - - N = 10000, - - ?line {Time1,ok} = timer:tc(?MODULE,enc_dec,[NumOfProcs,Msg, N]), - ?line {Time1S,ok} = timer:tc(?MODULE,enc_dec,[1, Msg, NumOfProcs * N]), - - ?line ok = testNBAPsystem:compile(Config,ber_bin,[optimize,nif]), - ?line {Time3,ok} = timer:tc(?MODULE,enc_dec,[NumOfProcs,Msg, N]), - - ?line {Time3S,ok} = timer:tc(?MODULE,enc_dec,[1, Msg, NumOfProcs * N]), - - {comment,lists:flatten( - io_lib:format( - "Encode/decode time parallell with ~p cores: ~p [microsecs]~n" - "Encode/decode time sequential: ~p [microsecs]", - [NumOfProcs,Time1+Time3,Time1S+Time3S]))}; - false -> - {skipped,"No smp support"} - end. - -per_performance(Config) -> - PrivDir = proplists:get_value(priv_dir, Config), - NifDir = filename:join(PrivDir,"nif"), - ErlDir = filename:join(PrivDir,"erl"), - file:make_dir(NifDir),file:make_dir(ErlDir), - - ?line Msg = {initiatingMessage, testNBAPsystem:cell_setup_req_msg()}, - ?line ok = testNBAPsystem:compile([{priv_dir,NifDir}|Config],per_bin, - [optimize]), - ?line ok = testNBAPsystem:compile([{priv_dir,ErlDir}|Config],per_bin, - []), - - Modules = ['NBAP-CommonDataTypes', - 'NBAP-Constants', - 'NBAP-Containers', - 'NBAP-IEs', - 'NBAP-PDU-Contents', - 'NBAP-PDU-Discriptions'], - - - PreNif = fun() -> - code:add_patha(NifDir), - lists:foreach(fun(M) -> - code:purge(M), - code:load_file(M) - end,Modules) - end, - - PreErl = fun() -> - code:add_patha(ErlDir), - lists:foreach(fun(M) -> - code:purge(M), - code:load_file(M) - end,Modules) - end, - - Func = fun() -> - element(1,timer:tc( - asn1_wrapper,encode,['NBAP-PDU-Discriptions', - 'NBAP-PDU', - Msg])) - end, - - nif_vs_erlang_performance({{{PreNif,Func},{PreErl,Func}},100000,32}). - -ber_performance(Config) -> - - ?line Msg = {initiatingMessage, testNBAPsystem:cell_setup_req_msg()}, - ?line ok = testNBAPsystem:compile(Config,ber_bin,[optimize,nif]), - - - BerFun = fun() -> - {ok,B} = asn1_wrapper:encode('NBAP-PDU-Discriptions', - 'NBAP-PDU', Msg), - asn1_wrapper:decode( - 'NBAP-PDU-Discriptions', - 'NBAP-PDU', - B) - end, - nif_vs_erlang_performance({BerFun,100000,32}). - -cert_pem_performance(Config) when is_list(Config) -> - cert_pem_performance({100000, 32}); -cert_pem_performance({N,S}) -> - nif_vs_erlang_performance({fun cert_pem/0,N,S}). - -dsa_pem_performance(Config) when is_list(Config) -> - cert_pem_performance({100000, 32}); -dsa_pem_performance({N,S}) -> - nif_vs_erlang_performance({fun dsa_pem/0,N,S}). - - -nif_vs_erlang_performance({{TC1,TC2},N,Sched}) -> - random:seed({123,456,789}), - io:format("Running a ~p sample with ~p max procs...~n~n",[N,Sched]), - - {True,False} = exec(TC1,TC2,Sched,N+1), - - io:format("~ndone!~n"), - - io:format("~n"),TStats = print_stats(strip(True,N div 20)), - io:format("~n"),FStats = print_stats(strip(False,N div 20)), - Str = io_lib:format("~nNifs are ~.3f% faster than erlang!~n", - [(element(2,FStats) - element(2,TStats)) / - element(2,FStats) * 100]), - io:format(Str), - {comment, lists:flatten(Str)}; -nif_vs_erlang_performance({T,N,Sched}) -> - PTC1 = fun() -> - application:set_env(asn1, nif_loadable, true) - end, - PTC2 = fun() -> - application:set_env(asn1, nif_loadable, false) - end, - TC = fun() -> - element(1,timer:tc(T)) - end, - nif_vs_erlang_performance({{{PTC1,TC},{PTC2,TC}},N,Sched}). - - -print_stats(Data) -> - Length = length(Data), - Mean = lists:sum(Data) / Length, - Variance = lists:foldl(fun(N,Acc) -> math:pow(N - Mean, 2)+Acc end, 0, Data), - StdDev = math:sqrt(Variance / Length), - Median = lists:nth(round(Length/2),Data), - Min = lists:min(Data), - Max = lists:max(Data), - if Length < 20 -> - io:format("Data: ~w~n",[Data]); - true -> - ok - end, - io:format("Length: ~p~nMean: ~p~nStdDev: ~p~nMedian: ~p~nMin: ~p~nMax: ~p~n", - [Length,Mean,StdDev,Median,Min,Max]), - {Length,Mean,StdDev,Median,Min,Max}. - -collect(Acc) -> - receive - {Tag,Val} -> - Prev = proplists:get_value(Tag,Acc,[]), - collect(lists:keystore(Tag,1,Acc,{Tag,[Val|Prev]})) - after 100 -> - Acc - end. - -exec(One,Two,Max,N) -> - exec(One,Two,Max,N,{[],[]}). -exec(_,_,_,1,{D1,D2}) -> - {lists:flatten(D1),lists:flatten(D2)}; -exec({PreOne,One} = O,{PreTwo,Two} = T,MaxProcs, N, {D1,D2}) -> - Num = random:uniform(round(N/2)), - if Num rem 3 == 0 -> - timer:sleep(Num rem 1000); - true -> - ok - end, - Procs = random:uniform(MaxProcs), - io:format("\tBatch: ~p items in ~p processes, ~p left~n",[Num,Procs,N-Num]), - if Num rem 2 == 1 -> - erlang:garbage_collect(), - PreOne(), - MoreOne = pexec(One, Num, Procs, []), - erlang:garbage_collect(), - PreTwo(), - MoreTwo = pexec(Two, Num, Procs, []); - true -> - erlang:garbage_collect(), - PreTwo(), - MoreTwo = pexec(Two, Num, Procs, []), - erlang:garbage_collect(), - PreOne(), - MoreOne = pexec(One, Num, Procs, []) - end, - exec(O,T,MaxProcs,N-Num,{[MoreOne|D1], - [MoreTwo|D2]}). - -pexec(_Fun, _, 0, []) -> - []; -pexec(Fun, _, 0, [{Ref,Pid}|Rest]) -> - receive - {data,D} -> - [D|pexec(Fun,0,0,[{Ref,Pid}|Rest])]; - {'DOWN', Ref, process, Pid, normal} -> - pexec(Fun, 0,0,Rest) - end; -pexec(Fun, 0, 1, AccProcs) -> - pexec(Fun, 0, 0, AccProcs); -pexec(Fun, N, 1, AccProcs) -> - [Fun()|pexec(Fun, N - 1, 1, AccProcs)]; -pexec(Fun, N, Procs, AccProcs) -> - S = self(), - Pid = spawn(fun() -> - S ! {data,pexec(Fun,N,1,[])} - end), - Ref = erlang:monitor(process, Pid), - pexec(Fun, N, Procs - 1, [{Ref,Pid}|AccProcs]). - -strip(Data,Num) -> - {_,R} = lists:split(Num,lists:sort(Data)), - element(2,lists:split(Num,lists:reverse(R))). - -faster(A,B) -> - (B - A)/B * 100. - -enc_dec(1, Msg, N) -> - worker_loop(N, Msg); -enc_dec(NumOfProcs,Msg, N) -> - pforeach(fun(_) -> - worker_loop(N, Msg) - end, [I || I <- lists:seq(1,NumOfProcs)]). - -worker_loop(0, _Msg) -> - ok; -worker_loop(N, Msg) -> - ?line {ok,B}=asn1_wrapper:encode('NBAP-PDU-Discriptions', - 'NBAP-PDU', - Msg), - ?line {ok,_Msg}=asn1_wrapper:decode('NBAP-PDU-Discriptions', - 'NBAP-PDU', - B), - worker_loop(N - 1, Msg). - - -pforeach(Fun, List) -> - pforeach(Fun, List, []). -pforeach(Fun, [], [{Pid,Ref}|Pids]) -> - receive - {'DOWN', Ref, process, Pid, normal} -> - pforeach(Fun, [], Pids) - end; -pforeach(Fun, [H|T], Pids) -> - Pid = spawn(fun() -> Fun(H) end), - Ref = erlang:monitor(process, Pid), - pforeach(Fun, T, [{Pid, Ref}|Pids]); -pforeach(_Fun,[],[]) -> - ok. - --record('InitiatingMessage',{procedureCode,criticality,value}). --record('Iu-ReleaseCommand',{first,second}). - -ticket7904(suite) -> []; -ticket7904(Config) -> - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - - ?line ok = asn1ct:compile(DataDir ++ - "RANAPextract1",[per_bin,optimize,{outdir,OutDir}]), - - Val1 = #'InitiatingMessage'{procedureCode=1, - criticality=ignore, - value=#'Iu-ReleaseCommand'{ - first=13, - second=true}}, - - ?line {ok,_} = 'RANAPextract1':encode('InitiatingMessage', Val1), - asn1rt:unload_driver(), - ?line {ok,_} = 'RANAPextract1':encode('InitiatingMessage', Val1). +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2012. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + +-module([cert_pem/0]). +-module([dsa_pem/0]). cert_pem() -> 'OTP-PUB-KEY':decode('Certificate',<<48,130,3,184,48,130,3,33,160,3,2,1,2,2,1,1,48,13,6,9,42,134,72,134,247,13,1,1,5,5,0,48,129,131,49,14,48,12,6,3,85,4,3,19,5,111,116,112,67,65,49,19,48,17,6,3,85,4,11,19,10,69,114,108,97,110,103,32,79,84,80,49,20,48,18,6,3,85,4,10,19,11,69,114,105,99,115,115,111,110,32,65,66,49,11,48,9,6,3,85,4,6,19,2,83,69,49,18,48,16,6,3,85,4,7,19,9,83,116,111,99,107,104,111,108,109,49,37,48,35,6,9,42,134,72,134,247,13,1,9,1,22,22,112,101,116,101,114,64,101,114,105,120,46,101,114,105,99,115,115,111,110,46,115,101,48,30,23,13,48,56,48,49,48,57,48,56,50,57,51,48,90,23,13,49,55,49,49,49,55,48,56,50,57,51,48,90,48,129,132,49,15,48,13,6,3,85,4,3,19,6,99,108,105,101,110,116,49,19,48,17,6,3,85,4,11,19,10,69,114,108,97,110,103,32,79,84,80,49,20,48,18,6,3,85,4,10,19,11,69,114,105,99,115,115,111,110,32,65,66,49,11,48,9,6,3,85,4,6,19,2,83,69,49,18,48,16,6,3,85,4,7,19,9,83,116,111,99,107,104,111,108,109,49,37,48,35,6,9,42,134,72,134,247,13,1,9,1,22,22,112,101,116,101,114,64,101,114,105,120,46,101,114,105,99,115,115,111,110,46,115,101,48,129,159,48,13,6,9,42,134,72,134,247,13,1,1,1,5,0,3,129,141,0,48,129,137,2,129,129,0,245,56,68,254,220,239,193,190,63,221,182,60,67,77,121,163,214,136,137,183,139,8,166,30,100,27,45,17,126,58,15,173,151,218,75,224,148,14,22,164,10,100,186,183,104,175,197,97,96,182,146,150,106,129,140,100,194,106,90,62,133,233,155,46,155,33,101,220,83,193,182,232,240,99,253,249,114,8,159,172,143,77,179,132,229,205,29,110,185,233,224,52,25,149,249,100,80,229,199,125,23,106,146,233,159,26,13,8,161,206,221,43,240,149,42,45,194,190,85,6,235,152,220,219,160,32,144,67,2,3,1,0,1,163,130,1,55,48,130,1,51,48,9,6,3,85,29,19,4,2,48,0,48,11,6,3,85,29,15,4,4,3,2,5,224,48,29,6,3,85,29,14,4,22,4,20,26,59,44,5,72,211,158,214,23,34,30,241,125,27,123,115,93,163,231,120,48,129,179,6,3,85,29,35,4,129,171,48,129,168,128,20,6,171,128,52,58,164,184,118,178,189,157,46,40,229,109,145,222,125,1,155,161,129,140,164,129,137,48,129,134,49,17,48,15,6,3,85,4,3,19,8,101,114,108,97,110,103,67,65,49,19,48,17,6,3,85,4,11,19,10,69,114,108,97,110,103,32,79,84,80,49,20,48,18,6,3,85,4,10,19,11,69,114,105,99,115,115,111,110,32,65,66,49,18,48,16,6,3,85,4,7,19,9,83,116,111,99,107,104,111,108,109,49,11,48,9,6,3,85,4,6,19,2,83,69,49,37,48,35,6,9,42,134,72,134,247,13,1,9,1,22,22,112,101,116,101,114,64,101,114,105,120,46,101,114,105,99,115,115,111,110,46,115,101,130,1,1,48,33,6,3,85,29,17,4,26,48,24,129,22,112,101,116,101,114,64,101,114,105,120,46,101,114,105,99,115,115,111,110,46,115,101,48,33,6,3,85,29,18,4,26,48,24,129,22,112,101,116,101,114,64,101,114,105,120,46,101,114,105,99,115,115,111,110,46,115,101,48,13,6,9,42,134,72,134,247,13,1,1,5,5,0,3,129,129,0,93,11,112,227,121,15,121,179,247,135,110,216,17,197,84,18,149,166,147,142,190,178,0,209,190,0,142,233,144,100,194,205,220,182,73,204,108,42,95,23,48,63,4,120,239,42,194,25,184,35,117,107,96,229,18,45,76,122,125,40,171,210,132,50,146,178,160,55,17,35,255,208,114,30,47,55,185,154,155,165,204,180,14,143,20,234,6,234,201,225,72,235,5,87,61,255,250,23,217,1,144,246,98,221,223,102,49,168,177,13,70,241,26,27,254,251,217,14,244,18,242,197,151,50,186,214,15,42>>). @@ -288,4 +34,4 @@ dsa_pem() -> {1,2,840,10040,4,1}, <<48,130,1,31,2,129,129,0,183,179,230,217,37,99,144,157,21,228,204,162,207,61,246,144,58,139,139,184,184,43,108,206,0,115,173,208,100,233,201,121,21,90,179,119,53,140,25,52,34,202,121,211,164,107,43,56,68,162,159,51,244,232,138,126,164,109,121,89,237,142,57,28,32,188,44,67,253,111,121,104,40,141,211,255,140,118,37,234,150,201,155,160,16,17,51,59,26,249,41,129,16,211,119,128,95,254,182,235,132,0,92,206,93,77,106,217,201,132,203,4,75,201,246,204,216,162,1,84,79,211,10,21,152,195,103,145,2,21,0,213,30,184,86,247,16,247,69,192,241,35,138,84,57,140,3,71,65,206,233,2,129,129,0,148,179,24,63,74,91,128,25,96,29,5,78,223,246,175,0,121,86,54,178,42,231,98,241,147,180,157,60,149,160,50,243,227,76,175,89,234,203,252,242,76,108,9,204,157,182,59,206,227,127,99,215,42,156,194,78,116,25,7,62,243,169,45,5,101,179,247,127,199,144,135,103,23,42,154,125,231,248,154,101,175,155,101,42,232,41,80,41,47,128,208,11,31,106,63,12,202,207,135,80,200,136,250,171,31,118,52,91,200,138,112,111,179,23,214,123,21,118,194,179,0,185,217,52,197,182,236,13>>}, {0, - <<2,129,128,124,66,0,111,121,139,142,209,95,136,95,237,177,150,248,252,49,135,117,100,155,232,138,244,132,89,40,5,70,125,202,96,78,239,76,37,125,149,82,64,107,54,227,73,25,180,227,41,0,234,73,47,80,242,242,129,250,61,68,62,39,38,156,193,146,40,241,247,106,215,223,202,194,110,130,62,186,90,18,28,196,174,99,47,193,61,130,100,150,25,248,115,164,231,153,99,46,69,66,139,33,187,51,49,35,219,234,29,44,172,166,247,42,16,177,187,9,162,81,243,33,26,100,46,78,57,203,135>>}}). + <<2,129,128,124,66,0,111,121,139,142,209,95,136,95,237,177,150,248,252,49,135,117,100,155,232,138,244,132,89,40,5,70,125,202,96,78,239,76,37,125,149,82,64,107,54,227,73,25,180,227,41,0,234,73,47,80,242,242,129,250,61,68,62,39,38,156,193,146,40,241,247,106,215,223,202,194,110,130,62,186,90,18,28,196,174,99,47,193,61,130,100,150,25,248,115,164,231,153,99,46,69,66,139,33,187,51,49,35,219,234,29,44,172,166,247,42,16,177,187,9,162,81,243,33,26,100,46,78,57,203,135>>}}). diff --git a/lib/asn1/test/testChoExtension.erl b/lib/asn1/test/testChoExtension.erl index 5e149ed247..b75cfb6831 100644 --- a/lib/asn1/test/testChoExtension.erl +++ b/lib/asn1/test/testChoExtension.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,21 +19,11 @@ %% -module(testChoExtension). --export([compile/3]). -export([extension/1]). -include_lib("test_server/include/test_server.hrl"). -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "ChoExtension",[Rules,{outdir,OutDir}] ++ Options). - - - extension(_Rules) -> ?line {ok,Bytes1} = asn1_wrapper:encode('ChoExtension','ChoExt1',{'ChoExt1',{bool,true}}), diff --git a/lib/asn1/test/testChoExternal.erl b/lib/asn1/test/testChoExternal.erl index b6586b616b..b2d171f9c7 100644 --- a/lib/asn1/test/testChoExternal.erl +++ b/lib/asn1/test/testChoExternal.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -28,12 +28,12 @@ -compile(Config,Rules,Optimize) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "ChoExternal",[Rules,{outdir,OutDir}]++Optimize). +compile(Config, Rules, Optimize) -> + DataDir = ?config(data_dir, Config), + CaseDir = ?config(case_dir, Config), + true = code:add_patha(CaseDir), + ok = asn1ct:compile(DataDir ++ "ChoExternal", + [Rules, {outdir, CaseDir}] ++ Optimize). diff --git a/lib/asn1/test/testChoOptional.erl b/lib/asn1/test/testChoOptional.erl index 61a1955d28..cbb8134e51 100644 --- a/lib/asn1/test/testChoOptional.erl +++ b/lib/asn1/test/testChoOptional.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,29 +19,16 @@ %% -module(testChoOptional). - --export([compile/3]). -export([optional/1]). %-include("ChoOptional.hrl"). -include_lib("test_server/include/test_server.hrl"). -include("External.hrl"). - -record('Seq1',{bool, int = asn1_NOVALUE, cho = asn1_NOVALUE}). -record('Seq2',{int = asn1_NOVALUE, cho = asn1_NOVALUE, bool}). -record('Seq3',{cho = asn1_NOVALUE, int = asn1_NOVALUE, bool}). - -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "ChoOptional",[Rules,{outdir,OutDir}]++Options). - - - optional(_Rules) -> ?line {ok,Bytes11} = asn1_wrapper:encode('ChoOptional','Seq1',#'Seq1'{bool = true}), diff --git a/lib/asn1/test/testChoOptionalImplicitTag.erl b/lib/asn1/test/testChoOptionalImplicitTag.erl index e28353cb5a..efe335cabd 100644 --- a/lib/asn1/test/testChoOptionalImplicitTag.erl +++ b/lib/asn1/test/testChoOptionalImplicitTag.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2010. All Rights Reserved. +%% Copyright Ericsson AB 1999-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -20,28 +20,16 @@ -module(testChoOptionalImplicitTag). --export([compile/2]). -export([optional/1]). %-include("ChoOptional.hrl"). -include_lib("test_server/include/test_server.hrl"). -include("External.hrl"). - -record('Seq1',{bool, int = asn1_NOVALUE, cho = asn1_NOVALUE}). -record('Seq2',{int = asn1_NOVALUE, cho = asn1_NOVALUE, bool}). -record('Seq3',{cho = asn1_NOVALUE, int = asn1_NOVALUE, bool}). - -compile(Config,Rules) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "ChoOptionalImplicitTag",[Rules,{outdir,OutDir}]). - - - optional(_Rules) -> ?line {ok,Bytes11} = asn1_wrapper:encode('ChoOptionalImplicitTag','Seq1',#'Seq1'{bool = true}), diff --git a/lib/asn1/test/testChoPrim.erl b/lib/asn1/test/testChoPrim.erl index f037db1c5d..936a38f76c 100644 --- a/lib/asn1/test/testChoPrim.erl +++ b/lib/asn1/test/testChoPrim.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,22 +19,11 @@ %% -module(testChoPrim). --export([compile/3]). -export([bool/1]). -export([int/1]). -include_lib("test_server/include/test_server.hrl"). - -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "ChoPrim",[Rules,{outdir,OutDir}]++Options). - - - bool(Rules) -> ?line {ok,Bytes11} = asn1_wrapper:encode('ChoPrim','ChoCon',{bool0,true}), diff --git a/lib/asn1/test/testChoRecursive.erl b/lib/asn1/test/testChoRecursive.erl index 36e23e2e03..22be26cbce 100644 --- a/lib/asn1/test/testChoRecursive.erl +++ b/lib/asn1/test/testChoRecursive.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -20,7 +20,6 @@ -module(testChoRecursive). --export([compile/3]). -export([recursive/1]). -include_lib("test_server/include/test_server.hrl"). @@ -28,16 +27,6 @@ -record('ChoRec_something',{a, b, c}). -record('ChoRec2_something',{a, b, c}). - -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "ChoRecursive",[Rules,{outdir,OutDir}]++Options). - - - recursive(_Rules) -> ?line {ok,Bytes11} = asn1_wrapper:encode('ChoRecursive','ChoRec',{'ChoRec',{something, diff --git a/lib/asn1/test/testChoTypeRefCho.erl b/lib/asn1/test/testChoTypeRefCho.erl index f381d9078d..9bd732f462 100644 --- a/lib/asn1/test/testChoTypeRefCho.erl +++ b/lib/asn1/test/testChoTypeRefCho.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,22 +19,10 @@ %% -module(testChoTypeRefCho). --export([compile/3]). -export([choice/1]). -include_lib("test_server/include/test_server.hrl"). - - -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "ChoTypeRefCho",[Rules,{outdir,OutDir}]++Options). - - - choice(_Rules) -> ?line {ok,Bytes11} = asn1_wrapper:encode('ChoTypeRefCho','ChoTRcho',{choCho,{choInt,88}}), diff --git a/lib/asn1/test/testChoTypeRefPrim.erl b/lib/asn1/test/testChoTypeRefPrim.erl index 8fb9ed9f02..edef6192fe 100644 --- a/lib/asn1/test/testChoTypeRefPrim.erl +++ b/lib/asn1/test/testChoTypeRefPrim.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,22 +19,10 @@ %% -module(testChoTypeRefPrim). --export([compile/3]). -export([prim/1]). -include_lib("test_server/include/test_server.hrl"). - - -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "ChoTypeRefPrim",[Rules,{outdir,OutDir}]++Options). - - - prim(_Rules) -> ?line {ok,Bytes11} = asn1_wrapper:encode('ChoTypeRefPrim','ChoTR',{bool,true}), diff --git a/lib/asn1/test/testChoTypeRefSeq.erl b/lib/asn1/test/testChoTypeRefSeq.erl index 45d6209e79..bf2b66c73e 100644 --- a/lib/asn1/test/testChoTypeRefSeq.erl +++ b/lib/asn1/test/testChoTypeRefSeq.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,7 +19,6 @@ %% -module(testChoTypeRefSeq). --export([compile/3]). -export([seq/1]). -include_lib("test_server/include/test_server.hrl"). @@ -28,16 +27,6 @@ -record('ChoSeqImp',{seqInt, seqOs}). -record('ChoSeqExp',{seqInt, seqOs}). - -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "ChoTypeRefSeq",[Rules,{outdir,OutDir}]++Options). - - - seq(_Rules) -> ?line {ok,Bytes1} = diff --git a/lib/asn1/test/testChoTypeRefSet.erl b/lib/asn1/test/testChoTypeRefSet.erl index 9869549d7a..8a3e8bdbb0 100644 --- a/lib/asn1/test/testChoTypeRefSet.erl +++ b/lib/asn1/test/testChoTypeRefSet.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,7 +19,6 @@ %% -module(testChoTypeRefSet). --export([compile/3]). -export([set/1]). -include_lib("test_server/include/test_server.hrl"). @@ -28,16 +27,6 @@ -record('ChoSetImp',{setInt, setOs}). -record('ChoSetExp',{setInt, setOs}). - -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "ChoTypeRefSet",[Rules,{outdir,OutDir}]++Options). - - - set(_Rules) -> ?line {ok,Bytes1} = diff --git a/lib/asn1/test/testChoiceIndefinite.erl b/lib/asn1/test/testChoiceIndefinite.erl index e5f3ee51c8..630efcf27a 100644 --- a/lib/asn1/test/testChoiceIndefinite.erl +++ b/lib/asn1/test/testChoiceIndefinite.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2002-2010. All Rights Reserved. +%% Copyright Ericsson AB 2002-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,20 +19,10 @@ %% -module(testChoiceIndefinite). --export([compile/3]). -export([main/1]). -include_lib("test_server/include/test_server.hrl"). - -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "ChoiceIndef", - [Rules,{outdir,OutDir}]++Options). - main(per_bin) -> ok; main(per) -> ok; main(ber_bin_v2) -> @@ -50,6 +40,3 @@ main(ber) -> ?line {ok,V} = asn1_wrapper:decode('ChoiceIndef','Seq',B), ?line {ok,V} = asn1_wrapper:decode('ChoiceIndef','Seq',Bi), ok. - - - diff --git a/lib/asn1/test/testCompactBitString.erl b/lib/asn1/test/testCompactBitString.erl index cd5586602b..9563a31bf3 100644 --- a/lib/asn1/test/testCompactBitString.erl +++ b/lib/asn1/test/testCompactBitString.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2010. All Rights Reserved. +%% Copyright Ericsson AB 2001-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,29 +19,11 @@ %% -module(testCompactBitString). --export([compile/3]). -export([compact_bit_string/1, bit_string_unnamed/1,otp_4869/1, ticket_7734/1]). -include_lib("test_server/include/test_server.hrl"). - -compile(Config,Rules,Option) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "PrimStrings", - [Rules,{outdir,OutDir}]++Option), - case Rules of - per_bin -> - ?line ok = asn1ct:compile(DataDir ++ "Constraints", - [Rules,{outdir,OutDir}]++Option); - _ -> ok - end. - - - compact_bit_string(Rules) -> %%========================================================== diff --git a/lib/asn1/test/testConstraints.erl b/lib/asn1/test/testConstraints.erl index dcbc04f8d8..cb15a24359 100644 --- a/lib/asn1/test/testConstraints.erl +++ b/lib/asn1/test/testConstraints.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2010. All Rights Reserved. +%% Copyright Ericsson AB 2001-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,24 +19,11 @@ %% -module(testConstraints). --export([compile/3]). -export([int_constraints/1,refed_NNL_name/1]). -include_lib("test_server/include/test_server.hrl"). - - -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "Constraints",[Rules,{outdir,OutDir}]++Options). - - - - int_constraints(Rules) -> %%========================================================== diff --git a/lib/asn1/test/testContextSwitchingTypes.erl b/lib/asn1/test/testContextSwitchingTypes.erl index 7d05e5c352..4f67942922 100644 --- a/lib/asn1/test/testContextSwitchingTypes.erl +++ b/lib/asn1/test/testContextSwitchingTypes.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2011. All Rights Reserved. +%% Copyright Ericsson AB 2001-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,29 +19,19 @@ %% -module(testContextSwitchingTypes). --export([compile/3]). --export([test/0]). +-export([test/1]). -include_lib("test_server/include/test_server.hrl"). - -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "ContextSwitchingTypes", - [Rules,{outdir,OutDir}]++Options). - - -test() -> +test(Config) -> ?line ValT = 'ContextSwitchingTypes':'val1-T'(), ?line {ok,Bytes1} = asn1_wrapper:encode('ContextSwitchingTypes','T',ValT), ?line {ok,Result1} = asn1_wrapper:decode('ContextSwitchingTypes','T',Bytes1), ?line ok = check_EXTERNAL(Result1), - ?line {ok,ValT2} = asn1ct:value('ContextSwitchingTypes','T'), + ?line {ok,ValT2} = asn1ct:value('ContextSwitchingTypes','T', + [{i, ?config(case_dir, Config)}]), ?line {ok,Bytes1_2} = asn1_wrapper:encode('ContextSwitchingTypes','T',ValT2), ?line {ok,Result1_2} = diff --git a/lib/asn1/test/testDER.erl b/lib/asn1/test/testDER.erl index 630f7ecc14..395116bd34 100644 --- a/lib/asn1/test/testDER.erl +++ b/lib/asn1/test/testDER.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2010. All Rights Reserved. +%% Copyright Ericsson AB 2003-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,19 +19,10 @@ %% -module(testDER). --export([compile/3]). -export([test/0]). -include_lib("test_server/include/test_server.hrl"). - -compile(Config,Rule,Options) -> - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "DERSpec", - [Rule,der,{outdir,OutDir}]++Options). - test() -> Val = {'Set',12,{version,214},true}, ?line {ok,Bin}=asn1_wrapper:encode('DERSpec','Set',Val), diff --git a/lib/asn1/test/testDeepTConstr.erl b/lib/asn1/test/testDeepTConstr.erl index 53d2b3040e..aa3afbb58f 100644 --- a/lib/asn1/test/testDeepTConstr.erl +++ b/lib/asn1/test/testDeepTConstr.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2010. All Rights Reserved. +%% Copyright Ericsson AB 2001-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -21,23 +21,10 @@ -module(testDeepTConstr). --export([compile/3,main/1]). +-export([main/1]). -include_lib("test_server/include/test_server.hrl"). -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line ok = asn1ct:compile(DataDir ++ - "TConstrChoice",[Rules,{outdir,OutDir}]++Options), - ?line ok = asn1ct:compile(DataDir ++ - "TConstr",[Rules,{outdir,OutDir}]++Options). - - - main(_Erule) -> Val1 = {'FilterItem', {substrings, diff --git a/lib/asn1/test/testDef.erl b/lib/asn1/test/testDef.erl index 7942a358be..48f0015008 100644 --- a/lib/asn1/test/testDef.erl +++ b/lib/asn1/test/testDef.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,7 +19,6 @@ %% -module(testDef). --export([compile/3]). -export([main/1]). -include_lib("test_server/include/test_server.hrl"). @@ -37,16 +36,6 @@ bool32 = asn1_DEFAULT, bool33 = asn1_DEFAULT}). - -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "Def",[Rules,{outdir,OutDir}]++Options). - - - main(_Rules) -> ?line {ok,Bytes11} = asn1_wrapper:encode('Def','Def1',#'Def1'{bool0 = true, diff --git a/lib/asn1/test/testDoubleEllipses.erl b/lib/asn1/test/testDoubleEllipses.erl index 20be4ea215..9030a99ce2 100644 --- a/lib/asn1/test/testDoubleEllipses.erl +++ b/lib/asn1/test/testDoubleEllipses.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2010. All Rights Reserved. +%% Copyright Ericsson AB 2007-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,7 +19,6 @@ %% -module(testDoubleEllipses). --export([compile/3]). -export([main/1]). -include_lib("test_server/include/test_server.hrl"). @@ -34,17 +33,6 @@ -record('SetAlt',{a,d,b,e,c,f,g}). -record('SetAltV2',{a,d,b,e,h,i,c,f,g}). - - - -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "DoubleEllipses",[Rules,{outdir,OutDir}]++Options). - - main(_Rules) -> %% SEQUENCE ?line {ok,Bytes} = diff --git a/lib/asn1/test/testEnumExt.erl b/lib/asn1/test/testEnumExt.erl index 4ea0f3b8a1..c97116413a 100644 --- a/lib/asn1/test/testEnumExt.erl +++ b/lib/asn1/test/testEnumExt.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2010. All Rights Reserved. +%% Copyright Ericsson AB 1998-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,19 +19,10 @@ %% -module(testEnumExt). --export([compile/3]). -export([main/1]). -include_lib("test_server/include/test_server.hrl"). -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "EnumExt",[Rules,{outdir,OutDir}]++Options). - - main(Rules) when Rules == per; Rules == per_bin; Rules == uper_bin -> io:format("main(~p)~n",[Rules]), B32=[32],B64=[64], diff --git a/lib/asn1/test/testExternal.erl b/lib/asn1/test/testExternal.erl deleted file mode 100644 index 6e1fa0ee7d..0000000000 --- a/lib/asn1/test/testExternal.erl +++ /dev/null @@ -1,35 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. -%% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%% -%% %CopyrightEnd% -%% -%% --module(testExternal). - --export([compile/3]). - --include_lib("test_server/include/test_server.hrl"). - - -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line test_server:format("Rules ~p~n",[Rules]), - ?line ok = asn1ct:compile(DataDir ++ "External",[Rules,{outdir,OutDir}]++Options). - - diff --git a/lib/asn1/test/testINSTANCE_OF.erl b/lib/asn1/test/testINSTANCE_OF.erl index 6ae656da44..5986a00ec5 100644 --- a/lib/asn1/test/testINSTANCE_OF.erl +++ b/lib/asn1/test/testINSTANCE_OF.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2010. All Rights Reserved. +%% Copyright Ericsson AB 2003-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,21 +19,10 @@ %% -module(testINSTANCE_OF). --export([compile/3,main/1]). +-export([main/1]). -include_lib("test_server/include/test_server.hrl"). - -compile(Config,Rules,Opt) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line ok = asn1ct:compile(DataDir ++ "INSTANCEOF.asn1", - [Rules,{outdir,OutDir}]++Opt). - - main(Erule) -> ?line {ok,Integer} = asn1_wrapper:encode('INSTANCEOF','Int',3), diff --git a/lib/asn1/test/testInfObj.erl b/lib/asn1/test/testInfObj.erl index 9d73be9f23..03e70c730a 100644 --- a/lib/asn1/test/testInfObj.erl +++ b/lib/asn1/test/testInfObj.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2010. All Rights Reserved. +%% Copyright Ericsson AB 2001-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -20,7 +20,7 @@ -module(testInfObj). --export([compile/3,main/1,compile_RANAPfiles/3]). +-export([main/1]). -include_lib("test_server/include/test_server.hrl"). @@ -28,42 +28,6 @@ -record('InitiatingMessage2',{procedureCode,criticality,value}). -record('Iu-ReleaseCommand',{first,second}). -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line ok = asn1ct:compile(DataDir ++ - "RANAPextract1",[Rules,{outdir,OutDir}]++Options), - ?line ok = asn1ct:compile(DataDir ++ "InfObj",[Rules,{outdir,OutDir}]++Options), - %% test case for OTP-4792 optional open type - ?line ok = asn1ct:compile(DataDir ++ "MAP-ExtensionDataTypes",[Rules,{outdir,OutDir}]++Options), - %% OTP-6707 - ?line ok = asn1ct:compile(DataDir ++ "Objects",[Rules,{outdir,OutDir}]++Options), - %% OTP-6717 - ?line ok = asn1ct:compile(DataDir ++ "INAPv2extract",[Rules,{outdir,OutDir}]++Options). - - -compile_RANAPfiles(Config,Rules,Options) -> - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line ok = asn1ct:compile(DataDir ++ "RANAP-CommonDataTypes", - [Rules,{outdir,OutDir}]++Options), - ?line ok = asn1ct:compile(DataDir ++ "RANAP-Constants", - [Rules,{outdir,OutDir}]++Options), - ?line ok = asn1ct:compile(DataDir ++ "RANAP-Containers", - [Rules,{outdir,OutDir}]++Options), - ?line ok = asn1ct:compile(DataDir ++ "RANAP-IEs", - [Rules,{outdir,OutDir}]++Options), - ?line ok = asn1ct:compile(DataDir ++ "RANAP-PDU-Contents", - [Rules,{outdir,OutDir}]++Options), - ?line ok = asn1ct:compile(DataDir ++ "RANAP-PDU-Descriptions", - [Rules,{outdir,OutDir}]++Options). - - main(_Erule) -> Val1 = #'InitiatingMessage'{procedureCode=1, criticality=ignore, diff --git a/lib/asn1/test/testInfObjectClass.erl b/lib/asn1/test/testInfObjectClass.erl index 07ebb7dbd0..e639066246 100644 --- a/lib/asn1/test/testInfObjectClass.erl +++ b/lib/asn1/test/testInfObjectClass.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2010. All Rights Reserved. +%% Copyright Ericsson AB 2001-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -21,22 +21,10 @@ -module(testInfObjectClass). --export([compile/3,main/1]). +-export([main/1]). -include_lib("test_server/include/test_server.hrl"). - - - -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "ErrorClass",[Rules,{outdir,OutDir}]++Options), - ?line ok = asn1ct:compile(DataDir ++ "InfClass",[Rules,{outdir,OutDir}]++Options). - - main(Rule) -> %% this test is added for OTP-4591, to test that elements in decoded %% value has terms in right order. diff --git a/lib/asn1/test/testMegaco.erl b/lib/asn1/test/testMegaco.erl index ca2b1062d1..f4edcebb7e 100644 --- a/lib/asn1/test/testMegaco.erl +++ b/lib/asn1/test/testMegaco.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2010. All Rights Reserved. +%% Copyright Ericsson AB 2001-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -108,24 +108,17 @@ compile(_Config,ber,[optimize]) -> compile(_Config,per,[optimize]) -> {ok,no_module,no_module}; compile(Config,Erule,Options) -> - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line ok = asn1ct:compile(DataDir ++ - "MEDIA-GATEWAY-CONTROL.asn", - [Erule,{outdir,OutDir}]++Options), - - ?line ok = asn1ct:compile(DataDir ++ - "OLD-MEDIA-GATEWAY-CONTROL.asn", - [Erule,{outdir,OutDir}]++Options), + asn1_test_lib:compile("MEDIA-GATEWAY-CONTROL.asn", Config, [Erule|Options]), + asn1_test_lib:compile("OLD-MEDIA-GATEWAY-CONTROL.asn", Config, [Erule|Options]), {ok,'OLD-MEDIA-GATEWAY-CONTROL','MEDIA-GATEWAY-CONTROL'}. main(no_module,_) -> ok; -main('OLD-MEDIA-GATEWAY-CONTROL',_) -> +main('OLD-MEDIA-GATEWAY-CONTROL',Config) -> % Msg = msg11(), - {ok,Msg} = asn1ct:value('OLD-MEDIA-GATEWAY-CONTROL','MegacoMessage'), + CaseDir = ?config(case_dir, Config), + {ok,Msg} = asn1ct:value('OLD-MEDIA-GATEWAY-CONTROL','MegacoMessage', + [{i, CaseDir}]), ?line {ok,Bytes} = asn1_wrapper:encode('OLD-MEDIA-GATEWAY-CONTROL', 'MegacoMessage',Msg), ?line {ok,Msg} = asn1_wrapper:decode('OLD-MEDIA-GATEWAY-CONTROL', @@ -176,7 +169,7 @@ request(Mid, TransId, ContextId, CmdReq) when is_list(CmdReq) -> msg11() -> TimeStamp = #'TimeNotation'{date = "19990729", - time = "22010001"}, + time = "22012001"}, Parm = #'EventParameter'{eventParameterName = "ds", value = "916135551212"}, diff --git a/lib/asn1/test/testMergeCompile.erl b/lib/asn1/test/testMergeCompile.erl index 733cbc0eef..31aa3518f6 100644 --- a/lib/asn1/test/testMergeCompile.erl +++ b/lib/asn1/test/testMergeCompile.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2010. All Rights Reserved. +%% Copyright Ericsson AB 2001-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -20,31 +20,13 @@ -module(testMergeCompile). --export([compile/3,main/1,mvrasn/1]). +-export([main/1,mvrasn/1]). -include_lib("test_server/include/test_server.hrl"). -record('InitiatingMessage',{procedureCode,criticality,value}). -record('Iu-ReleaseCommand',{protocolIEs,protocolExtensions}). -compile(Config,Erule,Options) -> - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line ok = asn1ct:compile(DataDir ++ - "MS.set.asn",[Erule,{outdir,OutDir}]++Options), - - ?line ok = asn1ct:compile(DataDir ++ - "RANAPSET.set.asn1",[Erule,{outdir,OutDir}]++Options), - - ?line ok = asn1ct:compile(filename:join([DataDir,"Mvrasn4.set.asn"]), - [Erule,{outdir,OutDir}]++Options), - - ?line ok = asn1ct:compile(filename:join([DataDir,"Mvrasn6.set.asn"]), - [Erule,{outdir,OutDir}]++Options). - - main(Erule) -> %% test of module MS.set.asn that tests OTP-4492: different tagdefault in %% modules and types with same name in modules diff --git a/lib/asn1/test/testMvrasn6.erl b/lib/asn1/test/testMvrasn6.erl deleted file mode 100644 index eaa667e6d7..0000000000 --- a/lib/asn1/test/testMvrasn6.erl +++ /dev/null @@ -1,44 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2001-2010. All Rights Reserved. -%% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%% -%% %CopyrightEnd% -%% -%% --module(testMvrasn6). - --export([compile/2]). --export([main/0]). - --include_lib("test_server/include/test_server.hrl"). - -compile(Config,Rules) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line Options = [Rules,{outdir,OutDir}], - ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-21-4",Options), - ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-20-6",Options), - ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-19-6",Options), - ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-15-6",Options), - ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-18-6",Options), - ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-14-6",Options), - ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-11-6",Options). - - -main() -> - ok. - diff --git a/lib/asn1/test/testNBAPsystem.erl b/lib/asn1/test/testNBAPsystem.erl index 1269f94060..4e8381e51e 100644 --- a/lib/asn1/test/testNBAPsystem.erl +++ b/lib/asn1/test/testNBAPsystem.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2010. All Rights Reserved. +%% Copyright Ericsson AB 2005-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,7 +19,7 @@ %% -module(testNBAPsystem). --export([compile/3,test/2,cell_setup_req_msg/0]). +-export([compile/2,test/2,cell_setup_req_msg/0]). -include_lib("test_server/include/test_server.hrl"). @@ -78,19 +78,15 @@ powerRaiseLimit, dLPowerAveragingWindowSize, 'iE-Extensions' = asn1_NOVALUE}). id, criticality, extensionValue}). -compile(Config,Rules,Opt) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line DataDir2 = filename:join([DataDir,nbapsystem]), - - ?line ok = asn1ct:compile(filename:join([DataDir2,"NBAP-CommonDataTypes.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"NBAP-IEs.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"NBAP-PDU-Contents.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"NBAP-PDU-Discriptions.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"NBAP-Constants.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"NBAP-Containers.asn"]),[Rules,{outdir,OutDir}]++Opt). +compile(Config, Options) -> + [asn1_test_lib:compile(filename:join([nbapsystem, M]), Config, Options) + || M <- ["NBAP-CommonDataTypes.asn", + "NBAP-IEs.asn", + "NBAP-PDU-Contents.asn", + "NBAP-PDU-Discriptions.asn", + "NBAP-Constants.asn", + "NBAP-Containers.asn"]], + ok. test(_Erule,Config) -> @@ -291,13 +287,7 @@ protocolIEs_051107() -> criticality = ignore, extensionValue = 'hsdpa-non-capable'}. - - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -compare(V,V) -> +compare(V,V) -> ok; compare(V,L) when is_list(L) -> compare(V,list_to_binary(L)); @@ -306,52 +296,7 @@ compare(_,_) -> check_record_names(Msg,Config) -> DataDir = ?config(data_dir,Config), - OutDir = ?config(priv_dir,Config), - io:format("check_record_names: compiling ~p~ninclude directory: ~p~n", - [filename:join([DataDir,"test_records"]),OutDir]), - ?line {ok,test_records} = compile:file(filename:join([DataDir,"test_records"]), - [{i,OutDir}]), - io:format("check_record_names: calling test_records:'check_record_names_OTP-5812'/1~n",[]), - ?line ok = test_records:'check_record_names_OTP-5812'(Msg). - -% check_record_names({initiatingMessage, -% #'InitiatingMessage'{procedureID = ProcedureID, -% criticality = _Criticality, -% messageDiscriminator = _MessageDisc, -% transactionID = _TransactionID, -% value = Value}}) -> - -% ?line ok = check_record_ProcedureID(ProcedureID), -% ?line ok = check_record_Value(Value). - -% check_record_ProcedureID(#'ProcedureID'{}) -> -% ok; -% check_record_ProcedureID(_) -> false. - -% check_record_Value(#'ResourceStatusIndication'{protocolIEs = ProtocolIEs}) -> -% ?line ok = check_record_ProtocolIEs(ProtocolIEs); -% check_record_Value(_) -> false. - -% check_record_ProtocolIEs(#'ProtocolIE-Field'{value =IndicationType}) -> -% ?line ok = check_record_NFResourceStatusInd(IndicationType); -% check_record_ProtocolIEs(_) -> false. - -% check_record_NFResourceStatusInd({'no-Failure',#'No-Failure-ResourceStatusInd'{'local-Cell-InformationList'=[LCI]}}) -> -% ?line ok = check_record_LCInfoResourceStatusInd(LCI); -% check_record_NFResourceStatusInd(_) -> false. - -% check_record_LCInfoResourceStatusInd(#'Local-Cell-InformationItem-ResourceStatusInd'{commonChannelsCapacityConsumptionLaw=[CCCCL],dedicatedChannelsCapacityConsumptionLaw=[DCCCL],'iE-Extensions' = [LCIRE]}) -> -% ?line ok = check_record_CCCCL(CCCCL), -% ?line ok = check_record_DCCCL(DCCCL), -% ?line ok = check_record_LCIRE(LCIRE). - -% check_record_CCCCL(#'CommonChannelsCapacityConsumptionLaw_SEQOF'{}) -> -% ok; -% check_record_CCCCL(_) -> false. - -% check_record_DCCCL(#'DedicatedChannelsCapacityConsumptionLaw_SEQOF'{}) -> -% ok; -% check_record_DCCCL(_) -> false. -% check_record_LCIRE(#'ProtocolExtensionField'{}) -> -% ok; -% check_record_LCIRE(_) -> false. + CaseDir = ?config(case_dir,Config), + {ok, test_records} = compile:file(filename:join([DataDir, "test_records"]), + [{i, CaseDir}]), + ok = test_records:'check_record_names_OTP-5812'(Msg). diff --git a/lib/asn1/test/testOpenTypeImplicitTag.erl b/lib/asn1/test/testOpenTypeImplicitTag.erl index 8662744ed3..a37d8004ef 100644 --- a/lib/asn1/test/testOpenTypeImplicitTag.erl +++ b/lib/asn1/test/testOpenTypeImplicitTag.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2002-2010. All Rights Reserved. +%% Copyright Ericsson AB 2002-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,21 +19,10 @@ %% -module(testOpenTypeImplicitTag). --export([compile/3]). -export([main/1]). -include_lib("test_server/include/test_server.hrl"). - -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "OpenTypeImplicitTag",[Rules,{outdir,OutDir}]++Options). - - - main(_Rules) -> ?line {ok,Bytes1} = diff --git a/lib/asn1/test/testParamBasic.erl b/lib/asn1/test/testParamBasic.erl index 4ba0029b54..b5780195b8 100644 --- a/lib/asn1/test/testParamBasic.erl +++ b/lib/asn1/test/testParamBasic.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2010. All Rights Reserved. +%% Copyright Ericsson AB 2001-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,8 +19,6 @@ %% -module(testParamBasic). --export([compile/3]). --export([compile_der/2]). -export([main/1]). -include_lib("test_server/include/test_server.hrl"). @@ -30,22 +28,6 @@ -record('T21',{number, string}). -record('T22',{number, string}). - -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "ParamBasic", - [Rules,{outdir,OutDir}]++Options). - -compile_der(Config,Rules) -> - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "ParamBasic", - [der,Rules,{outdir,OutDir}]). - main(Rules) -> ?line {ok,Bytes11} = diff --git a/lib/asn1/test/testParameterizedInfObj.erl b/lib/asn1/test/testParameterizedInfObj.erl index b95d627d58..68faf08a61 100644 --- a/lib/asn1/test/testParameterizedInfObj.erl +++ b/lib/asn1/test/testParameterizedInfObj.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2010. All Rights Reserved. +%% Copyright Ericsson AB 2001-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -20,7 +20,7 @@ -module(testParameterizedInfObj). --export([compile/3,main/1,ranap/1]). +-export([main/1,ranap/1]). -include_lib("test_server/include/test_server.hrl"). @@ -31,16 +31,6 @@ -record('Iu-ReleaseCommand',{protocolIEs,protocolExtensions}). -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line ok = asn1ct:compile(DataDir ++ "Param",[Rules,{outdir,OutDir}]++Options). -% ?line ok = asn1ct:compile(DataDir ++ "RANAP-CommonDataTypes",[Rules,{outdir,OutDir}]++Options). - - main(Erule) -> PERVal = #'AllocationOrRetentionPriority' {priorityLevel = true, diff --git a/lib/asn1/test/testPrim.erl b/lib/asn1/test/testPrim.erl index 39c1e4d1d8..0d4427ba69 100644 --- a/lib/asn1/test/testPrim.erl +++ b/lib/asn1/test/testPrim.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2011. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,7 +19,6 @@ %% -module(testPrim). --export([compile/3]). -export([bool/1]). -export([int/1]). -export([enum/1]). @@ -30,18 +29,6 @@ -include_lib("test_server/include/test_server.hrl"). - - -compile(Config,Rules,Opt) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "Prim", - [Rules,{outdir,OutDir}] ++ Opt), - ?line ok = asn1ct:compile(DataDir ++ "Real", - [Rules,{outdir,OutDir}] ++ Opt). - bool(Rules) -> %%========================================================== diff --git a/lib/asn1/test/testPrimExternal.erl b/lib/asn1/test/testPrimExternal.erl index 23633177eb..65c3c3a31a 100644 --- a/lib/asn1/test/testPrimExternal.erl +++ b/lib/asn1/test/testPrimExternal.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,21 +19,10 @@ %% -module(testPrimExternal). --export([compile/3]). -export([external/1]). -include_lib("test_server/include/test_server.hrl"). - -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "PrimExternal",[Rules,{outdir,OutDir}]++Options). - - - external(_Rules) -> diff --git a/lib/asn1/test/testPrimStrings.erl b/lib/asn1/test/testPrimStrings.erl index 33652d6554..b1c5172b95 100644 --- a/lib/asn1/test/testPrimStrings.erl +++ b/lib/asn1/test/testPrimStrings.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,7 +19,6 @@ %% -module(testPrimStrings). --export([compile/3]). -export([bit_string/1]). -export([bit_string_unnamed/1]). -export([octet_string/1]). @@ -33,22 +32,6 @@ -include_lib("test_server/include/test_server.hrl"). - -compile(Config,Rules,Option) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "PrimStrings", - [Rules,{outdir,OutDir}]++Option), - ?line {ok,IO} = file:open(test_config,write), - io:format(IO,"~p.~n",[Config]), - file:close(IO), - ?line ok = asn1ct:compile(DataDir ++ "BitStr", - [Rules, {outdir,OutDir}]++Option). - - - bit_string(Rules) -> %%========================================================== diff --git a/lib/asn1/test/testRANAP.erl b/lib/asn1/test/testRANAP.erl deleted file mode 100644 index 52a58d850b..0000000000 --- a/lib/asn1/test/testRANAP.erl +++ /dev/null @@ -1,52 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2001-2010. All Rights Reserved. -%% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%% -%% %CopyrightEnd% -%% -%% - --module(testRANAP). - --export([compile/3,testobj/1]). - --include_lib("test_server/include/test_server.hrl"). - - -compile(Config,Erule,Options) -> - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line ok = asn1ct:compile(filename:join(DataDir,"RANAP"),[Erule,{outdir,OutDir}]++Options), - ?line {ok,testobj} = compile:file(filename:join(DataDir,"testobj"),[{i,OutDir},{outdir,OutDir}]++Options), - ok. - -testobj(_Erule) -> - ?line ok = testobj:run_com_id(), - ?line ok = testobj:run_dir_tsf_2cn(), - ?line ok = testobj:run_dir_tsf_2rnc(), - ?line ok = testobj:run_init_ue(), - ?line ok = testobj:run_iu_rel_cmd(), - ?line ok = testobj:run_iu_rel_cmp(), - ?line ok = testobj:run_rab_ass_rsp_delete(), - ?line ok = testobj:run_rab_ass_rsp_setup(), - ?line ok = testobj:run_rab_create(), - ?line ok = testobj:run_rab_rel(), - ?line ok = testobj:run_reset(), - ?line ok = testobj:run_reset_res(), - ?line ok = testobj:run_sm_cmd(), - ?line ok = testobj:run_sm_cmp(), - ?line ok = testobj:run_sm_rej(). diff --git a/lib/asn1/test/testROSE.erl b/lib/asn1/test/testROSE.erl deleted file mode 100644 index a692ec7682..0000000000 --- a/lib/asn1/test/testROSE.erl +++ /dev/null @@ -1,36 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2002-2010. All Rights Reserved. -%% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%% -%% %CopyrightEnd% -%% -%% --module(testROSE). - --export([compile/3]). - --include_lib("test_server/include/test_server.hrl"). - - - -compile(Config,Rules,Opt) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line ok = asn1ct:compile(DataDir ++ "Remote-Operations-Merged.set.asn1", - [Rules,{outdir,OutDir}]++Opt). - diff --git a/lib/asn1/test/testSSLspecs.erl b/lib/asn1/test/testSSLspecs.erl index 10623af51e..51ef134e5f 100644 --- a/lib/asn1/test/testSSLspecs.erl +++ b/lib/asn1/test/testSSLspecs.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2010. All Rights Reserved. +%% Copyright Ericsson AB 2004-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -20,58 +20,37 @@ -module(testSSLspecs). --export([compile/3,run/1,compile_inline/2,run_inline/1]). +-export([compile/2,run/1,compile_inline/2,run_inline/1]). -include_lib("test_server/include/test_server.hrl"). +compile(Config, Options) -> + DataDir = ?config(data_dir, Config), + CaseDir = ?config(case_dir, Config), + NewOptions = [{i, DataDir}, {i, CaseDir}|Options], -compile(Config,Rules,Options) -> + asn1_test_lib:compile_all(["SSL-PKIX", "PKIXAttributeCertificate"], + Config, NewOptions), - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line ok = asn1ct:compile(DataDir ++ - "SSL-PKIX",[Rules,{outdir,OutDir},{i,DataDir}, - {i,OutDir}]++Options), - ?line ok = asn1ct:compile(DataDir ++ "PKIXAttributeCertificate", - [Rules,{outdir,OutDir},{i,DataDir}, - {i,OutDir}]++Options), %% test case for OTP-4792 optional open type - ?line ok = asn1ct:compile(DataDir ++ "PKIX1Algorithms88", - [Rules,{outdir,OutDir},{i,DataDir}, - {i,OutDir}]++Options), - ?line ok = asn1ct:compile(DataDir ++ "PKIX1Explicit88", - [Rules,{outdir,OutDir},{i,DataDir}, - {i,OutDir}]++Options), - ?line ok = asn1ct:compile(DataDir ++ "PKIX1Implicit88", - [Rules,{outdir,OutDir},{i,DataDir}, - {i,OutDir}]++Options), + asn1_test_lib:compile_all(["PKIX1Algorithms88", "PKIX1Explicit88", + "PKIX1Implicit88"], + Config, NewOptions), + %% OTP-6698, OTP-6702 - ?line ok = remove_db_files(OutDir), - ?line ok = asn1ct:compile(DataDir ++ "PKIX1Explicit93", - [Rules,{outdir,OutDir},{i,DataDir}, - {i,OutDir}]++Options), - ?line ok = asn1ct:compile(DataDir ++ "PKIX1Implicit93", - [Rules,{outdir,OutDir},{i,DataDir}, - {i,OutDir}]++Options). - -compile_inline(Config,Rule) -> - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - - case Rule of - BER when BER==ber_bin;BER==ber_bin_v2 -> - Options = [der,compact_bit_string,optimize, - asn1config,inline], - ?line ok = remove_db_file_inline(OutDir), - ?line ok = asn1ct:compile(DataDir ++ "OTP-PKIX.set.asn", - [Rule,{outdir,OutDir},{i,DataDir}, - {i,OutDir}]++Options); - _ -> - ok - end. + ok = remove_db_files(CaseDir), + asn1_test_lib:compile_all(["PKIX1Explicit93", "PKIX1Implicit93"], + Config, NewOptions). + +compile_inline(Config, Rule) when Rule == ber_bin; Rule == ber_bin_v2 -> + DataDir = ?config(data_dir, Config), + CaseDir = ?config(case_dir, Config), + Options = [{i, CaseDir}, {i, DataDir}, Rule, + der, compact_bit_string, optimize, asn1config, inline], + ok = remove_db_file_inline(CaseDir), + asn1_test_lib:compile("OTP-PKIX.set.asn", Config, Options); +compile_inline(_Config, _Rule) -> + ok. remove_db_files(Dir) -> ?line ok = remove_db_file(Dir ++ "PKIX1Explicit93.asn1db"), diff --git a/lib/asn1/test/testSelectionTypes.erl b/lib/asn1/test/testSelectionTypes.erl index 893c31622f..6d1641388f 100644 --- a/lib/asn1/test/testSelectionTypes.erl +++ b/lib/asn1/test/testSelectionTypes.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2010. All Rights Reserved. +%% Copyright Ericsson AB 2004-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,19 +19,10 @@ %% -module(testSelectionTypes). --export([compile/3]). -export([test/0]). -include_lib("test_server/include/test_server.hrl"). - -compile(Config,Rule,Options) -> - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "SelectionType", - [Rule,{outdir,OutDir}]++Options). - test() -> Val = ["PrintableString","PrintableString","PrintableString"], ?line {ok,Bin}=asn1_wrapper:encode('SelectionType','MendeleyevTable',Val), diff --git a/lib/asn1/test/testSeq2738.erl b/lib/asn1/test/testSeq2738.erl index 9cf9c8fcb4..cddfe4b311 100644 --- a/lib/asn1/test/testSeq2738.erl +++ b/lib/asn1/test/testSeq2738.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2010. All Rights Reserved. +%% Copyright Ericsson AB 1999-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,7 +19,6 @@ %% -module(testSeq2738). --export([compile/3]). -export([main/1]). -include_lib("test_server/include/test_server.hrl"). @@ -32,14 +31,6 @@ -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "Seq2738",[Rules,{outdir,OutDir}]++Options). - - main(_Rules) -> ?line {ok,Bytes} = diff --git a/lib/asn1/test/testSeqDefault.erl b/lib/asn1/test/testSeqDefault.erl index edf07cf1c1..a772b749bd 100644 --- a/lib/asn1/test/testSeqDefault.erl +++ b/lib/asn1/test/testSeqDefault.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -20,7 +20,6 @@ -module(testSeqDefault). -include("External.hrl"). --export([compile/3]). -export([main/1]). -include_lib("test_server/include/test_server.hrl"). @@ -37,15 +36,6 @@ -record('SeqIn',{boolIn, intIn}). -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "SeqDefault",[Rules,{outdir,OutDir}]++Options). - - - main(_Rules) -> ?line {ok,Bytes11} = diff --git a/lib/asn1/test/testSeqExtension.erl b/lib/asn1/test/testSeqExtension.erl index 538e2c250b..7c77ab87e9 100644 --- a/lib/asn1/test/testSeqExtension.erl +++ b/lib/asn1/test/testSeqExtension.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -20,7 +20,6 @@ -module(testSeqExtension). -include("External.hrl"). --export([compile/3]). -export([main/1]). -include_lib("test_server/include/test_server.hrl"). @@ -31,16 +30,6 @@ -record('SeqExt4',{bool, int}). -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "SeqExtension", - [Rules,{outdir,OutDir}]++Options). - - - main(_Rules) -> ?line {ok,Bytes11} = diff --git a/lib/asn1/test/testSeqIndefinite.erl b/lib/asn1/test/testSeqIndefinite.erl index 9285d7b368..25742474bb 100644 --- a/lib/asn1/test/testSeqIndefinite.erl +++ b/lib/asn1/test/testSeqIndefinite.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2010. All Rights Reserved. +%% Copyright Ericsson AB 1999-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,20 +19,11 @@ %% -module(testSeqIndefinite). --export([compile/3]). -export([main/1]). -include_lib("test_server/include/test_server.hrl"). -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "SeqSetIndefinite", - [Rules,{outdir,OutDir}]++Options). - main(per_bin) -> ok; main(per) -> ok; main(ber_bin_v2) -> diff --git a/lib/asn1/test/testSeqOf.erl b/lib/asn1/test/testSeqOf.erl index 961e2d89d9..0c0bbc3e66 100644 --- a/lib/asn1/test/testSeqOf.erl +++ b/lib/asn1/test/testSeqOf.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,7 +19,6 @@ %% -module(testSeqOf). --export([compile/3]). -export([main/1]). -include_lib("test_server/include/test_server.hrl"). @@ -35,18 +34,6 @@ -record('SeqEmp',{seq1}). -record('Empty',{}). - -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "SeqOf",[Rules,{outdir,OutDir}]++Options), - ?line ok = asn1ct:compile(DataDir ++ "SeqOfEnum",[Rules,{outdir,OutDir}]++Options), - ?line ok = asn1ct:compile(DataDir ++ "XSeqOf",[Rules,{outdir,OutDir}]++Options). - - - main(Rules) -> ?line {ok,Bytes11} = diff --git a/lib/asn1/test/testSeqOfCho.erl b/lib/asn1/test/testSeqOfCho.erl index 05bd45580f..5b83c8bf21 100644 --- a/lib/asn1/test/testSeqOfCho.erl +++ b/lib/asn1/test/testSeqOfCho.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,7 +19,6 @@ %% -module(testSeqOfCho). --export([compile/3]). -export([main/1]). -include_lib("test_server/include/test_server.hrl"). @@ -31,17 +30,6 @@ -record('SeqOfChoEmbDef_SEQOF',{bool1, int1, seq1 = asn1_DEFAULT}). -record('SeqOfChoEmbOpt_SEQOF',{bool1, int1, seq1 = asn1_NOVALUE}). - - -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "SeqOfCho",[Rules,{outdir,OutDir}]++Options). - - - main(_Rules) -> ?line {ok,Bytes11} = diff --git a/lib/asn1/test/testSeqOfIndefinite.erl b/lib/asn1/test/testSeqOfIndefinite.erl index 0221581cf1..01ef36e0b4 100644 --- a/lib/asn1/test/testSeqOfIndefinite.erl +++ b/lib/asn1/test/testSeqOfIndefinite.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2010. All Rights Reserved. +%% Copyright Ericsson AB 1999-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,42 +19,10 @@ %% -module(testSeqOfIndefinite). --export([compile/3]). -export([main/0]). -include_lib("test_server/include/test_server.hrl"). -%-record('Seq1',{bool1, int1, seq1 = asn1_DEFAULT}). -%-record('Seq2',{seq2 = asn1_DEFAULT, bool2, int2}). -%-record('Seq3',{bool3, seq3 = asn1_DEFAULT, int3}). -%-record('Seq4',{seq41 = asn1_DEFAULT, seq42 = asn1_DEFAULT, seq43 = asn1_DEFAULT}). -%-record('SeqIn',{boolIn, intIn}). -%-record('SeqCho',{bool1, int1, seq1 = asn1_DEFAULT}). -%-record('SeqChoInline',{bool1, int1, seq1 = asn1_DEFAULT}). -%-record('SeqChoOfInline_SEQOF',{bool1, int1, seq1 = asn1_DEFAULT}). -%-record('SeqEmp',{seq1}). -%-record('Empty',{}). - - - -compile(Config,Rules,Opts) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line Options = [Rules,{outdir,OutDir}]++Opts, - ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-Constants-1",Options), - ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-DataTypes-1",Options), - ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-21-4",Options), - ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-20-4",Options), - ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-19-4",Options), - ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-18-4",Options), - ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-17-4",Options), - ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-15-4",Options), - ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-14-4",Options), - ?line ok = asn1ct:compile(DataDir ++ "Mvrasn-11-4",Options), - ?line ok = asn1ct:compile(DataDir ++ "SeqOf",Options). - main() -> ?line ok = test(isd), ?line ok = test(isd2), diff --git a/lib/asn1/test/testSeqOfTag.erl b/lib/asn1/test/testSeqOfTag.erl index 4f56ab717b..2359df0c59 100644 --- a/lib/asn1/test/testSeqOfTag.erl +++ b/lib/asn1/test/testSeqOfTag.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,8 +19,6 @@ %% -module(testSeqOfTag). - --export([compile/3]). -export([main/1]). -include_lib("test_server/include/test_server.hrl"). @@ -45,17 +43,6 @@ -record('Imp',{os, bool}). -record('Exp',{os, bool}). - - -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "SeqOfTag",[Rules,{outdir,OutDir}]++Options). - - - main(_Rules) -> ?line {ok,Bytes11} = diff --git a/lib/asn1/test/testSeqOptional.erl b/lib/asn1/test/testSeqOptional.erl index 0125c9fb3e..8013f3c685 100644 --- a/lib/asn1/test/testSeqOptional.erl +++ b/lib/asn1/test/testSeqOptional.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -20,7 +20,6 @@ -module(testSeqOptional). -include("External.hrl"). --export([compile/3]). -export([main/1]). -include_lib("test_server/include/test_server.hrl"). @@ -37,16 +36,6 @@ -record('SeqIn',{boolIn, intIn}). -record('SeqChoOpt',{int, cho = asn1_NOVALUE}). - -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "SeqOptional",[Rules,{outdir,OutDir}]++Options). - - - main(_Rules) -> ?line {ok,Bytes11} = diff --git a/lib/asn1/test/testSeqPrim.erl b/lib/asn1/test/testSeqPrim.erl index ec48d1b779..c2451a7cd1 100644 --- a/lib/asn1/test/testSeqPrim.erl +++ b/lib/asn1/test/testSeqPrim.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,7 +19,6 @@ %% -module(testSeqPrim). --export([compile/3]). -export([main/1]). -include_lib("test_server/include/test_server.hrl"). @@ -27,15 +26,6 @@ -record('Seq',{bool, boolCon, boolPri, boolApp, boolExpCon, boolExpPri, boolExpApp}). -record('Empty',{}). -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "SeqPrim",[Rules,{outdir,OutDir}]++Options). - - - main(_Rules) -> diff --git a/lib/asn1/test/testSeqSetDefaultVal.erl b/lib/asn1/test/testSeqSetDefaultVal.erl index 5a1a443ebc..ab484db5f2 100644 --- a/lib/asn1/test/testSeqSetDefaultVal.erl +++ b/lib/asn1/test/testSeqSetDefaultVal.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2010. All Rights Reserved. +%% Copyright Ericsson AB 2001-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -20,7 +20,6 @@ -module(testSeqSetDefaultVal). -include("External.hrl"). --export([compile/2]). -export([main/1]). -include_lib("test_server/include/test_server.hrl"). @@ -95,14 +94,6 @@ -record('S4_b',{ba = asn1_DEFAULT, bb = asn1_DEFAULT}). - -compile(Config,Rules) -> - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "Default", - [Rules,der,{outdir,OutDir}]). - main(_Rules) -> ?line {ok,[48,0]} = diff --git a/lib/asn1/test/testSeqTag.erl b/lib/asn1/test/testSeqTag.erl index 60d3629840..9fdaae35dd 100644 --- a/lib/asn1/test/testSeqTag.erl +++ b/lib/asn1/test/testSeqTag.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,7 +19,6 @@ %% -module(testSeqTag). --export([compile/3]). -export([main/1]). -include_lib("test_server/include/test_server.hrl"). @@ -35,16 +34,6 @@ -record('Imp',{os, bool}). -record('Exp',{os, bool}). - -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "SeqTag",[Rules,{outdir,OutDir}]++Options). - - - main(_Rules) -> diff --git a/lib/asn1/test/testSeqTypeRefCho.erl b/lib/asn1/test/testSeqTypeRefCho.erl index 9262fd1bfd..4b9eac7034 100644 --- a/lib/asn1/test/testSeqTypeRefCho.erl +++ b/lib/asn1/test/testSeqTypeRefCho.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,7 +19,6 @@ %% -module(testSeqTypeRefCho). --export([compile/3]). -export([main/1]). -include_lib("test_server/include/test_server.hrl"). @@ -27,16 +26,6 @@ -record('SeqTRcho',{seqCho, seqChoE, 'seqCho-E', 'seqChoE-E'}). - -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "SeqTypeRefCho",[Rules,{outdir,OutDir}]++Options). - - - main(_Rules) -> diff --git a/lib/asn1/test/testSeqTypeRefSeq.erl b/lib/asn1/test/testSeqTypeRefSeq.erl index 51b0f13c57..57ec6c19b1 100644 --- a/lib/asn1/test/testSeqTypeRefSeq.erl +++ b/lib/asn1/test/testSeqTypeRefSeq.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,7 +19,6 @@ %% -module(testSeqTypeRefSeq). --export([compile/3]). -export([main/1]). -include_lib("test_server/include/test_server.hrl"). @@ -46,15 +45,6 @@ -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "SeqTypeRefSeq",[Rules,{outdir,OutDir}]++Options). - - - main(_Rules) -> diff --git a/lib/asn1/test/testSeqTypeRefSet.erl b/lib/asn1/test/testSeqTypeRefSet.erl index a704ce3403..c06a0e7a2b 100644 --- a/lib/asn1/test/testSeqTypeRefSet.erl +++ b/lib/asn1/test/testSeqTypeRefSet.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,7 +19,6 @@ %% -module(testSeqTypeRefSet). --export([compile/3]). -export([main/1]). -include_lib("test_server/include/test_server.hrl"). @@ -31,15 +30,6 @@ -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "SeqTypeRefSet",[Rules,{outdir,OutDir}]++Options). - - - main(_Rules) -> ?line {ok,Bytes41} = diff --git a/lib/asn1/test/testSetDefault.erl b/lib/asn1/test/testSetDefault.erl index e36894327c..8aa205e0f0 100644 --- a/lib/asn1/test/testSetDefault.erl +++ b/lib/asn1/test/testSetDefault.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,7 +19,6 @@ %% -module(testSetDefault). --export([compile/3]). -export([main/1]). -include_lib("test_server/include/test_server.hrl"). @@ -30,16 +29,6 @@ -record('SetIn',{boolIn, intIn}). - -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "SetDefault",[Rules,{outdir,OutDir}]++Options). - - - main(_Rules) -> ?line {ok,Bytes11} = diff --git a/lib/asn1/test/testSetExternal.erl b/lib/asn1/test/testSetExternal.erl index 41f32dcd90..30cddcacfb 100644 --- a/lib/asn1/test/testSetExternal.erl +++ b/lib/asn1/test/testSetExternal.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -20,7 +20,6 @@ -module(testSetExternal). -include("External.hrl"). --export([compile/3]). -export([main/1]). -include_lib("test_server/include/test_server.hrl"). @@ -33,17 +32,6 @@ %-record('Imp',{os, bool}). %-record('Exp',{os, bool}). - -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "SetExternal", - [Rules,{outdir,OutDir}]++Options). - - - main(_Rules) -> ?line {ok,Bytes11} = diff --git a/lib/asn1/test/testSetIndefinite.erl b/lib/asn1/test/testSetIndefinite.erl index bf8b242860..d8e2b6a9cf 100644 --- a/lib/asn1/test/testSetIndefinite.erl +++ b/lib/asn1/test/testSetIndefinite.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2010. All Rights Reserved. +%% Copyright Ericsson AB 1999-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,20 +19,11 @@ %% -module(testSetIndefinite). --export([compile/3]). -export([main/1]). -include_lib("test_server/include/test_server.hrl"). -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "SeqSetIndefinite", - [Rules,{outdir,OutDir}]++Options). - main(per_bin) -> ok; main(per) -> ok; main(ber_bin_v2) -> diff --git a/lib/asn1/test/testSetOf.erl b/lib/asn1/test/testSetOf.erl index 0769b9a344..08723fb468 100644 --- a/lib/asn1/test/testSetOf.erl +++ b/lib/asn1/test/testSetOf.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,7 +19,6 @@ %% -module(testSetOf). --export([compile/3]). -export([main/1]). -include_lib("test_server/include/test_server.hrl"). @@ -37,15 +36,6 @@ -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "SetOf",[Rules,{outdir,OutDir}]++Options). - - - main(_Rules) -> ?line {ok,Bytes11} = diff --git a/lib/asn1/test/testSetOfCho.erl b/lib/asn1/test/testSetOfCho.erl index 474742fbdb..c89bf9596e 100644 --- a/lib/asn1/test/testSetOfCho.erl +++ b/lib/asn1/test/testSetOfCho.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,7 +19,6 @@ %% -module(testSetOfCho). --export([compile/3]). -export([main/1]). -include_lib("test_server/include/test_server.hrl"). @@ -33,15 +32,6 @@ -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "SetOfCho",[Rules,{outdir,OutDir}]++Options). - - - main(_Rules) -> ?line {ok,Bytes11} = diff --git a/lib/asn1/test/testSetOfExternal.erl b/lib/asn1/test/testSetOfExternal.erl index 9e2b01c698..6b280a2595 100644 --- a/lib/asn1/test/testSetOfExternal.erl +++ b/lib/asn1/test/testSetOfExternal.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -20,7 +20,6 @@ -module(testSetOfExternal). --export([compile/3]). -export([main/1]). -include_lib("test_server/include/test_server.hrl"). @@ -32,15 +31,6 @@ -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "SetOfExternal",[Rules,{outdir,OutDir}]++Options). - - - main(_Rules) -> ?line {ok,Bytes11} = diff --git a/lib/asn1/test/testSetOfTag.erl b/lib/asn1/test/testSetOfTag.erl index c101306d7a..2c7a2f5473 100644 --- a/lib/asn1/test/testSetOfTag.erl +++ b/lib/asn1/test/testSetOfTag.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -20,7 +20,6 @@ -module(testSetOfTag). --export([compile/3]). -export([main/1]). -include_lib("test_server/include/test_server.hrl"). @@ -47,15 +46,6 @@ -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "SetOfTag",[Rules,{outdir,OutDir}]++Options). - - - main(_Rules) -> ?line {ok,Bytes11} = diff --git a/lib/asn1/test/testSetOptional.erl b/lib/asn1/test/testSetOptional.erl index 035fa70424..4692941524 100644 --- a/lib/asn1/test/testSetOptional.erl +++ b/lib/asn1/test/testSetOptional.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -20,7 +20,6 @@ -module(testSetOptional). -include("External.hrl"). --export([compile/3]). -export([main/1]). -export([ticket_7533/1,decoder/4]). -include_lib("test_server/include/test_server.hrl"). @@ -36,16 +35,6 @@ -record('SetOpt3Exp',{bool3 = asn1_NOVALUE, set3 = asn1_NOVALUE, int3 = asn1_NOVALUE}). -record('SetIn',{boolIn, intIn}). - -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "SetOptional",[Rules,{outdir,OutDir}]++Options). - - - main(_Rules) -> ?line {ok,Bytes11} = @@ -204,9 +193,8 @@ ticket_7533(Ber) when Ber == ber; Ber == ber_bin -> io:format("Decode result: ~p~n",[Result]), ok after 10000 -> - exit(Pid,normal), io:format("Decode timeout~n",[]), - error + exit(Pid,normal) end; ticket_7533(_) -> ok. diff --git a/lib/asn1/test/testSetPrim.erl b/lib/asn1/test/testSetPrim.erl index e093c918e3..3234b65135 100644 --- a/lib/asn1/test/testSetPrim.erl +++ b/lib/asn1/test/testSetPrim.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,7 +19,6 @@ %% -module(testSetPrim). --export([compile/3]). -export([main/1]). -include_lib("test_server/include/test_server.hrl"). @@ -27,15 +26,6 @@ -record('Set',{bool, boolCon, boolPri, boolApp, boolExpCon, boolExpPri, boolExpApp}). -record('Empty',{}). -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "SetPrim",[Rules,{outdir,OutDir}]++Options). - - - main(_Rules) -> diff --git a/lib/asn1/test/testSetTag.erl b/lib/asn1/test/testSetTag.erl index 8df3e36815..8b9364d603 100644 --- a/lib/asn1/test/testSetTag.erl +++ b/lib/asn1/test/testSetTag.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,7 +19,6 @@ %% -module(testSetTag). --export([compile/3]). -export([main/1]). -include_lib("test_server/include/test_server.hrl"). @@ -35,16 +34,6 @@ -record('Imp',{os, bool}). -record('Exp',{os, bool}). - -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "SetTag",[Rules,{outdir,OutDir}]++Options). - - - main(_Rules) -> diff --git a/lib/asn1/test/testSetTypeRefCho.erl b/lib/asn1/test/testSetTypeRefCho.erl index 1f68a8fbc4..a0989926c7 100644 --- a/lib/asn1/test/testSetTypeRefCho.erl +++ b/lib/asn1/test/testSetTypeRefCho.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,7 +19,6 @@ %% -module(testSetTypeRefCho). --export([compile/3]). -export([main/1]). -include_lib("test_server/include/test_server.hrl"). @@ -28,15 +27,6 @@ -record('SetTRcho',{setCho, setChoE, 'setCho-E', 'setChoE-E'}). -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "SetTypeRefCho",[Rules,{outdir,OutDir}]++Options). - - - main(_Rules) -> diff --git a/lib/asn1/test/testSetTypeRefPrim.erl b/lib/asn1/test/testSetTypeRefPrim.erl index e6cec260e5..9c7fbd803e 100644 --- a/lib/asn1/test/testSetTypeRefPrim.erl +++ b/lib/asn1/test/testSetTypeRefPrim.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,7 +19,6 @@ %% -module(testSetTypeRefPrim). --export([compile/3]). -export([main/1]). -include_lib("test_server/include/test_server.hrl"). @@ -27,15 +26,6 @@ -record('SetTR',{octStr, octStrI, octStrE, 'octStr-I', 'octStrI-I', 'octStrE-I', 'octStr-E', 'octStrI-E', 'octStrE-E'}). -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "SetTypeRefPrim",[Rules,{outdir,OutDir}]++Options). - - - main(_Rules) -> diff --git a/lib/asn1/test/testSetTypeRefSeq.erl b/lib/asn1/test/testSetTypeRefSeq.erl index 0c1c9400bf..a3ef4b188d 100644 --- a/lib/asn1/test/testSetTypeRefSeq.erl +++ b/lib/asn1/test/testSetTypeRefSeq.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,7 +19,6 @@ %% -module(testSetTypeRefSeq). --export([compile/3]). -export([main/1]). -include_lib("test_server/include/test_server.hrl"). @@ -31,15 +30,6 @@ -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "SetTypeRefSeq",[Rules,{outdir,OutDir}]++Options). - - - main(_Rules) -> ?line {ok,Bytes41} = diff --git a/lib/asn1/test/testSetTypeRefSet.erl b/lib/asn1/test/testSetTypeRefSet.erl index 6544e77458..ce77316ef8 100644 --- a/lib/asn1/test/testSetTypeRefSet.erl +++ b/lib/asn1/test/testSetTypeRefSet.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2010. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,7 +19,6 @@ %% -module(testSetTypeRefSet). --export([compile/3]). -export([main/1]). -include_lib("test_server/include/test_server.hrl"). @@ -46,15 +45,6 @@ -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "SetTypeRefSet",[Rules,{outdir,OutDir}]++Options). - - - main(_Rules) -> diff --git a/lib/asn1/test/testTCAP.erl b/lib/asn1/test/testTCAP.erl index 5e29938a16..878ce7c070 100644 --- a/lib/asn1/test/testTCAP.erl +++ b/lib/asn1/test/testTCAP.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2010. All Rights Reserved. +%% Copyright Ericsson AB 2003-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,33 +19,23 @@ %% -module(testTCAP). --export([compile/3,test/2,compile_asn1config/3,test_asn1config/0]). +-export([compile/2,test/2,compile_asn1config/2,test_asn1config/0]). -include_lib("test_server/include/test_server.hrl"). +compile(Config, Options) -> + Files = ["Remote-Operations-Information-Objects", + "TCAPMessages", + "TCAPMessages-simple", + "TCAPPackage"], + asn1_test_lib:compile_all(Files, Config, Options), + asn1_test_lib:compile_erlang("TCAPPackage_msg", Config, []). - -compile(Config,Rules,Opt) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line ok = asn1ct:compile(DataDir ++ "Remote-Operations-Information-Objects",[Rules,{outdir,OutDir}]++Opt), -% ?line ok = asn1ct:compile(DataDir ++ "Remote-Operations-Generic-ROS-PDUs",[Rules,{outdir,OutDir}]++Opt), -% ?line ok = asn1ct:compile(DataDir ++ "Remote-Operations-Useful-Definitions",[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(DataDir ++ "TCAPMessages",[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(DataDir ++ "TCAPMessages-simple",[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(DataDir ++ "TCAPPackage",[Rules,{outdir,OutDir}]++Opt), - ?line compile:file(filename:join([DataDir,"TCAPPackage_msg"]),[{i,OutDir},{outdir,OutDir}]). - -compile_asn1config(Config,Rules,Opt) -> - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line ok = asn1ct:compile(DataDir ++ "TCAPPackage", - [Rules,{outdir,OutDir},{i,DataDir}]++Opt). +compile_asn1config(Config, Options) -> + Files = ["Remote-Operations-Information-Objects", + "TCAPPackage"], + asn1_test_lib:compile_all(Files, Config, Options), + asn1_test_lib:compile_erlang("TCAPPackage_msg", Config, []). test(Erule,_Config) when Erule==ber;Erule==ber_bin;Erule==ber_bin_v2 -> % ?line OutDir = ?config(priv_dir,Config), diff --git a/lib/asn1/test/testTcapsystem.erl b/lib/asn1/test/testTcapsystem.erl index 2f13c11cd4..4979a385b2 100644 --- a/lib/asn1/test/testTcapsystem.erl +++ b/lib/asn1/test/testTcapsystem.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2010. All Rights Reserved. +%% Copyright Ericsson AB 2004-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,54 +19,46 @@ %% -module(testTcapsystem). --export([compile/3]). +-export([compile/2]). -include_lib("test_server/include/test_server.hrl"). - - -compile(Config,Rules,Opt) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line DataDir2 = filename:join([DataDir,tcapsystem]), - - ?line ok = asn1ct:compile(filename:join([DataDir2,"DialoguePDUs.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-ApplicationContexts.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-BS-Code.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-CallHandlingOperations.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-CH-DataTypes.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-CommonDataTypes.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-DialogueInformation.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-ER-DataTypes.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-Errors.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-ExtensionDataTypes.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-GR-DataTypes.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-Group-Call-Operations.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-LCS-DataTypes.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-LocationServiceOperations.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-MobileServiceOperations.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-MS-DataTypes.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-OM-DataTypes.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-OperationAndMaintenanceOperations.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-Protocol.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-SecureTransportOperations.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-ShortMessageServiceOperations.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-SM-DataTypes.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-SS-Code.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-SS-DataTypes.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-ST-DataTypes.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-SupplementaryServiceOperations.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"MAP-TS-Code.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"MobileDomainDefinitions.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"Remote-Operations-Generic-ROS-PDUs.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"Remote-Operations-Information-Objects.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"Remote-Operations-Useful-Definitions.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"TCAP-Examples.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"TCAPMessages.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"TCAP-Tools.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"TC-Notation-Extensions.asn"]),[Rules,{outdir,OutDir}]++Opt), - ?line ok = asn1ct:compile(filename:join([DataDir2,"UnidialoguePDUs.asn"]),[Rules,{outdir,OutDir}]++Opt). - - +compile(Config, Options) -> + [asn1_test_lib:compile(filename:join([tcapsystem, M]), Config, Options) + || M <- ["DialoguePDUs.asn", + "MAP-ApplicationContexts.asn", + "MAP-BS-Code.asn", + "MAP-CallHandlingOperations.asn", + "MAP-CH-DataTypes.asn", + "MAP-CommonDataTypes.asn", + "MAP-DialogueInformation.asn", + "MAP-ER-DataTypes.asn", + "MAP-Errors.asn", + "MAP-ExtensionDataTypes.asn", + "MAP-GR-DataTypes.asn", + "MAP-Group-Call-Operations.asn", + "MAP-LCS-DataTypes.asn", + "MAP-LocationServiceOperations.asn", + "MAP-MobileServiceOperations.asn", + "MAP-MS-DataTypes.asn", + "MAP-OM-DataTypes.asn", + "MAP-OperationAndMaintenanceOperations.asn", + "MAP-Protocol.asn", + "MAP-SecureTransportOperations.asn", + "MAP-ShortMessageServiceOperations.asn", + "MAP-SM-DataTypes.asn", + "MAP-SS-Code.asn", + "MAP-SS-DataTypes.asn", + "MAP-ST-DataTypes.asn", + "MAP-SupplementaryServiceOperations.asn", + "MAP-TS-Code.asn", + "MobileDomainDefinitions.asn", + "Remote-Operations-Generic-ROS-PDUs.asn", + "Remote-Operations-Information-Objects.asn", + "Remote-Operations-Useful-Definitions.asn", + "TCAP-Examples.asn", + "TCAPMessages.asn", + "TCAP-Tools.asn", + "TC-Notation-Extensions.asn", + "UnidialoguePDUs.asn"]], + ok. diff --git a/lib/asn1/test/testTimer.erl b/lib/asn1/test/testTimer.erl index 74002e16e9..2d3b777558 100644 --- a/lib/asn1/test/testTimer.erl +++ b/lib/asn1/test/testTimer.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2010. All Rights Reserved. +%% Copyright Ericsson AB 2001-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -26,12 +26,6 @@ -define(times, 5000). -compile(Config,Enc,Options) -> - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ok = asn1ct:compile(DataDir++"H235-SECURITY-MESSAGES",[Enc,{outdir,OutDir}]++Options), - ok = asn1ct:compile(DataDir++"H323-MESSAGES",[Enc,{outdir,OutDir}]++Options). - val() -> _Value = {'H323-UserInformation',{'H323-UU-PDU', {callProceeding, diff --git a/lib/asn1/test/testTypeValueNotation.erl b/lib/asn1/test/testTypeValueNotation.erl index f0699370e0..cd5223ef23 100644 --- a/lib/asn1/test/testTypeValueNotation.erl +++ b/lib/asn1/test/testTypeValueNotation.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2002-2010. All Rights Reserved. +%% Copyright Ericsson AB 2002-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,60 +19,43 @@ %% -module(testTypeValueNotation). --export([compile/3]). -export([main/2]). -include_lib("test_server/include/test_server.hrl"). --record('Seq',{octstr, int, bool, enum, bitstr, null, oid, vstr}). - - -compile(Config,Rules,Options) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "SeqTypeRefPrim", - [Rules,{outdir,OutDir}]++Options), - %% OTP-6695 - ?line ok = asn1ct:compile(DataDir ++ "ValueTest", - [Rules,{outdir,OutDir}]++Options). - - -main(Rules,Option) -> - - io:format("testTypeValueNotation:main/2 with arguments:~nRules: ~w, Option: ~w~n",[Rules,Option]), - Value1 = #'Seq'{octstr = [1,2,3,4], - int = 12, - bool = true, - enum = a, - bitstr = [1,0,1,0], - null = 'NULL', - oid = {1,2,55}, - vstr = "Hello World"}, - Value2 = #'Seq'{octstr = {'OctStr',[1,2,3,4]}, - int = {'Int',12}, - bool = {'Bool',true}, - enum = {'Enum',a}, - bitstr = {'BitStr',[1,0,1,0]}, - null = {'Null','NULL'}, - oid = {'OId',{1,2,55}}, - vstr = {'VStr',"Hello World"}}, - case Option of - optimize when Rules == per_bin; Rules == ber_bin ; Rules == uper_bin; Rules == ber_bin_v2 -> - ?line {ok,Bytes} = - asn1_wrapper:encode('SeqTypeRefPrim','Seq',Value1), - ?line {error,_Reason} = - asn1_wrapper:encode('SeqTypeRefPrim','Seq',Value2), - ?line {ok,Value1} = - asn1_wrapper:decode('SeqTypeRefPrim','Seq',Bytes); - _ -> - ?line {ok,Bytes} = - asn1_wrapper:encode('SeqTypeRefPrim','Seq',Value1), - ?line {ok,Bytes} = - asn1_wrapper:encode('SeqTypeRefPrim','Seq',Value2), - ?line {ok,Value1} = - asn1_wrapper:decode('SeqTypeRefPrim','Seq',Bytes) - end, - - ok. +-record('Seq', {octstr, int, bool, enum, bitstr, null, oid, vstr}). + +main(Rule, Option) -> + Value1 = #'Seq'{octstr = [1, 2, 3, 4], + int = 12, + bool = true, + enum = a, + bitstr = [1, 0, 1, 0], + null = 'NULL', + oid = {1, 2, 55}, + vstr = "Hello World"}, + Value2 = #'Seq'{octstr = {'OctStr', [1, 2, 3, 4]}, + int = {'Int', 12}, + bool = {'Bool', true}, + enum = {'Enum', a}, + bitstr = {'BitStr', [1, 0, 1, 0]}, + null = {'Null', 'NULL'}, + oid = {'OId', {1, 2, 55}}, + vstr = {'VStr', "Hello World"}}, + main(Rule, Option, Value1, Value2). + +%% Value2 will fail for ber_bin_v2, per_bin with nifs (optimize) and uper_bin +main(ber_bin_v2, _, Value1, Value2) -> encode_fail(Value1, Value2); +main(per_bin, [optimize], Value1, Value2) -> encode_fail(Value1, Value2); +main(uper_bin, [], Value1, Value2) -> encode_fail(Value1, Value2); +main(_, _, Value1, Value2) -> encode_normal(Value1, Value2). + +encode_normal(Value1, Value2) -> + {ok, Bytes} = asn1_wrapper:encode('SeqTypeRefPrim', 'Seq', Value1), + {ok, Bytes} = asn1_wrapper:encode('SeqTypeRefPrim', 'Seq', Value2), + {ok, Value1} = asn1_wrapper:decode('SeqTypeRefPrim', 'Seq', Bytes). + +encode_fail(Value1, Value2) -> + {ok, Bytes} = asn1_wrapper:encode('SeqTypeRefPrim', 'Seq', Value1), + {error, _Reason} = asn1_wrapper:encode('SeqTypeRefPrim', 'Seq', Value2), + {ok, Value1} = asn1_wrapper:decode('SeqTypeRefPrim', 'Seq', Bytes). diff --git a/lib/asn1/test/testX420.erl b/lib/asn1/test/testX420.erl index 1d18e76c48..abdbbfe536 100644 --- a/lib/asn1/test/testX420.erl +++ b/lib/asn1/test/testX420.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2010. All Rights Reserved. +%% Copyright Ericsson AB 2008-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -26,32 +26,21 @@ -include_lib("test_server/include/test_server.hrl"). -compile(Erule,Options,Config) -> - +compile(Erule, Options, Config) -> Specs = specs(), - ?line 99 = length(Specs), - ?line ok = compile_loop(Erule,Specs,Options,Config). - - + 99 = length(Specs), + ok = compile_loop(Erule,Specs,Options,Config). -compile_loop(_Erule,[],_Options,_Config) -> +compile_loop(_Erule, [], _Options, _Config) -> ok; -compile_loop(Erule,[Spec|Specs],Options,Config) - when Erule == ber; Erule == ber_bin; Erule == ber_bin_v2; - Erule == per -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - - case asn1ct:compile(DataDir ++ "/x420/" ++ Spec,[Erule,{outdir,OutDir}, - {i,OutDir}]++Options) of - ok -> - compile_loop(Erule,Specs,Options,Config); - Error -> - Error - end; -compile_loop(_Erule,_Specs,_Options,_Config) -> - ok.%%{skip,io_lib:format("Not tested for ~p",[Erule])}. +compile_loop(Erule, [Spec|Specs], Options, Config) + when Erule == ber; Erule == ber_bin; Erule == ber_bin_v2; Erule == per -> + CaseDir = ?config(case_dir, Config), + asn1_test_lib:compile(filename:join([x420, Spec]), Config, + [Erule, {i, CaseDir}]), + compile_loop(Erule, Specs, Options, Config); +compile_loop(_Erule, _Specs, _Options, _Config) -> + ok. specs() -> @@ -91,7 +80,7 @@ specs() -> "Protected-Part-Descriptors", "ProtocolObjectIdentifiers", "Raster-Gr-Coding-Attributes", "Raster-Gr-Presentation-Attributes", "Raster-Gr-Profile-Attributes", "Reliable-Transfer-APDU", - "Remote-Operations-Abstract-Syntaxes", + "Remote-Operations-Abstract-Syntaxes", "Remote-Operations-Generic-ROS-PDUs", "Remote-Operations-Information-Objects-extensions", "Remote-Operations-Information-Objects", diff --git a/lib/asn1/test/test_bad_values.erl b/lib/asn1/test/test_bad_values.erl deleted file mode 100644 index d379a509ab..0000000000 --- a/lib/asn1/test/test_bad_values.erl +++ /dev/null @@ -1,29 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2005-2010. All Rights Reserved. -%% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%% -%% %CopyrightEnd% -%% -%% --module(test_bad_values). - --export([tests/1]). --include_lib("test_server/include/test_server.hrl"). - -tests(Config) -> - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line {error,_R} = asn1ct:compile(DataDir ++ "BadEnumValue1",[{outdir,OutDir}]), - ok. diff --git a/lib/asn1/test/test_compile_options.erl b/lib/asn1/test/test_compile_options.erl index a622d5bfd2..4e732308d8 100644 --- a/lib/asn1/test/test_compile_options.erl +++ b/lib/asn1/test/test_compile_options.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2011. All Rights Reserved. +%% Copyright Ericsson AB 2005-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -40,10 +40,7 @@ wrong_path(Config) -> comp(Parent,Config) -> DataDir = ?config(data_dir,Config), OutDir = ?config(priv_dir,Config), - %%?line true = code:add_patha(?config(priv_dir,Config)), - io:format("DataDir: ~p~n",[DataDir]), ?line Err=asn1ct:compile(DataDir++"NoImport",[{i,OutDir},{i,filename:join([DataDir,"subdir"])},{outdir,OutDir}]), - io:format("compiling process terminated with value: ~p~n",[Err]), Parent!Err. %% OTP-5701 @@ -67,13 +64,7 @@ path(Config) -> file:set_cwd(CWD), ok. -ticket_6143(Config) -> - DataDir = ?config(data_dir,Config), - OutDir = ?config(priv_dir,Config), - io:format("DataDir: ~p~n",[DataDir]), - - ?line ok=asn1ct:compile(filename:join([DataDir,"AA1"]),[{i,DataDir},{outdir,OutDir}]), - ok. +ticket_6143(Config) -> asn1_test_lib:compile("AA1", Config, []). noobj(Config) -> DataDir = ?config(data_dir,Config), diff --git a/lib/asn1/test/test_driver_load.erl b/lib/asn1/test/test_driver_load.erl index 965f2473e9..e0e6602046 100644 --- a/lib/asn1/test/test_driver_load.erl +++ b/lib/asn1/test/test_driver_load.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2010. All Rights Reserved. +%% Copyright Ericsson AB 2003-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,29 +19,16 @@ %% -module(test_driver_load). --export([compile/2,test/2,encode/0]). +-export([test/1,encode/0]). -include_lib("test_server/include/test_server.hrl"). -test(per_bin,0) -> +test(0) -> ok; -test(per_bin,N) -> +test(N) -> spawn(?MODULE,encode,[]), - test(per_bin,N-1); -test(_,_) -> - ok. - -compile(Config,per_bin) -> - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line ok = asn1ct:compile(DataDir ++ "P-Record", - [per_bin,optimize,{outdir,OutDir}]); -compile(_,Erule) -> - {skip,lists:concat(["not implemented for version: ",Erule])}. - + test(N-1). encode() -> ?line Msg = msg(), diff --git a/lib/asn1/test/test_inline.erl b/lib/asn1/test/test_inline.erl index b7ec0d8921..62625572e3 100644 --- a/lib/asn1/test/test_inline.erl +++ b/lib/asn1/test/test_inline.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2011. All Rights Reserved. +%% Copyright Ericsson AB 2004-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,7 +19,7 @@ %% -module(test_inline). --export([compile/3,main/1,inline1/3,performance/1,performance2/0]). +-export([compile/2,main/2,inline1/3,performance/1,performance2/0]). -export([mvrasn_inlined_encdec/2,mvrasn_encdec/2, mi_encdec/2,m_encdec/2]). @@ -27,52 +27,38 @@ -define(times, 5000). -define(times2, 50000). -compile(Config,_Rules,Opt) -> - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line true = code:add_patha(DataDir), - - ?line ok=asn1ct:compile(DataDir++"Mvrasn.set.asn",[{inline,mvrasn_inlined},{outdir,OutDir}]++Opt), - ?line ok=asn1ct:compile(DataDir++"Mvrasn-11-6.asn",[{outdir,OutDir}]++Opt), +compile(Config, Options) -> + CaseDir = ?config(case_dir, Config), + asn1_test_lib:compile("Mvrasn.set.asn", Config, [{inline, mvrasn_inlined}|Options]), + asn1_test_lib:compile("Mod.set.asn", Config, [{inline, m}|Options]), + ok = remove_inlined_files(CaseDir, [filename:join([CaseDir, X])||X<-["m.erl", "m.beam"]]), + asn1_test_lib:compile("Mod.set.asn", Config, [inline|Options]), + ok = remove_inlined_files(CaseDir, []). - ?line ok=asn1ct:compile(DataDir++"Mod.set.asn",[{inline,m},{outdir,OutDir}]++Opt), - ?line ok=remove_inlined_files(OutDir,[filename:join([OutDir,X])||X<-["m.erl","m.beam"]]), - ?line ok=asn1ct:compile(DataDir++"Mod.set.asn",[inline,{outdir,OutDir}]++Opt), - ?line ok=remove_inlined_files(OutDir,[]). - -inline1(Config,Rule,Opt) -> - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - - ?line ok=asn1ct:compile(DataDir++"P-Record", - [{inline,'inlined_P_Record'}, - {outdir,OutDir}]++Opt), - ?line test_inline1(), - - ?line ok=remove_inlined_files2(OutDir,ber_bin_v2), +inline1(Config, Rule, Opt) -> + CaseDir = ?config(case_dir, Config), + + asn1_test_lib:compile("P-Record", Config, [{inline, 'inlined_P_Record'}|Opt]), + test_inline1(), + + ok=remove_inlined_files2(CaseDir, ber_bin_v2), case Rule of - ber_bin_v2 -> - ?line ok=asn1ct:compile(DataDir++"P-Record", - [inline,asn1config,ber_bin,optimize, - {outdir,OutDir}]++Opt), - ?line test_inline2(Rule,'P-Record'), - ?line remove_inlined_files3(OutDir,Rule), - io:format("compiling ~p~nwith ~p~n", - [DataDir ++ "p_record.set.asn", - [inline,asn1config,ber_bin,optimize,{outdir,OutDir}]++Opt]), - ?line ok = asn1ct:compile(DataDir ++ "p_record.set.asn", - [inline,asn1config,ber_bin,optimize, - {outdir,OutDir}]++Opt), - ?line test_inline2(Rule,'p_record'), - ?line remove_inlined_files4(OutDir,Rule); - _ -> - ok + ber_bin_v2 -> + asn1_test_lib:compile("P-Record", Config, + [ber_bin, inline, asn1config, optimize|Opt]), + test_inline2(Rule, 'P-Record'), + remove_inlined_files3(CaseDir, Rule), + asn1_test_lib:compile("p_record.set.asn", Config, + [ber_bin, inline, asn1config, optimize|Opt]), + test_inline2(Rule, 'p_record'), + remove_inlined_files4(CaseDir, Rule); + _ -> + ok end. -main(_Erule) -> - ?line Val = val(), +main(Config, _Erule) -> + Val = val(Config), ?line {ok,Bytes}=asn1_wrapper:encode(mvrasn_inlined,'InsertSubscriberDataArg',Val), ?line {ok,_Val2}=asn1_wrapper:decode(mvrasn_inlined,'InsertSubscriberDataArg',Bytes). @@ -94,14 +80,13 @@ test_inline2(ber_bin_v2,Mod) -> test_inline2(_,_) -> ok. -val() -> - ?line {ok,Val} = asn1ct:value('Mvrasn-11-6','InsertSubscriberDataArg'), +val(Config) -> + {ok,Val} = asn1ct:value('Mvrasn','InsertSubscriberDataArg', + [{i, ?config(case_dir, Config)}]), Val. performance(Config) -> - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line true = code:add_patha(?config(data_dir,Config)), - ?line Val = val(), + Val = val(Config), %% warm up timer:tc(?MODULE,mvrasn_inlined_encdec,[2,Val]), %% performance test diff --git a/lib/asn1/test/test_modified_x420.erl b/lib/asn1/test/test_modified_x420.erl index 4e96db070b..2e9dfeee87 100644 --- a/lib/asn1/test/test_modified_x420.erl +++ b/lib/asn1/test/test_modified_x420.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2010. All Rights Reserved. +%% Copyright Ericsson AB 2008-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -20,18 +20,10 @@ -module(test_modified_x420). %-compile(export_all). --export([compile/1, test_io/1]). +-export([test_io/1]). -include_lib("test_server/include/test_server.hrl"). -compile(Config) -> - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - - ok = asn1ct:compile(filename:join([DataDir,modified_x420,"PKCS7"]),[der,{outdir,OutDir}]), - ok = asn1ct:compile(filename:join([DataDir,modified_x420,"InformationFramework"]),[der,{outdir,OutDir}]), - ok = asn1ct:compile(filename:join([DataDir,modified_x420,"AuthenticationFramework"]),[der,{outdir,OutDir}]). - test_io(Config) -> io:format("~p~n~n", [catch test(Config)]). diff --git a/lib/asn1/test/test_partial_incomplete_decode.erl b/lib/asn1/test/test_partial_incomplete_decode.erl index a2e0a96bd8..df56c27115 100644 --- a/lib/asn1/test/test_partial_incomplete_decode.erl +++ b/lib/asn1/test/test_partial_incomplete_decode.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2010. All Rights Reserved. +%% Copyright Ericsson AB 2003-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,40 +19,11 @@ %% -module(test_partial_incomplete_decode). --export([compile/3,test/2]). +-export([test/1]). -include_lib("test_server/include/test_server.hrl"). - - -compile(Config,Rule,Opt) when Rule == ber_bin_v2 -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line ok = asn1ct:compile(DataDir ++ "PartialDecSeq.asn", - [Rule,{outdir,OutDir},{i,DataDir}, - asn1config]++Opt), - ?line ok = asn1ct:compile(DataDir ++ "PartialDecSeq2.asn", - [Rule,{outdir,OutDir},{i,DataDir}, - asn1config]++Opt), - ?line ok = asn1ct:compile(DataDir ++ "PartialDecSeq3.asn", - [Rule,{outdir,OutDir},{i,DataDir}, - asn1config]++Opt), - ?line ok = asn1ct:compile(DataDir ++ "PartialDecMyHTTP.asn", - [Rule,{outdir,OutDir},{i,DataDir}, - asn1config]++Opt), - ?line ok = asn1ct:compile(DataDir ++ "MEDIA-GATEWAY-CONTROL.asn", - [Rule,{outdir,OutDir},{i,DataDir}, - asn1config]++Opt), - ?line ok = asn1ct:compile(DataDir ++ "P-Record", - [Rule,{outdir,OutDir},{i,DataDir}, - asn1config]++Opt); -compile(_,Rule,_) -> - {skip,lists:concat(["not implemented yet for version: ",Rule])}. - -test(ber_bin_v2,Config) -> +test(Config) -> FMsg = msg('F'), ?line {ok,Bytes} = asn1_wrapper:encode('PartialDecSeq','F',FMsg), ?line {ok,_} = asn1_wrapper:decode('PartialDecSeq','F',Bytes), @@ -110,9 +81,7 @@ test(ber_bin_v2,Config) -> %% test of MEDIA-GATEWAY-CONTROL test_megaco(Config), - ok; -test(Erule,_) -> - {skip,lists:concat(["not implemented yet for version: ",Erule])}. + ok. test_megaco(Config) -> ?line DataDir = ?config(data_dir,Config), diff --git a/lib/asn1/test/test_selective_decode.erl b/lib/asn1/test/test_selective_decode.erl index e1e101b622..bb348611da 100644 --- a/lib/asn1/test/test_selective_decode.erl +++ b/lib/asn1/test/test_selective_decode.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2010. All Rights Reserved. +%% Copyright Ericsson AB 2003-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,12 +19,12 @@ %% -module(test_selective_decode). --export([test/2]). +-export([test/0]). -include_lib("test_server/include/test_server.hrl"). -test(ber_bin_v2,_Config) -> +test() -> FMsg = msg('F'), ?line {ok,Bytes} = asn1_wrapper:encode('PartialDecSeq','F',FMsg), ?line {ok,3} = @@ -48,10 +48,7 @@ test(ber_bin_v2,_Config) -> ?line {ok,Bytes4} = asn1_wrapper:encode('P-Record','PersonnelRecord', PRecMsg), ?line {ok,_} = 'P-Record':sel_dec(list_to_binary(Bytes4)), - - ok; -test(Erule,_) -> - {skip,lists:concat(["not implemented yet for version: ",Erule])}. + ok. diff --git a/lib/asn1/test/test_special_decode_performance.erl b/lib/asn1/test/test_special_decode_performance.erl index 60a95a3675..4ac0ff2b27 100644 --- a/lib/asn1/test/test_special_decode_performance.erl +++ b/lib/asn1/test/test_special_decode_performance.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2010. All Rights Reserved. +%% Copyright Ericsson AB 2003-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,25 +19,10 @@ %% -module(test_special_decode_performance). --export([compile/2,go/1,loop2/4,loop1/5]). +-export([go/1,loop2/4,loop1/5]). -include_lib("test_server/include/test_server.hrl"). - -compile(Config,Rule) when Rule==ber_bin_v2 -> - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line asn1ct:compile(DataDir++"MEDIA-GATEWAY-CONTROL", - [ber_bin,optimize,asn1config,{outdir,OutDir}, - {i,DataDir}]), - ?line asn1ct:compile(DataDir++"PartialDecSeq", - [ber_bin,optimize,asn1config,{outdir,OutDir}, - {i,DataDir}]); -compile(_,Rule) -> - {skip,lists:concat(["not implemented yet for version: ",Rule])}. - go(all) -> {Time_S_s,Time_S_e,Time_S_c}=go(10000,'PartialDecSeq'), {Time_MGC_s,Time_MGC_e,Time_MGC_c}=go(10000,'MEDIA-GATEWAY-CONTROL'), diff --git a/lib/asn1/test/test_undecoded_rest.erl b/lib/asn1/test/test_undecoded_rest.erl index 647fe2bb1c..36fd26ed59 100644 --- a/lib/asn1/test/test_undecoded_rest.erl +++ b/lib/asn1/test/test_undecoded_rest.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2010. All Rights Reserved. +%% Copyright Ericsson AB 2004-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,47 +19,35 @@ %% -module(test_undecoded_rest). --export([compile/3,test/1]). +-export([test/2]). -include_lib("test_server/include/test_server.hrl"). %% testing OTP-5104 -compile(Config,Rules,Opt) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - - ?line ok = asn1ct:compile(DataDir ++ "P-Record",[Rules,{outdir,OutDir}]++Opt). - - -test(Opt) -> - ?line {ok,Msg} = asn1ct:value('P-Record','PersonnelRecord'), - ?line {ok,Bytes} = asn1_wrapper:encode('P-Record','PersonnelRecord',Msg), - Bytes2 = - fun(B) when is_list(B) -> - B ++ [55,55,55]; - (B) when is_binary(B) -> - iolist_to_binary([B,<<55,55,55>>]) - end (Bytes), - +test(Opt, Config) -> + {ok, Msg} = asn1ct:value('P-Record', 'PersonnelRecord', + [{i, ?config(case_dir, Config)}]), + {ok, Bytes} = asn1_wrapper:encode('P-Record', 'PersonnelRecord', Msg), + Bytes2 = if is_list(Bytes) -> + Bytes ++ [55, 55, 55]; + is_binary(Bytes) -> + iolist_to_binary([Bytes, <<55, 55, 55>>]) + end, case Opt of - undec_rest -> - ?line {ok,Msg,R}=asn1_wrapper:decode('P-Record','PersonnelRecord', - Bytes2), - ?line case R of - <<55,55,55>> ->ok; - [55,55,55] -> ok; - BStr when is_bitstring(BStr) -> - PadLen = (8 - (bit_size(BStr) rem 8)) rem 8, - case <<0:PadLen,BStr/bitstring>> of - <<0,55,55,55>> -> ok - end - end; - _ -> - ?line {ok,Msg} = asn1_wrapper:decode('P-Record','PersonnelRecord', - Bytes2) + undec_rest -> + {ok, Msg, R} = asn1_wrapper:decode('P-Record', 'PersonnelRecord', + Bytes2), + case R of + <<55, 55, 55>> -> ok; + [55, 55, 55] -> ok; + BStr when is_bitstring(BStr) -> + PadLen = (8 - (bit_size(BStr) rem 8)) rem 8, + <<0, 55, 55, 55>> = <<0:PadLen, BStr/bitstring>> + end; + _ -> + {ok, Msg} = asn1_wrapper:decode('P-Record', 'PersonnelRecord', + Bytes2) end, ok. diff --git a/lib/asn1/test/test_x691.erl b/lib/asn1/test/test_x691.erl index bc8a3495d8..dcfa211d80 100644 --- a/lib/asn1/test/test_x691.erl +++ b/lib/asn1/test/test_x691.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2010. All Rights Reserved. +%% Copyright Ericsson AB 2008-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,25 +19,10 @@ %% -module(test_x691). --export([compile/3]). -export([cases/2]). -include_lib("test_server/include/test_server.hrl"). - -compile(Config,Rules,Option) -> - - ?line DataDir = ?config(data_dir,Config), - ?line OutDir = ?config(priv_dir,Config), - ?line true = code:add_patha(?config(priv_dir,Config)), - ?line ok = asn1ct:compile(DataDir ++ "P-RecordA1", - [Rules, {outdir,OutDir}]++Option), - ?line ok = asn1ct:compile(DataDir ++ "P-RecordA2", - [Rules, {outdir,OutDir}]++Option), - ?line ok = asn1ct:compile(DataDir ++ "P-RecordA3", - [Rules, {outdir,OutDir}]++Option). - - cases(Erule,Variant) -> MsgA1 = a1(), ?line {ok,B1} = asn1_wrapper:encode('P-RecordA1','PersonnelRecord',MsgA1), diff --git a/lib/common_test/priv/ct_default.css b/lib/common_test/priv/ct_default.css index 75f8d5db8a..8ae6990cd8 100644 --- a/lib/common_test/priv/ct_default.css +++ b/lib/common_test/priv/ct_default.css @@ -81,13 +81,21 @@ div.copyright { color: #000000; } -div.ct_internal { +div.ct_internal { background: lightgrey; color: black; font-family: "Monaco", "Andale Mono", "Consolas", monospace; font-size: .95em; margin: .2em 0 0 0; } +div.ct_error_notify { + background: #CC0000; + color: #FFFFFF; + font-family: "Monaco", "Andale Mono", "Consolas", monospace; + font-size: 1.05em; + margin: .2em 0 0 0; +} + div.default { background: lightgreen; color: black; font-family: "Monaco", "Andale Mono", "Consolas", monospace; diff --git a/lib/common_test/src/ct.erl b/lib/common_test/src/ct.erl index e0e82283c4..63a8adbc63 100644 --- a/lib/common_test/src/ct.erl +++ b/lib/common_test/src/ct.erl @@ -64,7 +64,7 @@ print/1, print/2, print/3, pal/1, pal/2, pal/3, capture_start/0, capture_stop/0, capture_get/0, capture_get/1, - fail/1, fail/2, comment/1, comment/2, + fail/1, fail/2, comment/1, comment/2, make_priv_dir/0, testcases/2, userdata/2, userdata/3, timetrap/1, get_timetrap_info/0, sleep/1]). @@ -585,8 +585,16 @@ capture_get([]) -> %%% @doc Terminate a test case with the given error %%% <code>Reason</code>. fail(Reason) -> - exit({test_case_failed,Reason}). - + try + exit({test_case_failed,Reason}) + catch + Class:R -> + case erlang:get_stacktrace() of + [{?MODULE,fail,1,_}|Stk] -> ok; + Stk -> ok + end, + erlang:raise(Class, R, Stk) + end. %%%----------------------------------------------------------------- %%% @spec fail(Format, Args) -> void() @@ -599,13 +607,21 @@ fail(Reason) -> fail(Format, Args) -> try io_lib:format(Format, Args) of Str -> - exit({test_case_failed,lists:flatten(Str)}) + try + exit({test_case_failed,lists:flatten(Str)}) + catch + Class:R -> + case erlang:get_stacktrace() of + [{?MODULE,fail,2,_}|Stk] -> ok; + Stk -> ok + end, + erlang:raise(Class, R, Stk) + end catch _:BadArgs -> exit({BadArgs,{?MODULE,fail,[Format,Args]}}) end. - %%%----------------------------------------------------------------- %%% @spec comment(Comment) -> void() %%% Comment = term() @@ -657,6 +673,15 @@ send_html_comment(Comment) -> ct_util:set_testdata({comment,Html}), test_server:comment(Html). +%%%----------------------------------------------------------------- +%%% @spec make_priv_dir() -> ok | {error,Reason} +%%% Reason = term() +%%% @doc If the test has been started with the create_priv_dir +%%% option set to manual_per_tc, in order for the test case to use +%%% the private directory, it must first create it by calling +%%% this function. +make_priv_dir() -> + test_server:make_priv_dir(). %%%----------------------------------------------------------------- %%% @spec get_target_name(Handle) -> {ok,TargetName} | {error,Reason} @@ -845,6 +870,8 @@ get_status() -> get_testdata(Key) -> case catch ct_util:get_testdata(Key) of + {error,ct_util_server_not_running} -> + no_tests_running; Error = {error,_Reason} -> Error; {'EXIT',_Reason} -> diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index c24a7c238b..187794e78b 100644 --- a/lib/common_test/src/ct_framework.erl +++ b/lib/common_test/src/ct_framework.erl @@ -29,7 +29,8 @@ -export([get_logopts/0, format_comment/1, get_html_wrapper/3]). --export([error_in_suite/1, ct_init_per_group/2, ct_end_per_group/2]). +-export([error_in_suite/1, init_per_suite/1, end_per_suite/1, + init_per_group/2, end_per_group/2]). -export([make_all_conf/3, make_conf/5]). @@ -54,6 +55,7 @@ init_tc(Mod,Func,Config) -> %% in case Mod == ct_framework, lookup the suite name Suite = get_suite_name(Mod, Config), + %% check if previous testcase was interpreted and has left %% a "dead" trace window behind - if so, kill it case ct_util:get_testdata(interpret) of @@ -63,27 +65,17 @@ init_tc(Mod,Func,Config) -> _ -> ok end, - %% check if we need to add defaults explicitly because - %% there's no init_per_suite exported from Mod - {InitFailed,DoInit} = - case ct_util:get_testdata(curr_tc) of - {Suite,{suite0_failed,_}=Failure} -> - {Failure,false}; - {?MODULE,_} -> % should not really happen - {false,false}; - {Suite,_} -> % Func is not 1st case in suite - {false,false}; - _ when Func == init_per_suite -> % defaults will be added anyway - {false,false}; - _ -> % first case in suite - {false,true} - end, - case InitFailed of - false -> + + case ct_util:get_testdata(curr_tc) of + {Suite,{suite0_failed,{require,Reason}}} -> + {skip,{require_failed_in_suite0,Reason}}; + {Suite,{suite0_failed,_}=Failure} -> + {skip,Failure}; + _ -> ct_util:set_testdata({curr_tc,{Suite,Func}}), case ct_util:read_suite_data({seq,Suite,Func}) of undefined -> - init_tc1(Mod,Func,Config,DoInit); + init_tc1(Mod,Suite,Func,Config); Seq when is_atom(Seq) -> case ct_util:read_suite_data({seq,Suite,Seq}) of [Func|TCs] -> % this is the 1st case in Seq @@ -96,17 +88,13 @@ init_tc(Mod,Func,Config) -> _ -> ok end, - init_tc1(Mod,Func,Config,DoInit); + init_tc1(Mod,Suite,Func,Config); {failed,Seq,BadFunc} -> {skip,{sequence_failed,Seq,BadFunc}} - end; - {_,{require,Reason}} -> - {skip,{require_failed_in_suite0,Reason}}; - _ -> - {skip,InitFailed} + end end. -init_tc1(?MODULE,error_in_suite,[Config0],_) when is_list(Config0) -> +init_tc1(?MODULE,_,error_in_suite,[Config0]) when is_list(Config0) -> ct_logs:init_tc(false), ct_event:notify(#event{name=tc_start, node=node(), @@ -117,14 +105,16 @@ init_tc1(?MODULE,error_in_suite,[Config0],_) when is_list(Config0) -> Reason -> {skip,Reason} end; -init_tc1(Mod,Func,[Config0],DoInit) when is_list(Config0) -> + +init_tc1(Mod,Suite,Func,[Config0]) when is_list(Config0) -> Config1 = case ct_util:read_suite_data(last_saved_config) of - {{Mod,LastFunc},SavedConfig} -> % last testcase + {{Suite,LastFunc},SavedConfig} -> % last testcase [{saved_config,{LastFunc,SavedConfig}} | lists:keydelete(saved_config,1,Config0)]; - {{LastSuite,InitOrEnd},SavedConfig} when InitOrEnd == init_per_suite ; - InitOrEnd == end_per_suite -> + {{LastSuite,InitOrEnd}, + SavedConfig} when InitOrEnd == init_per_suite ; + InitOrEnd == end_per_suite -> %% last suite [{saved_config,{LastSuite,SavedConfig}} | lists:keydelete(saved_config,1,Config0)]; @@ -133,13 +123,14 @@ init_tc1(Mod,Func,[Config0],DoInit) when is_list(Config0) -> end, ct_util:delete_suite_data(last_saved_config), Config = lists:keydelete(watchdog,1,Config1), - if Func /= init_per_suite, DoInit /= true -> - ok; - true -> + + if Func == init_per_suite -> %% delete all default values used in previous suite ct_config:delete_default_config(suite), %% release all name -> key bindings (once per suite) - ct_config:release_allocated() + ct_config:release_allocated(); + Func /= init_per_suite -> + ok end, GroupPath = ?val(tc_group_path, Config, []), @@ -154,9 +145,7 @@ init_tc1(Mod,Func,[Config0],DoInit) when is_list(Config0) -> true -> ct_config:delete_default_config(testcase) end, - %% in case Mod == ct_framework, lookup the suite name - Suite = get_suite_name(Mod, Config), - case add_defaults(Mod,Func,AllGroups,DoInit) of + case add_defaults(Mod,Func,AllGroups) of Error = {suite0_failed,_} -> ct_logs:init_tc(false), ct_event:notify(#event{name=tc_start, @@ -166,35 +155,25 @@ init_tc1(Mod,Func,[Config0],DoInit) when is_list(Config0) -> {error,Error}; {SuiteInfo,MergeResult} -> case MergeResult of - {error,Reason} when DoInit == false -> + {error,Reason} -> ct_logs:init_tc(false), ct_event:notify(#event{name=tc_start, node=node(), data={Mod,FuncSpec}}), {skip,Reason}; _ -> - init_tc2(Mod,Func,SuiteInfo,MergeResult, - Config,DoInit) + init_tc2(Mod,Suite,Func,SuiteInfo,MergeResult,Config) end end; -init_tc1(_Mod,_Func,Args,_DoInit) -> - {ok,Args}. -init_tc2(Mod,Func,SuiteInfo,MergeResult,Config,DoInit) -> - %% if first testcase fails when there's no init_per_suite - %% we must do suite/0 configurations before skipping test - MergedInfo = - case MergeResult of - {error,_} when DoInit == true -> - SuiteInfo; - _ -> - MergeResult - end, +init_tc1(_Mod,_Suite,_Func,Args) -> + {ok,Args}. +init_tc2(Mod,Suite,Func,SuiteInfo,MergeResult,Config) -> %% timetrap must be handled before require - MergedInfo1 = timetrap_first(MergedInfo, [], []), + MergedInfo = timetrap_first(MergeResult, [], []), %% tell logger to use specified style sheet - case lists:keysearch(stylesheet,1,MergedInfo++Config) of + case lists:keysearch(stylesheet,1,MergeResult++Config) of {value,{stylesheet,SSFile}} -> ct_logs:set_stylesheet(Func,add_data_dir(SSFile,Config)); _ -> @@ -209,7 +188,7 @@ init_tc2(Mod,Func,SuiteInfo,MergeResult,Config,DoInit) -> %% list of {Type,Bool} tuples, e.g. {telnet,true}), case ct_util:get_overridden_silenced_connections() of undefined -> - case lists:keysearch(silent_connections,1,MergedInfo++Config) of + case lists:keysearch(silent_connections,1,MergeResult++Config) of {value,{silent_connections,Conns}} -> ct_util:silence_connections(Conns); _ -> @@ -218,18 +197,14 @@ init_tc2(Mod,Func,SuiteInfo,MergeResult,Config,DoInit) -> Conns -> ct_util:silence_connections(Conns) end, - if Func /= init_per_suite, DoInit /= true -> - ct_logs:init_tc(false); - true -> - ct_logs:init_tc(true) - end, + ct_logs:init_tc(Func == init_per_suite), FuncSpec = group_or_func(Func,Config), ct_event:notify(#event{name=tc_start, node=node(), data={Mod,FuncSpec}}), - case catch configure(MergedInfo1,MergedInfo1,SuiteInfo, - {FuncSpec,DoInit},Config) of + case catch configure(MergedInfo,MergedInfo,SuiteInfo, + FuncSpec,Config) of {suite0_failed,Reason} -> ct_util:set_testdata({curr_tc,{Mod,{suite0_failed,{require,Reason}}}}), {skip,{require_failed_in_suite0,Reason}}; @@ -246,7 +221,7 @@ init_tc2(Mod,Func,SuiteInfo,MergeResult,Config,DoInit) -> _ -> case get('$test_server_framework_test') of undefined -> - ct_suite_init(Mod, FuncSpec, FinalConfig); + ct_suite_init(Suite, FuncSpec, FinalConfig); Fun -> case Fun(init_tc, FinalConfig) of NewConfig when is_list(NewConfig) -> @@ -258,21 +233,21 @@ init_tc2(Mod,Func,SuiteInfo,MergeResult,Config,DoInit) -> end end. -ct_suite_init(Mod, Func, [Config]) when is_list(Config) -> - case ct_hooks:init_tc( Mod, Func, Config) of +ct_suite_init(Suite, Func, [Config]) when is_list(Config) -> + case ct_hooks:init_tc(Suite, Func, Config) of NewConfig when is_list(NewConfig) -> {ok, [NewConfig]}; Else -> Else end. -add_defaults(Mod,Func, GroupPath, DoInit) -> +add_defaults(Mod,Func, GroupPath) -> Suite = get_suite_name(Mod, GroupPath), case (catch Suite:suite()) of {'EXIT',{undef,_}} -> SuiteInfo = merge_with_suite_defaults(Suite,[]), SuiteInfoNoCTH = [I || I <- SuiteInfo, element(1,I) =/= ct_hooks], - case add_defaults1(Mod,Func, GroupPath, SuiteInfoNoCTH, DoInit) of + case add_defaults1(Mod,Func, GroupPath, SuiteInfoNoCTH) of Error = {error,_} -> {SuiteInfo,Error}; MergedInfo -> {SuiteInfo,MergedInfo} end; @@ -292,7 +267,7 @@ add_defaults(Mod,Func, GroupPath, DoInit) -> SuiteInfoNoCTH = [I || I <- SuiteInfo1, element(1,I) =/= ct_hooks], case add_defaults1(Mod,Func, GroupPath, - SuiteInfoNoCTH, DoInit) of + SuiteInfoNoCTH) of Error = {error,_} -> {SuiteInfo1,Error}; MergedInfo -> {SuiteInfo1,MergedInfo} end; @@ -313,7 +288,7 @@ add_defaults(Mod,Func, GroupPath, DoInit) -> {suite0_failed,bad_return_value} end. -add_defaults1(Mod,Func, GroupPath, SuiteInfo, DoInit) -> +add_defaults1(Mod,Func, GroupPath, SuiteInfo) -> Suite = get_suite_name(Mod, GroupPath), %% GroupPathInfo (for subgroup on level X) = %% [LevelXGroupInfo, LevelX-1GroupInfo, ..., TopLevelGroupInfo] @@ -325,8 +300,7 @@ add_defaults1(Mod,Func, GroupPath, SuiteInfo, DoInit) -> _ -> [] end end, GroupPath), - Args = if Func == init_per_group; Func == ct_init_per_group; - Func == end_per_group; Func == ct_end_per_group -> + Args = if Func == init_per_group ; Func == end_per_group -> [?val(name, hd(GroupPath))]; true -> [] @@ -347,7 +321,7 @@ add_defaults1(Mod,Func, GroupPath, SuiteInfo, DoInit) -> (default_config == element(1,SDDef)))], case check_for_clashes(TestCaseInfo, GroupPathInfo, SuiteReqs) of [] -> - add_defaults2(Mod,Func, TCAndGroupInfo,SuiteInfo,SuiteReqs, DoInit); + add_defaults2(Mod,Func, TCAndGroupInfo,SuiteInfo,SuiteReqs); Clashes -> {error,{config_name_already_in_use,Clashes}} end. @@ -421,34 +395,25 @@ keysmember([Key,Pos|Next], List) -> keysmember([], _) -> true. -add_defaults2(Mod,init_per_suite, IPSInfo, SuiteInfo,SuiteReqs, false) -> - add_defaults2(Mod,init_per_suite, IPSInfo, SuiteInfo,SuiteReqs, true); +add_defaults2(_Mod,init_per_suite, IPSInfo, SuiteInfo,SuiteReqs) -> + Info = lists:flatten([IPSInfo, SuiteReqs]), + lists:flatten([Info,remove_info_in_prev(Info, [SuiteInfo])]); -add_defaults2(_Mod,IPG, IPGAndGroupInfo, SuiteInfo,SuiteReqs, DoInit) when - IPG == init_per_group ; IPG == ct_init_per_group -> - %% If DoInit == true, we have to process the suite() list, otherwise - %% it has already been handled (see clause for init_per_suite) - case DoInit of - true -> - %% note: we know for sure this is a top level group - Info = lists:flatten([IPGAndGroupInfo, SuiteReqs]), - Info ++ remove_info_in_prev(Info, [SuiteInfo]); - false -> - SuiteInfo1 = - remove_info_in_prev(lists:flatten([IPGAndGroupInfo, - SuiteReqs]), [SuiteInfo]), - %% don't require terms in prev groups (already processed) - case IPGAndGroupInfo of - [IPGInfo] -> - lists:flatten([IPGInfo,SuiteInfo1]); - [IPGInfo | [CurrGroupInfo | PrevGroupInfo]] -> - PrevGroupInfo1 = delete_require_terms(PrevGroupInfo), - lists:flatten([IPGInfo,CurrGroupInfo,PrevGroupInfo1, - SuiteInfo1]) - end +add_defaults2(_Mod,init_per_group, IPGAndGroupInfo, SuiteInfo,SuiteReqs) -> + SuiteInfo1 = + remove_info_in_prev(lists:flatten([IPGAndGroupInfo, + SuiteReqs]), [SuiteInfo]), + %% don't require terms in prev groups (already processed) + case IPGAndGroupInfo of + [IPGInfo] -> + lists:flatten([IPGInfo,SuiteInfo1]); + [IPGInfo | [CurrGroupInfo | PrevGroupInfo]] -> + PrevGroupInfo1 = delete_require_terms(PrevGroupInfo), + lists:flatten([IPGInfo,CurrGroupInfo,PrevGroupInfo1, + SuiteInfo1]) end; -add_defaults2(_Mod,_Func, TCAndGroupInfo, SuiteInfo,SuiteReqs, false) -> +add_defaults2(_Mod,_Func, TCAndGroupInfo, SuiteInfo,SuiteReqs) -> %% Include require elements from test case info and current group, %% but not from previous groups or suite/0 (since we've already required %% those vars). Let test case info elements override group and suite @@ -463,14 +428,7 @@ add_defaults2(_Mod,_Func, TCAndGroupInfo, SuiteInfo,SuiteReqs, false) -> PrevGroupInfo1 = delete_require_terms(PrevGroupInfo), lists:flatten([TCInfo,CurrGroupInfo,PrevGroupInfo1, SuiteInfo1]) - end; - -add_defaults2(_Mod,_Func, TCInfo, SuiteInfo,SuiteReqs, true) -> - %% Here we have to process the suite info list also (no call to - %% init_per_suite before this first test case). This TC can't belong - %% to a group, or the clause for (ct_)init_per_group would've caught this. - Info = lists:flatten([TCInfo, SuiteReqs]), - lists:flatten([Info,remove_info_in_prev(Info, [SuiteInfo])]). + end. delete_require_terms([Info | Prev]) -> Info1 = [T || T <- Info, @@ -558,18 +516,9 @@ configure([],_,_,_,Config) -> %% function and be scoped 'group', or come from the testcase %% info function and then be scoped 'testcase' -required_default(Name,Key,Info,SuiteInfo,{FuncSpec,true}) -> - case try_set_default(Name,Key,SuiteInfo,suite) of - ok -> - ok; - _ -> - required_default(Name,Key,Info,[],{FuncSpec,false}) - end; -required_default(Name,Key,Info,_,{init_per_suite,_}) -> +required_default(Name,Key,Info,_,init_per_suite) -> try_set_default(Name,Key,Info,suite); -required_default(Name,Key,Info,_,{{init_per_group,GrName,_},_}) -> - try_set_default(Name,Key,Info,{group,GrName}); -required_default(Name,Key,Info,_,{{ct_init_per_group,GrName,_},_}) -> +required_default(Name,Key,Info,_,{init_per_group,GrName,_}) -> try_set_default(Name,Key,Info,{group,GrName}); required_default(Name,Key,Info,_,_FuncSpec) -> try_set_default(Name,Key,Info,testcase). @@ -621,6 +570,9 @@ end_tc(Mod,Func,{Result,[Args]}, Return) -> end_tc(Mod,Func,self(),Result,Args,Return). end_tc(Mod,Func,TCPid,Result,Args,Return) -> + %% in case Mod == ct_framework, lookup the suite name + Suite = get_suite_name(Mod, Args), + case lists:keysearch(watchdog,1,Args) of {value,{watchdog,Dog}} -> test_server:timetrap_cancel(Dog); false -> ok @@ -636,60 +588,62 @@ end_tc(Mod,Func,TCPid,Result,Args,Return) -> end, ct_util:delete_testdata(comment), ct_util:delete_suite_data(last_saved_config), - FuncSpec = - case group_or_func(Func,Args) of - {_,GroupName,_Props} = Group -> - if Func == end_per_group; Func == ct_end_per_group -> - ct_config:delete_default_config({group,GroupName}); - true -> ok - end, - case lists:keysearch(save_config,1,Args) of - {value,{save_config,SaveConfig}} -> - ct_util:save_suite_data( - last_saved_config, - {Mod,{group,GroupName}}, - SaveConfig), - Group; - false -> - Group - end; - _ -> - case lists:keysearch(save_config,1,Args) of - {value,{save_config,SaveConfig}} -> - ct_util:save_suite_data(last_saved_config, - {Mod,Func},SaveConfig), - Func; - false -> - Func - end - end, - ct_util:reset_silent_connections(), + + FuncSpec = case group_or_func(Func,Args) of + {_,_GroupName,_} = Group -> Group; + _ -> Func + end, case get('$test_server_framework_test') of undefined -> {FinalResult,FinalNotify} = case ct_hooks:end_tc( - Mod, FuncSpec, Args, Result, Return) of + Suite, FuncSpec, Args, Result, Return) of '$ct_no_change' -> {ok,Result}; FinalResult1 -> {FinalResult1,FinalResult1} end, - % send sync notification so that event handlers may print - % in the log file before it gets closed + %% send sync notification so that event handlers may print + %% in the log file before it gets closed ct_event:sync_notify(#event{name=tc_done, node=node(), data={Mod,FuncSpec, tag_cth(FinalNotify)}}); Fun -> - % send sync notification so that event handlers may print - % in the log file before it gets closed + %% send sync notification so that event handlers may print + %% in the log file before it gets closed ct_event:sync_notify(#event{name=tc_done, node=node(), data={Mod,FuncSpec,tag(Result)}}), FinalResult = Fun(end_tc, Return) + end, + + case FuncSpec of + {_,GroupName,_Props} -> + if Func == end_per_group -> + ct_config:delete_default_config({group,GroupName}); + true -> ok + end, + case lists:keysearch(save_config,1,Args) of + {value,{save_config,SaveConfig}} -> + ct_util:save_suite_data(last_saved_config, + {Suite,{group,GroupName}}, + SaveConfig); + false -> + ok + end; + _ -> + case lists:keysearch(save_config,1,Args) of + {value,{save_config,SaveConfig}} -> + ct_util:save_suite_data(last_saved_config, + {Suite,Func},SaveConfig); + false -> + ok + end end, + ct_util:reset_silent_connections(), case FinalResult of {skip,{sequence_failed,_,_}} -> @@ -706,7 +660,7 @@ end_tc(Mod,Func,TCPid,Result,Args,Return) -> end, case Func of end_per_suite -> - ct_util:match_delete_suite_data({seq,Mod,'_'}); + ct_util:match_delete_suite_data({seq,Suite,'_'}); _ -> ok end, @@ -806,31 +760,36 @@ error_notification(Mod,Func,_Args,{Error,Loc}) -> end end, - io:format(user, "~n- - - - - - - - - - - - - - - - " - "- - - - - - - - - -~n", []), + PrintErr = fun(ErrFormat, ErrArgs) -> + Div = "~n- - - - - - - - - - - - - - - - " + "- - - - - - - - - -~n", + io:format(user, lists:concat([Div,ErrFormat,Div,"~n"]), + ErrArgs), + ct_logs:tc_log(ct_error_notify, "CT Error Notification", + ErrFormat, ErrArgs) + end, case Loc of - %% we don't use the line parse transform as we compile this - %% module so location will be on form {M,F} [{?MODULE,error_in_suite}] -> - io:format(user, "Error in suite detected: ~s", [ErrStr]); + PrintErr("Error in suite detected: ~s", [ErrStr]); - R when R == unknown; R == undefined -> - io:format(user, "Error detected: ~s", [ErrStr]); + R when R == unknown; R == undefined -> + PrintErr("Error detected: ~s", [ErrStr]); %% if a function specified by all/0 does not exist, we %% pick up undef here - [{LastMod,LastFunc}] -> - io:format(user, "~w:~w could not be executed~n", - [LastMod,LastFunc]), - io:format(user, "Reason: ~s", [ErrStr]); + [{LastMod,LastFunc}|_] when ErrStr == "undef" -> + PrintErr("~w:~w could not be executed~nReason: ~s", + [LastMod,LastFunc,ErrStr]); + + [{LastMod,LastFunc}|_] -> + PrintErr("~w:~w failed~nReason: ~s", [LastMod,LastFunc,ErrStr]); [{LastMod,LastFunc,LastLine}|_] -> %% print error to console, we are only %% interested in the last executed expression - io:format(user, "~w:~w failed on line ~w~n", - [LastMod,LastFunc,LastLine]), - io:format(user, "Reason: ~s", [ErrStr]), - + PrintErr("~w:~w failed on line ~w~nReason: ~s", + [LastMod,LastFunc,LastLine,ErrStr]), + case ct_util:read_suite_data({seq,Mod,Func}) of undefined -> ok; @@ -839,8 +798,6 @@ error_notification(Mod,Func,_Args,{Error,Loc}) -> mark_as_failed(Seq,Mod,Func,SeqTCs) end end, - io:format(user, "~n- - - - - - - - - - - - - - - - " - "- - - - - - - - - -~n~n", []), ok. %% cases in seq that have already run @@ -861,9 +818,7 @@ mark_as_failed1(_,_,_,[]) -> ok. group_or_func(Func, Config) when Func == init_per_group; - Func == end_per_group; - Func == ct_init_per_group; - Func == ct_end_per_group -> + Func == end_per_group -> case ?val(tc_group_properties, Config) of undefined -> {Func,unknown,[]}; @@ -1206,8 +1161,8 @@ make_conf(Mod, Name, Props, TestSpec) -> "end_per_group/2 missing for group " "~p in ~p, using default.", [Name,Mod]), - {{?MODULE,ct_init_per_group}, - {?MODULE,ct_end_per_group}, + {{?MODULE,init_per_group}, + {?MODULE,end_per_group}, [{suite,Mod}]} end, {conf,[{name,Name}|Props++ExtraProps],InitConf,TestSpec,EndConf}. @@ -1467,22 +1422,31 @@ error_in_suite(Config) -> Reason = test_server:lookup_config(error,Config), exit(Reason). +%% if init_per_suite and end_per_suite are missing in the suite, +%% these will be called instead (without any trace of them in the +%% log files), only so that it's possible to call hook functions +%% for configuration +init_per_suite(Config) -> + Config. + +end_per_suite(_Config) -> + ok. + %% if the group config functions are missing in the suite, %% use these instead -ct_init_per_group(GroupName, Config) -> +init_per_group(GroupName, Config) -> ct:comment(io_lib:format("start of ~p", [GroupName])), ct_logs:log("TEST INFO", "init_per_group/2 for ~w missing " "in suite, using default.", [GroupName]), Config. -ct_end_per_group(GroupName, _) -> +end_per_group(GroupName, _) -> ct:comment(io_lib:format("end of ~p", [GroupName])), ct_logs:log("TEST INFO", "end_per_group/2 for ~w missing " "in suite, using default.", [GroupName]), ok. - %%%----------------------------------------------------------------- %%% @spec report(What,Data) -> ok @@ -1559,10 +1523,6 @@ report(What,Data) -> ok; {end_per_group,_} -> ok; - {ct_init_per_group,_} -> - ok; - {ct_end_per_group,_} -> - ok; {_,ok} -> add_to_stats(ok); {_,{skipped,{failed,{_,init_per_testcase,_}}}} -> @@ -1599,8 +1559,7 @@ report(What,Data) -> data=Data}), ct_hooks:on_tc_skip(What, Data), if Case /= end_per_suite, - Case /= end_per_group, - Case /= ct_end_per_group -> + Case /= end_per_group -> add_to_stats(auto_skipped); true -> ok diff --git a/lib/common_test/src/ct_hooks.erl b/lib/common_test/src/ct_hooks.erl index c42adbbdd9..2a23cd992b 100644 --- a/lib/common_test/src/ct_hooks.erl +++ b/lib/common_test/src/ct_hooks.erl @@ -70,8 +70,7 @@ terminate(Hooks) -> {skip, Reason :: term()} | {auto_skip, Reason :: term()} | {fail, Reason :: term()}. -init_tc(ct_framework, _Func, Args) -> - Args; + init_tc(Mod, init_per_suite, Config) -> Info = try proplists:get_value(ct_hooks, Mod:suite(),[]) of List when is_list(List) -> @@ -104,27 +103,21 @@ init_tc(_Mod, TC, Config) -> {auto_skip, Reason :: term()} | {fail, Reason :: term()} | ok | '$ct_no_change'. -end_tc(ct_framework, _Func, _Args, Result, _Return) -> - Result; end_tc(Mod, init_per_suite, Config, _Result, Return) -> call(fun call_generic/3, Return, [post_init_per_suite, Mod, Config], '$ct_no_change'); - end_tc(Mod, end_per_suite, Config, Result, _Return) -> call(fun call_generic/3, Result, [post_end_per_suite, Mod, Config], '$ct_no_change'); - end_tc(_Mod, {init_per_group, GroupName, _}, Config, _Result, Return) -> call(fun call_generic/3, Return, [post_init_per_group, GroupName, Config], '$ct_no_change'); - end_tc(Mod, {end_per_group, GroupName, Opts}, Config, Result, _Return) -> Res = call(fun call_generic/3, Result, [post_end_per_group, GroupName, Config], '$ct_no_change'), maybe_stop_locker(Mod, GroupName,Opts), Res; - end_tc(_Mod, TC, Config, Result, _Return) -> call(fun call_generic/3, Result, [post_end_per_testcase, TC, Config], '$ct_no_change'). diff --git a/lib/common_test/src/ct_logs.erl b/lib/common_test/src/ct_logs.erl index 19ad7b26d8..0cd9b5f7cb 100644 --- a/lib/common_test/src/ct_logs.erl +++ b/lib/common_test/src/ct_logs.erl @@ -38,7 +38,7 @@ -export([get_ts_html_wrapper/3]). %% Logging stuff directly from testcase --export([tc_log/3,tc_print/3,tc_pal/3,ct_log/3, +-export([tc_log/3,tc_log/4,tc_log_async/3,tc_print/3,tc_pal/3,ct_log/3, basic_html/0]). %% Simulate logger process for use without ct environment running @@ -239,7 +239,7 @@ end_tc(TCPid) -> %%% activity it is. <code>Format</code> and <code>Args</code> is the %%% data to log (as in <code>io:format(Format,Args)</code>).</p> log(Heading,Format,Args) -> - cast({log,self(),group_leader(), + cast({log,sync,self(),group_leader(), [{int_header(),[log_timestamp(now()),Heading]}, {Format,Args}, {int_footer(),[]}]}), @@ -261,7 +261,7 @@ log(Heading,Format,Args) -> %%% @see cont_log/2 %%% @see end_log/0 start_log(Heading) -> - cast({log,self(),group_leader(), + cast({log,sync,self(),group_leader(), [{int_header(),[log_timestamp(now()),Heading]}]}), ok. @@ -276,7 +276,7 @@ cont_log([],[]) -> ok; cont_log(Format,Args) -> maybe_log_timestamp(), - cast({log,self(),group_leader(),[{Format,Args}]}), + cast({log,sync,self(),group_leader(),[{Format,Args}]}), ok. %%%----------------------------------------------------------------- @@ -287,7 +287,7 @@ cont_log(Format,Args) -> %%% @see start_log/1 %%% @see cont_log/2 end_log() -> - cast({log,self(),group_leader(),[{int_footer(), []}]}), + cast({log,sync,self(),group_leader(),[{int_footer(), []}]}), ok. @@ -333,9 +333,32 @@ add_link(Heading,File,Type) -> %%% stuff directly from a testcase (i.e. not from within the CT %%% framework).</p> tc_log(Category,Format,Args) -> - cast({log,self(),group_leader(),[{div_header(Category),[]}, - {Format,Args}, - {div_footer(),[]}]}), + tc_log(Category,"User",Format,Args). + +tc_log(Category,Printer,Format,Args) -> + cast({log,sync,self(),group_leader(),[{div_header(Category,Printer),[]}, + {Format,Args}, + {div_footer(),[]}]}), + ok. + + +%%%----------------------------------------------------------------- +%%% @spec tc_log_async(Category,Format,Args) -> ok +%%% Category = atom() +%%% Format = string() +%%% Args = list() +%%% +%%% @doc Internal use only. +%%% +%%% <p>This function is used to perform asynchronous printouts +%%% towards the test server IO handler. This is necessary in order +%%% to avoid deadlocks when e.g. the hook that handles SASL printouts +%%% prints to the test case log file at the same time test server +%%% asks ct_logs for an html wrapper.</p> +tc_log_async(Category,Format,Args) -> + cast({log,async,self(),group_leader(),[{div_header(Category),[]}, + {Format,Args}, + {div_footer(),[]}]}), ok. %%%----------------------------------------------------------------- @@ -349,19 +372,18 @@ tc_log(Category,Format,Args) -> %%% <p>This function is called by <code>ct</code> when printing %%% stuff a testcase on the user console.</p> tc_print(Category,Format,Args) -> - print_heading(Category), - io:format(user,Format,Args), - io:format(user,"\n\n",[]), + Head = get_heading(Category), + io:format(user, lists:concat([Head,Format,"\n\n"]), Args), ok. -print_heading(default) -> - io:format(user, - "----------------------------------------------------\n~s\n", - [log_timestamp(now())]); -print_heading(Category) -> - io:format(user, - "----------------------------------------------------\n~s ~w\n", - [log_timestamp(now()),Category]). +get_heading(default) -> + io_lib:format("-----------------------------" + "-----------------------\n~s\n", + [log_timestamp(now())]); +get_heading(Category) -> + io_lib:format("-----------------------------" + "-----------------------\n~s ~w\n", + [log_timestamp(now()),Category]). %%%----------------------------------------------------------------- @@ -377,9 +399,9 @@ print_heading(Category) -> %%% log and on the console.</p> tc_pal(Category,Format,Args) -> tc_print(Category,Format,Args), - cast({log,self(),group_leader(),[{div_header(Category),[]}, - {Format,Args}, - {div_footer(),[]}]}), + cast({log,sync,self(),group_leader(),[{div_header(Category),[]}, + {Format,Args}, + {div_footer(),[]}]}), ok. @@ -408,8 +430,10 @@ int_footer() -> "</div>". div_header(Class) -> - "<div class=\"" ++ atom_to_list(Class) ++ "\"><b>*** User " ++ - log_timestamp(now()) ++ " ***</b>". + div_header(Class,"User"). +div_header(Class,Printer) -> + "<div class=\"" ++ atom_to_list(Class) ++ "\"><b>*** " ++ Printer ++ + " " ++ log_timestamp(now()) ++ " ***</b>". div_footer() -> "</div>". @@ -420,7 +444,7 @@ maybe_log_timestamp() -> {MS,S,_} -> ok; _ -> - cast({log,self(),group_leader(), + cast({log,sync,self(),group_leader(), [{"<i>~s</i>",[log_timestamp({MS,S,US})]}]}) end. @@ -441,7 +465,8 @@ log_timestamp({MS,S,US}) -> orig_GL, ct_log_fd, tc_groupleaders, - stylesheet}). + stylesheet, + async_print_jobs}). logger(Parent,Mode) -> register(?MODULE,self()), @@ -520,50 +545,32 @@ logger(Parent,Mode) -> start_time=Time, orig_GL=group_leader(), ct_log_fd=CtLogFd, - tc_groupleaders=[]}). + tc_groupleaders=[], + async_print_jobs=[]}). logger_loop(State) -> receive - {log,Pid,GL,List} -> - case get_groupleader(Pid,GL,State) of + {log,SyncOrAsync,Pid,GL,List} -> + case get_groupleader(Pid, GL, State) of {tc_log,TCGL,TCGLs} -> case erlang:is_process_alive(TCGL) of true -> - %% we have to build one io-list of all strings - %% before printing, or other io printouts (made in - %% parallel) may get printed between this header - %% and footer - Fun = - fun({Str,Args},IoList) -> - case catch io_lib:format(Str,Args) of - {'EXIT',_Reason} -> - Fd = State#logger_state.ct_log_fd, - io:format(Fd, - "Logging fails! " - "Str: ~p, Args: ~p~n", - [Str,Args]), - %% stop the testcase, we need - %% to see the fault - exit(Pid,{log_printout_error,Str,Args}), - []; - IoStr when IoList == [] -> - [IoStr]; - IoStr -> - [IoList,"\n",IoStr] - end - end, - io:format(TCGL,"~s",[lists:foldl(Fun,[],List)]), - logger_loop(State#logger_state{tc_groupleaders=TCGLs}); + State1 = print_to_log(SyncOrAsync, Pid, TCGL, + List, State), + logger_loop(State1#logger_state{tc_groupleaders = + TCGLs}); false -> - %% Group leader is dead, so write to the CtLog instead + %% Group leader is dead, so write to the + %% CtLog instead Fd = State#logger_state.ct_log_fd, [begin io:format(Fd,Str,Args),io:nl(Fd) end || {Str,Args} <- List], logger_loop(State) end; {ct_log,Fd,TCGLs} -> - [begin io:format(Fd,Str,Args),io:nl(Fd) end || {Str,Args} <- List], - logger_loop(State#logger_state{tc_groupleaders=TCGLs}) + [begin io:format(Fd,Str,Args),io:nl(Fd) end || + {Str,Args} <- List], + logger_loop(State#logger_state{tc_groupleaders = TCGLs}) end; {{init_tc,TCPid,GL,RefreshLog},From} -> print_style(GL, State#logger_state.stylesheet), @@ -575,11 +582,12 @@ logger_loop(State) -> make_last_run_index(State#logger_state.start_time) end, return(From,ok), - logger_loop(State#logger_state{tc_groupleaders=TCGLs}); + logger_loop(State#logger_state{tc_groupleaders = TCGLs}); {{end_tc,TCPid},From} -> set_evmgr_gl(State#logger_state.ct_log_fd), return(From,ok), - logger_loop(State#logger_state{tc_groupleaders=rm_tc_gl(TCPid,State)}); + logger_loop(State#logger_state{tc_groupleaders = + rm_tc_gl(TCPid,State)}); {{get_log_dir,true},From} -> return(From,{ok,State#logger_state.log_dir}), logger_loop(State); @@ -590,21 +598,35 @@ logger_loop(State) -> make_last_run_index(State#logger_state.start_time), return(From,filename:basename(State#logger_state.log_dir)), logger_loop(State); - {set_stylesheet,_,SSFile} when State#logger_state.stylesheet == SSFile -> + {set_stylesheet,_,SSFile} when State#logger_state.stylesheet == + SSFile -> logger_loop(State); {set_stylesheet,TC,SSFile} -> Fd = State#logger_state.ct_log_fd, - io:format(Fd, "~p loading external style sheet: ~s~n", [TC,SSFile]), - logger_loop(State#logger_state{stylesheet=SSFile}); + io:format(Fd, "~p loading external style sheet: ~s~n", + [TC,SSFile]), + logger_loop(State#logger_state{stylesheet = SSFile}); {clear_stylesheet,_} when State#logger_state.stylesheet == undefined -> logger_loop(State); {clear_stylesheet,_} -> - logger_loop(State#logger_state{stylesheet=undefined}); + logger_loop(State#logger_state{stylesheet = undefined}); {ct_log, List} -> Fd = State#logger_state.ct_log_fd, [begin io:format(Fd,Str,Args),io:nl(Fd) end || {Str,Args} <- List], logger_loop(State); + {'DOWN',Ref,_,_Pid,_} -> + %% there might be print jobs executing in parallel with ct_logs + %% and whenever one is finished (indicated by 'DOWN'), the + %% next job should be spawned + case lists:delete(Ref, State#logger_state.async_print_jobs) of + [] -> + logger_loop(State#logger_state{async_print_jobs = []}); + Jobs -> + [Next|JobsRev] = lists:reverse(Jobs), + Jobs1 = [print_next(Next)|lists:reverse(JobsRev)], + logger_loop(State#logger_state{async_print_jobs = Jobs1}) + end; stop -> io:format(State#logger_state.ct_log_fd, int_header()++int_footer(), @@ -613,6 +635,49 @@ logger_loop(State) -> ok end. +create_io_fun(FromPid, State) -> + %% we have to build one io-list of all strings + %% before printing, or other io printouts (made in + %% parallel) may get printed between this header + %% and footer + Fd = State#logger_state.ct_log_fd, + fun({Str,Args}, IoList) -> + case catch io_lib:format(Str,Args) of + {'EXIT',_Reason} -> + io:format(Fd, "Logging fails! Str: ~p, Args: ~p~n", + [Str,Args]), + %% stop the testcase, we need to see the fault + exit(FromPid, {log_printout_error,Str,Args}), + []; + IoStr when IoList == [] -> + [IoStr]; + IoStr -> + [IoList,"\n",IoStr] + end + end. + +print_to_log(sync, FromPid, TCGL, List, State) -> + IoFun = create_io_fun(FromPid, State), + io:format(TCGL, "~s", [lists:foldl(IoFun, [], List)]), + State; + +print_to_log(async, FromPid, TCGL, List, State) -> + IoFun = create_io_fun(FromPid, State), + Printer = fun() -> + io:format(TCGL, "~s", [lists:foldl(IoFun, [], List)]) + end, + case State#logger_state.async_print_jobs of + [] -> + {_Pid,Ref} = spawn_monitor(Printer), + State#logger_state{async_print_jobs = [Ref]}; + Queue -> + State#logger_state{async_print_jobs = [Printer|Queue]} + end. + +print_next(PrintFun) -> + {_Pid,Ref} = spawn_monitor(PrintFun), + Ref. + %% #logger_state.tc_groupleaders == [{Pid,{Type,GLPid}},...] %% Type = tc | io %% @@ -855,33 +920,48 @@ insert_dir(D,[D1|Ds]) -> insert_dir(D,[]) -> [D]. -make_last_run_index([Name|Rest], Result, TotSucc, TotFail, UserSkip, AutoSkip, - TotNotBuilt, Missing) -> - case last_test(Name) of +make_last_run_index([Name|Rest], Result, TotSucc, TotFail, + UserSkip, AutoSkip, TotNotBuilt, Missing) -> + case get_run_dirs(Name) of false -> %% Silently skip. - make_last_run_index(Rest, Result, TotSucc, TotFail, UserSkip, AutoSkip, - TotNotBuilt, Missing); - LastLogDir -> + make_last_run_index(Rest, Result, TotSucc, TotFail, + UserSkip, AutoSkip, TotNotBuilt, Missing); + LogDirs -> SuiteName = filename:rootname(filename:basename(Name)), - case make_one_index_entry(SuiteName, LastLogDir, "-", false, Missing) of - {Result1,Succ,Fail,USkip,ASkip,NotBuilt} -> - %% for backwards compatibility - AutoSkip1 = case catch AutoSkip+ASkip of - {'EXIT',_} -> undefined; - Res -> Res - end, - make_last_run_index(Rest, [Result|Result1], TotSucc+Succ, - TotFail+Fail, UserSkip+USkip, AutoSkip1, - TotNotBuilt+NotBuilt, Missing); - error -> - make_last_run_index(Rest, Result, TotSucc, TotFail, UserSkip, AutoSkip, - TotNotBuilt, Missing) - end + {Result1,TotSucc1,TotFail1,UserSkip1,AutoSkip1,TotNotBuilt1} = + make_last_run_index1(SuiteName, LogDirs, Result, + TotSucc, TotFail, + UserSkip, AutoSkip, + TotNotBuilt, Missing), + make_last_run_index(Rest, Result1, TotSucc1, TotFail1, + UserSkip1, AutoSkip1, + TotNotBuilt1, Missing) end; + make_last_run_index([], Result, TotSucc, TotFail, UserSkip, AutoSkip, TotNotBuilt, _) -> {ok, [Result|total_row(TotSucc, TotFail, UserSkip, AutoSkip, TotNotBuilt, false)], {TotSucc,TotFail,UserSkip,AutoSkip,TotNotBuilt}}. + +make_last_run_index1(SuiteName, [LogDir | LogDirs], Result, TotSucc, TotFail, + UserSkip, AutoSkip, TotNotBuilt, Missing) -> + case make_one_index_entry(SuiteName, LogDir, "-", false, Missing) of + {Result1,Succ,Fail,USkip,ASkip,NotBuilt} -> + %% for backwards compatibility + AutoSkip1 = case catch AutoSkip+ASkip of + {'EXIT',_} -> undefined; + Res -> Res + end, + make_last_run_index1(SuiteName, LogDirs, [Result|Result1], TotSucc+Succ, + TotFail+Fail, UserSkip+USkip, AutoSkip1, + TotNotBuilt+NotBuilt, Missing); + error -> + make_last_run_index1(SuiteName, LogDirs, Result, TotSucc, TotFail, + UserSkip, AutoSkip, TotNotBuilt, Missing) + end; +make_last_run_index1(_, [], Result, TotSucc, TotFail, + UserSkip, AutoSkip, TotNotBuilt, _) -> + {Result,TotSucc,TotFail,UserSkip,AutoSkip,TotNotBuilt}. make_one_index_entry(SuiteName, LogDir, Label, All, Missing) -> case count_cases(LogDir) of @@ -1633,8 +1713,8 @@ make_all_suites_index(NewTestData = {_TestName,DirName}) -> sort_logdirs([Dir|Dirs],Groups) -> TestName = filename:rootname(filename:basename(Dir)), case filelib:wildcard(filename:join(Dir,"run.*")) of - [RunDir] -> - Groups1 = insert_test(TestName,{filename:basename(RunDir),RunDir},Groups), + RunDirs = [_|_] -> + Groups1 = sort_logdirs1(TestName,RunDirs,Groups), sort_logdirs(Dirs,Groups1); _ -> % ignore missing run directory sort_logdirs(Dirs,Groups) @@ -1642,6 +1722,12 @@ sort_logdirs([Dir|Dirs],Groups) -> sort_logdirs([],Groups) -> lists:keysort(1,sort_each_group(Groups)). +sort_logdirs1(TestName,[RunDir|RunDirs],Groups) -> + Groups1 = insert_test(TestName,{filename:basename(RunDir),RunDir},Groups), + sort_logdirs1(TestName,RunDirs,Groups1); +sort_logdirs1(_,[],Groups) -> + Groups. + insert_test(Test,IxDir,[{Test,IxDirs}|Groups]) -> [{Test,[IxDir|IxDirs]}|Groups]; insert_test(Test,IxDir,[]) -> @@ -1894,7 +1980,7 @@ simulate() -> simulate_logger_loop() -> receive - {log,_,_,List} -> + {log,_,_,_,List} -> S = [[io_lib:format(Str,Args),io_lib:nl()] || {Str,Args} <- List], io:format("~s",[S]), simulate_logger_loop(); @@ -1933,21 +2019,17 @@ notify_and_unlock_file(File) -> end. %%%----------------------------------------------------------------- -%%% @spec last_test(Dir) -> string() | false +%%% @spec get_run_dirs(Dir) -> [string()] | false %%% %%% @doc %%% -last_test(Dir) -> - last_test(filelib:wildcard(filename:join(Dir, "run.[1-2]*")), false). - -last_test([Run|Rest], false) -> - last_test(Rest, Run); -last_test([Run|Rest], Latest) when Run > Latest -> - last_test(Rest, Run); -last_test([_|Rest], Latest) -> - last_test(Rest, Latest); -last_test([], Latest) -> - Latest. +get_run_dirs(Dir) -> + case filelib:wildcard(filename:join(Dir, "run.[1-2]*")) of + [] -> + false; + RunDirs -> + lists:sort(RunDirs) + end. %%%----------------------------------------------------------------- %%% @spec xhtml(HTML, XHTML) -> HTML | XHTML diff --git a/lib/common_test/src/ct_repeat.erl b/lib/common_test/src/ct_repeat.erl index be3c485b75..e6eb135ae8 100644 --- a/lib/common_test/src/ct_repeat.erl +++ b/lib/common_test/src/ct_repeat.erl @@ -116,7 +116,7 @@ spawn_tester(script,Ctrl,Args) -> spawn_tester(func,Ctrl,Opts) -> Tester = fun() -> - case catch ct_run:run_test1(Opts) of + case catch ct_run:run_test2(Opts) of {'EXIT',Reason} -> exit(Reason); Result -> diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl index 05b10bca32..72124f6f21 100644 --- a/lib/common_test/src/ct_run.erl +++ b/lib/common_test/src/ct_run.erl @@ -37,7 +37,7 @@ %% Misc internal functions --export([variables_file_name/1,script_start1/2,run_test1/1]). +-export([variables_file_name/1,script_start1/2,run_test2/1]). -include("ct_event.hrl"). -include("ct_util.hrl"). @@ -63,6 +63,7 @@ stylesheet, multiply_timetraps = 1, scale_timetraps = false, + create_priv_dir, testspecs = [], tests}). @@ -178,6 +179,10 @@ script_start1(Parent, Args) -> fun([CT]) -> list_to_atom(CT); ([]) -> true end, false, Args), + CreatePrivDir = get_start_opt(create_priv_dir, + fun([PD]) -> list_to_atom(PD); + ([]) -> auto_per_tc + end, Args), EvHandlers = event_handler_args2opts(Args), CTHooks = ct_hooks_args2opts(Args), EnableBuiltinHooks = get_start_opt(enable_builtin_hooks, @@ -255,7 +260,8 @@ script_start1(Parent, Args) -> silent_connections = SilentConns, stylesheet = Stylesheet, multiply_timetraps = MultTT, - scale_timetraps = ScaleTT}, + scale_timetraps = ScaleTT, + create_priv_dir = CreatePrivDir}, %% check if log files should be refreshed or go on to run tests... Result = run_or_refresh(StartOpts, Args), @@ -322,12 +328,21 @@ script_start2(StartOpts = #opts{vts = undefined, Cover = choose_val(StartOpts#opts.cover, SpecStartOpts#opts.cover), - MultTT = choose_val(StartOpts#opts.multiply_timetraps, - SpecStartOpts#opts.multiply_timetraps), - ScaleTT = choose_val(StartOpts#opts.scale_timetraps, - SpecStartOpts#opts.scale_timetraps), - AllEvHs = merge_vals([StartOpts#opts.event_handlers, - SpecStartOpts#opts.event_handlers]), + MultTT = + choose_val(StartOpts#opts.multiply_timetraps, + SpecStartOpts#opts.multiply_timetraps), + ScaleTT = + choose_val(StartOpts#opts.scale_timetraps, + SpecStartOpts#opts.scale_timetraps), + + CreatePrivDir = + choose_val(StartOpts#opts.create_priv_dir, + SpecStartOpts#opts.create_priv_dir), + + AllEvHs = + merge_vals([StartOpts#opts.event_handlers, + SpecStartOpts#opts.event_handlers]), + AllCTHooks = merge_vals( [StartOpts#opts.ct_hooks, SpecStartOpts#opts.ct_hooks]), @@ -354,7 +369,8 @@ script_start2(StartOpts = #opts{vts = undefined, EnableBuiltinHooks, include = AllInclude, multiply_timetraps = MultTT, - scale_timetraps = ScaleTT}} + scale_timetraps = ScaleTT, + create_priv_dir = CreatePrivDir}} end; _ -> {undefined,StartOpts} @@ -567,6 +583,7 @@ script_usage() -> "\n\t[-no_auto_compile]" "\n\t[-multiply_timetraps N]" "\n\t[-scale_timetraps]" + "\n\t[-create_priv_dir auto_per_run | auto_per_tc | manual_per_tc]" "\n\t[-basic_html]\n\n"), io:format("Run tests from command line:\n\n" "\tct_run [-dir TestDir1 TestDir2 .. TestDirN] |" @@ -586,6 +603,7 @@ script_usage() -> "\n\t[-no_auto_compile]" "\n\t[-multiply_timetraps N]" "\n\t[-scale_timetraps]" + "\n\t[-create_priv_dir auto_per_run | auto_per_tc | manual_per_tc]" "\n\t[-basic_html]" "\n\t[-repeat N [-force_stop]] |" "\n\t[-duration HHMMSS [-force_stop]] |" @@ -606,6 +624,7 @@ script_usage() -> "\n\t[-no_auto_compile]" "\n\t[-multiply_timetraps N]" "\n\t[-scale_timetraps]" + "\n\t[-create_priv_dir auto_per_run | auto_per_tc | manual_per_tc]" "\n\t[-basic_html]" "\n\t[-repeat N [-force_stop]] |" "\n\t[-duration HHMMSS [-force_stop]] |" @@ -782,6 +801,9 @@ run_test2(StartOpts) -> MultiplyTT = get_start_opt(multiply_timetraps, value, 1, StartOpts), ScaleTT = get_start_opt(scale_timetraps, value, false, StartOpts), + %% create unique priv dir names + CreatePrivDir = get_start_opt(create_priv_dir, value, StartOpts), + %% auto compile & include files Include = case proplists:get_value(auto_compile, StartOpts) of @@ -842,7 +864,8 @@ run_test2(StartOpts) -> silent_connections = SilentConns, stylesheet = Stylesheet, multiply_timetraps = MultiplyTT, - scale_timetraps = ScaleTT}, + scale_timetraps = ScaleTT, + create_priv_dir = CreatePrivDir}, %% test specification case proplists:get_value(spec, StartOpts) of @@ -889,6 +912,8 @@ run_spec_file(Relaxed, SpecOpts#opts.multiply_timetraps), ScaleTT = choose_val(Opts#opts.scale_timetraps, SpecOpts#opts.scale_timetraps), + CreatePrivDir = choose_val(Opts#opts.create_priv_dir, + SpecOpts#opts.create_priv_dir), AllEvHs = merge_vals([Opts#opts.event_handlers, SpecOpts#opts.event_handlers]), AllInclude = merge_vals([Opts#opts.include, @@ -912,6 +937,7 @@ run_spec_file(Relaxed, testspecs = AbsSpecs, multiply_timetraps = MultTT, scale_timetraps = ScaleTT, + create_priv_dir = CreatePrivDir, ct_hooks = AllCTHooks, enable_builtin_hooks = EnableBuiltinHooks }, @@ -1170,7 +1196,8 @@ get_data_for_node(#testspec{label = Labels, enable_builtin_hooks = EnableBuiltinHooks, include = Incl, multiply_timetraps = MTs, - scale_timetraps = STs}, Node) -> + scale_timetraps = STs, + create_priv_dir = PDs}, Node) -> Label = proplists:get_value(Node, Labels), Profile = proplists:get_value(Node, Profiles), LogDir = case proplists:get_value(Node, LogDirs) of @@ -1184,6 +1211,7 @@ get_data_for_node(#testspec{label = Labels, Cover = proplists:get_value(Node, CoverFs), MT = proplists:get_value(Node, MTs), ST = proplists:get_value(Node, STs), + CreatePrivDir = proplists:get_value(Node, PDs), ConfigFiles = [{?ct_config_txt,F} || {N,F} <- Cfgs, N==Node] ++ [CBF || {N,CBF} <- UsrCfgs, N==Node], EvHandlers = [{H,A} || {N,H,A} <- EvHs, N==Node], @@ -1200,7 +1228,8 @@ get_data_for_node(#testspec{label = Labels, enable_builtin_hooks = EnableBuiltinHooks, include = Include, multiply_timetraps = MT, - scale_timetraps = ST}. + scale_timetraps = ST, + create_priv_dir = CreatePrivDir}. refresh_logs(LogDir) -> {ok,Cwd} = file:get_cwd(), @@ -1384,7 +1413,8 @@ do_run(Tests, Skip, Opts, Args) when is_record(Opts, opts) -> %% which framework it runs under. case os:getenv("TEST_SERVER_FRAMEWORK") of false -> - os:putenv("TEST_SERVER_FRAMEWORK", "ct_framework"); + os:putenv("TEST_SERVER_FRAMEWORK", "ct_framework"), + os:putenv("TEST_SERVER_FRAMEWORK_NAME", "common_test"); "ct_framework" -> ok; Other -> @@ -1746,25 +1776,31 @@ set_group_leader_same_as_shell() -> false end. -check_and_add([{TestDir0,M,_} | Tests], Added) -> +check_and_add([{TestDir0,M,_} | Tests], Added, PA) -> case locate_test_dir(TestDir0, M) of {ok,TestDir} -> case lists:member(TestDir, Added) of true -> - check_and_add(Tests, Added); + check_and_add(Tests, Added, PA); false -> - true = code:add_patha(TestDir), - check_and_add(Tests, [TestDir|Added]) + case lists:member(rm_trailing_slash(TestDir), + code:get_path()) of + false -> + true = code:add_patha(TestDir), + check_and_add(Tests, [TestDir|Added], [TestDir|PA]); + true -> + check_and_add(Tests, [TestDir|Added], PA) + end end; {error,_} -> {error,{invalid_directory,TestDir0}} end; -check_and_add([], _) -> - ok. +check_and_add([], _, PA) -> + {ok,PA}. do_run_test(Tests, Skip, Opts) -> - case check_and_add(Tests, []) of - ok -> + case check_and_add(Tests, [], []) of + {ok,AddedToPath} -> ct_util:set_testdata({stats,{0,0,{0,0}}}), ct_util:set_testdata({cover,undefined}), test_server_ctrl:start_link(local), @@ -1842,6 +1878,8 @@ do_run_test(Tests, Skip, Opts) -> test_server_ctrl:multiply_timetraps(Opts#opts.multiply_timetraps), test_server_ctrl:scale_timetraps(Opts#opts.scale_timetraps), + test_server_ctrl:create_priv_dir(choose_val(Opts#opts.create_priv_dir, + auto_per_run)), ct_event:notify(#event{name=start_info, node=node(), data={NoOfTests,NoOfSuites,NoOfCases}}), @@ -1858,7 +1896,9 @@ do_run_test(Tests, Skip, Opts) -> end, lists:foreach(fun(Suite) -> maybe_cleanup_interpret(Suite, Opts#opts.step) - end, CleanUp); + end, CleanUp), + [code:del_path(Dir) || Dir <- AddedToPath], + ok; Error -> Error end. @@ -2289,7 +2329,7 @@ ct_hooks_args2opts(Args) -> Acc end,[],Args). -ct_hooks_args2opts([CTH,Arg,Prio,"and"| Rest],Acc) -> +ct_hooks_args2opts([CTH,Arg,Prio,"and"| Rest],Acc) when Arg /= "and" -> ct_hooks_args2opts(Rest,[{list_to_atom(CTH), parse_cth_args(Arg), parse_cth_args(Prio)}|Acc]); @@ -2347,31 +2387,38 @@ event_handler_init_args2opts([]) -> %% relative dirs "post run_test erl_args" is not kept! rel_to_abs(CtArgs) -> {PA,PZ} = get_pa_pz(CtArgs, [], []), - io:format(user, "~n", []), [begin - code:del_path(filename:basename(D)), - Abs = filename:absname(D), - code:add_pathz(Abs), - if D /= Abs -> + Dir = rm_trailing_slash(D), + Abs = make_abs(Dir), + if Dir /= Abs -> + code:del_path(Dir), + code:del_path(Abs), io:format(user, "Converting ~p to ~p and re-inserting " "with add_pathz/1~n", - [D, Abs]); + [Dir, Abs]); true -> - ok - end + code:del_path(Dir) + end, + code:add_pathz(Abs) end || D <- PZ], [begin - code:del_path(filename:basename(D)), - Abs = filename:absname(D), - code:add_patha(Abs), - if D /= Abs -> + Dir = rm_trailing_slash(D), + Abs = make_abs(Dir), + if Dir /= Abs -> + code:del_path(Dir), + code:del_path(Abs), io:format(user, "Converting ~p to ~p and re-inserting " "with add_patha/1~n", - [D, Abs]); - true ->ok - end + [Dir, Abs]); + true -> + code:del_path(Dir) + end, + code:add_patha(Abs) end || D <- PA], - io:format(user, "~n", []). + io:format(user, "~n", []). + +rm_trailing_slash(Dir) -> + filename:join(filename:split(Dir)). get_pa_pz([{pa,Dirs} | Args], PA, PZ) -> get_pa_pz(Args, PA ++ Dirs, PZ); @@ -2382,6 +2429,19 @@ get_pa_pz([_ | Args], PA, PZ) -> get_pa_pz([], PA, PZ) -> {PA,PZ}. +make_abs(RelDir) -> + Tokens = filename:split(filename:absname(RelDir)), + filename:join(lists:reverse(make_abs1(Tokens, []))). + +make_abs1([".."|Dirs], [_Dir|Path]) -> + make_abs1(Dirs, Path); +make_abs1(["."|Dirs], Path) -> + make_abs1(Dirs, Path); +make_abs1([Dir|Dirs], Path) -> + make_abs1(Dirs, [Dir|Path]); +make_abs1([], Path) -> + Path. + %% This function translates ct:run_test/1 start options %% to ct_run start arguments (on the init arguments format) - %% this is useful mainly for testing the ct_run start functions. @@ -2419,6 +2479,10 @@ opts2args(EnvStartOpts) -> [{scale_timetraps,[]}]; ({scale_timetraps,false}) -> []; + ({create_priv_dir,auto_per_run}) -> + []; + ({create_priv_dir,PD}) when is_atom(PD) -> + [{create_priv_dir,[atom_to_list(PD)]}]; ({force_stop,true}) -> [{force_stop,[]}]; ({force_stop,false}) -> diff --git a/lib/common_test/src/ct_testspec.erl b/lib/common_test/src/ct_testspec.erl index b68cbd3aa1..5b197c0c81 100644 --- a/lib/common_test/src/ct_testspec.erl +++ b/lib/common_test/src/ct_testspec.erl @@ -568,6 +568,21 @@ add_tests([{scale_timetraps,Node,ST}|Ts],Spec) -> add_tests([{scale_timetraps,ST}|Ts],Spec) -> add_tests([{scale_timetraps,all_nodes,ST}|Ts],Spec); +%% --- create_priv_dir --- +add_tests([{create_priv_dir,all_nodes,PD}|Ts],Spec) -> + Tests = lists:map(fun(N) -> {create_priv_dir,N,PD} end, list_nodes(Spec)), + add_tests(Tests++Ts,Spec); +add_tests([{create_priv_dir,Nodes,PD}|Ts],Spec) when is_list(Nodes) -> + Ts1 = separate(Nodes,create_priv_dir,[PD],Ts,Spec#testspec.nodes), + add_tests(Ts1,Spec); +add_tests([{create_priv_dir,Node,PD}|Ts],Spec) -> + PDs = Spec#testspec.create_priv_dir, + PDs1 = [{ref2node(Node,Spec#testspec.nodes),PD} | + lists:keydelete(ref2node(Node,Spec#testspec.nodes),1,PDs)], + add_tests(Ts,Spec#testspec{create_priv_dir=PDs1}); +add_tests([{create_priv_dir,PD}|Ts],Spec) -> + add_tests([{create_priv_dir,all_nodes,PD}|Ts],Spec); + %% --- config --- add_tests([{config,all_nodes,Files}|Ts],Spec) -> Tests = lists:map(fun(N) -> {config,N,Files} end, list_nodes(Spec)), @@ -1158,7 +1173,8 @@ valid_terms() -> {skip_groups,6}, {skip_groups,7}, {skip_cases,5}, - {skip_cases,6} + {skip_cases,6}, + {create_priv_dir,2} ]. %% this function "guesses" if the user has misspelled a term name diff --git a/lib/common_test/src/ct_util.erl b/lib/common_test/src/ct_util.erl index 3b6ad6f98d..e9bfb2590b 100644 --- a/lib/common_test/src/ct_util.erl +++ b/lib/common_test/src/ct_util.erl @@ -827,15 +827,20 @@ get_profile_data(Profile, Key, StartDir) -> %%%----------------------------------------------------------------- %%% Internal functions call(Msg) -> - MRef = erlang:monitor(process,whereis(ct_util_server)), - Ref = make_ref(), - ct_util_server ! {Msg,{self(),Ref}}, - receive - {Ref, Result} -> - erlang:demonitor(MRef, [flush]), - Result; - {'DOWN',MRef,process,_,Reason} -> - {error,{ct_util_server_down,Reason}} + case whereis(ct_util_server) of + undefined -> + {error,ct_util_server_not_running}; + Pid -> + MRef = erlang:monitor(process, Pid), + Ref = make_ref(), + ct_util_server ! {Msg,{self(),Ref}}, + receive + {Ref, Result} -> + erlang:demonitor(MRef, [flush]), + Result; + {'DOWN',MRef,process,_,Reason} -> + {error,{ct_util_server_down,Reason}} + end end. return({To,Ref},Result) -> diff --git a/lib/common_test/src/ct_util.hrl b/lib/common_test/src/ct_util.hrl index bde832811a..082599a9c6 100644 --- a/lib/common_test/src/ct_util.hrl +++ b/lib/common_test/src/ct_util.hrl @@ -43,9 +43,10 @@ include=[], multiply_timetraps=[], scale_timetraps=[], + create_priv_dir=[], alias=[], tests=[], - merge_tests = true }). + merge_tests=true}). -record(cover, {app=none, level=details, diff --git a/lib/common_test/src/cth_log_redirect.erl b/lib/common_test/src/cth_log_redirect.erl index 14663b7738..ea79251cfc 100644 --- a/lib/common_test/src/cth_log_redirect.erl +++ b/lib/common_test/src/cth_log_redirect.erl @@ -31,22 +31,22 @@ %% Event handler Callbacks -export([init/1, handle_event/2, handle_call/2, handle_info/2, - terminate/2]). + terminate/1]). id(_Opts) -> ?MODULE. init(?MODULE, _Opts) -> error_logger:add_report_handler(?MODULE), - tc_log. + tc_log_async. -post_init_per_group(Group, Config, Result, tc_log) -> +post_init_per_group(Group, Config, Result, tc_log_async) -> case lists:member(parallel,proplists:get_value( tc_group_properties,Config,[])) of true -> {Result, {set_log_func(ct_log),Group}}; false -> - {Result, tc_log} + {Result, tc_log_async} end; post_init_per_group(_Group, _Config, Result, State) -> {Result, State}. @@ -58,14 +58,14 @@ post_end_per_testcase(_TC, _Config, Result, State) -> {Result, State}. pre_end_per_group(Group, Config, {ct_log, Group}) -> - {Config, set_log_func(tc_log)}; + {Config, set_log_func(tc_log_async)}; pre_end_per_group(_Group, Config, State) -> {Config, State}. %% Copied and modified from sasl_report_tty_h.erl init(_Type) -> - {ok, tc_log}. + {ok, tc_log_async}. handle_event({_Type, GL, _Msg}, State) when node(GL) /= node() -> {ok, State}; @@ -101,7 +101,8 @@ handle_call({set_logfunc,NewLogFunc},_) -> {ok, NewLogFunc, NewLogFunc}; handle_call(_Query, _State) -> {error, bad_query}. -terminate(_Reason, _Type) -> +terminate(_State) -> + error_logger:delete_report_handler(?MODULE), []. tag_event(Event) -> diff --git a/lib/common_test/src/vts.erl b/lib/common_test/src/vts.erl index cc8a932887..9dfb0bd6b8 100644 --- a/lib/common_test/src/vts.erl +++ b/lib/common_test/src/vts.erl @@ -766,10 +766,6 @@ report1(tc_done,{_Suite,init_per_group,_},State) -> State; report1(tc_done,{_Suite,end_per_group,_},State) -> State; -report1(tc_done,{_Suite,ct_init_per_group,_},State) -> - State; -report1(tc_done,{_Suite,ct_end_per_group,_},State) -> - State; report1(tc_done,{_Suite,_Case,ok},State) -> State#state{ok=State#state.ok+1}; report1(tc_done,{_Suite,_Case,{failed,_Reason}},State) -> diff --git a/lib/common_test/test/Makefile b/lib/common_test/test/Makefile index 284612b8f7..332c444145 100644 --- a/lib/common_test/test/Makefile +++ b/lib/common_test/test/Makefile @@ -29,6 +29,7 @@ MODULES= \ ct_test_support_eh \ ct_userconfig_callback \ ct_smoke_test_SUITE \ + ct_priv_dir_SUITE \ ct_event_handler_SUITE \ ct_config_info_SUITE \ ct_groups_test_1_SUITE \ diff --git a/lib/common_test/test/ct_error_SUITE.erl b/lib/common_test/test/ct_error_SUITE.erl index 2b3157ff3b..79ed51bc28 100644 --- a/lib/common_test/test/ct_error_SUITE.erl +++ b/lib/common_test/test/ct_error_SUITE.erl @@ -61,7 +61,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [cfg_error, lib_error, no_compile, timetrap_end_conf, timetrap_normal, timetrap_extended, timetrap_parallel, - timetrap_fun]. + timetrap_fun, misc_errors]. groups() -> []. @@ -249,6 +249,24 @@ timetrap_fun(Config) when is_list(Config) -> TestEvents = events_to_check(timetrap_fun), ok = ct_test_support:verify_events(TestEvents, Events, Config). +%%%----------------------------------------------------------------- +%%% +misc_errors(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + Join = fun(D, S) -> filename:join(D, "error/test/"++S) end, + Suites = [Join(DataDir, "misc_error_1_SUITE")], + {Opts,ERPid} = setup([{suite,Suites}], Config), + ok = ct_test_support:run(Opts, Config), + Events = ct_test_support:get_events(ERPid, Config), + + ct_test_support:log_events(misc_errors, + reformat(Events, ?eh), + ?config(priv_dir, Config), + Opts), + + TestEvents = events_to_check(misc_errors), + ok = ct_test_support:verify_events(TestEvents, Events, Config). + %%%----------------------------------------------------------------- %%% HELP FUNCTIONS @@ -682,7 +700,7 @@ test_events(timetrap_end_conf) -> [ {?eh,start_logging,{'DEF','RUNDIR'}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, - {?eh,start_info,{1,1,6}}, + {?eh,start_info,{1,1,9}}, {?eh,tc_start,{timetrap_1_SUITE,init_per_suite}}, {?eh,tc_done,{timetrap_1_SUITE,init_per_suite,ok}}, {?eh,tc_start,{timetrap_1_SUITE,tc1}}, @@ -709,6 +727,18 @@ test_events(timetrap_end_conf) -> {?eh,tc_done, {timetrap_1_SUITE,tc6,{failed,{testcase_aborted,testing_end_conf}}}}, {?eh,test_stats,{0,6,{0,0}}}, + {?eh,tc_start,{timetrap_1_SUITE,tc7}}, + {?eh,tc_done, + {timetrap_1_SUITE,tc7,{failed,{timetrap_timeout,1000}}}}, + {?eh,test_stats,{0,7,{0,0}}}, + {?eh,tc_start,{timetrap_1_SUITE,tc8}}, + {?eh,tc_done, + {timetrap_1_SUITE,tc8,{failed,{timetrap_timeout,1000}}}}, + {?eh,test_stats,{0,8,{0,0}}}, + {?eh,tc_start,{timetrap_1_SUITE,tc9}}, + {?eh,tc_done, + {timetrap_1_SUITE,tc9,{failed,{timetrap_timeout,1000}}}}, + {?eh,test_stats,{0,9,{0,0}}}, {?eh,tc_start,{timetrap_1_SUITE,end_per_suite}}, {?eh,tc_done,{timetrap_1_SUITE,end_per_suite,ok}}, {?eh,test_done,{'DEF','STOP_TIME'}}, @@ -892,4 +922,40 @@ test_events(timetrap_fun) -> {?eh,tc_done,{timetrap_7_SUITE,end_per_suite,ok}}, {?eh,test_done,{'DEF','STOP_TIME'}}, {?eh,stop_logging,[]} + ]; + +test_events(misc_errors) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,start_info,{1,1,7}}, + {?eh,tc_start,{misc_error_1_SUITE,ct_fail_1}}, + {?eh,tc_done,{misc_error_1_SUITE,ct_fail_1, + {failed,{error,{test_case_failed,{error,this_is_expected}}}}}}, + {?eh,test_stats,{0,1,{0,0}}}, + {?eh,tc_start,{misc_error_1_SUITE,ct_fail_2}}, + {?eh,tc_done,{misc_error_1_SUITE,ct_fail_2, + {failed,{error,{test_case_failed,"this_is_expected"}}}}}, + {?eh,test_stats,{0,2,{0,0}}}, + {?eh,tc_start,{misc_error_1_SUITE,ct_fail_3}}, + {?eh,tc_done,{misc_error_1_SUITE,ct_fail_3, + {failed,{error,{test_case_failed,this_is_expected}}}}}, + {?eh,test_stats,{0,3,{0,0}}}, + {?eh,tc_start,{misc_error_1_SUITE,ts_fail_1}}, + {?eh,tc_done,{misc_error_1_SUITE,ts_fail_1, + {failed,{error,{suite_failed,this_is_expected}}}}}, + {?eh,test_stats,{0,4,{0,0}}}, + {?eh,tc_start,{misc_error_1_SUITE,ts_fail_2}}, + {?eh,tc_done,{misc_error_1_SUITE,ts_fail_2, + {failed,{error,{suite_failed,this_is_expected}}}}}, + {?eh,test_stats,{0,5,{0,0}}}, + {?eh,tc_start,{misc_error_1_SUITE,killed_by_signal_1}}, + {?eh,tc_done,{misc_error_1_SUITE,killed_by_signal_1,i_die_now}}, + {?eh,test_stats,{0,6,{0,0}}}, + {?eh,tc_start,{misc_error_1_SUITE,killed_by_signal_2}}, + {?eh,tc_done,{misc_error_1_SUITE,killed_by_signal_2, + {failed,testcase_aborted_or_killed}}}, + {?eh,test_stats,{0,7,{0,0}}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]} ]. diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/misc_error_1_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/misc_error_1_SUITE.erl new file mode 100644 index 0000000000..4e20875505 --- /dev/null +++ b/lib/common_test/test/ct_error_SUITE_data/error/test/misc_error_1_SUITE.erl @@ -0,0 +1,154 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009-2010. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +-module(misc_error_1_SUITE). + +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). + +%%-------------------------------------------------------------------- +%% Function: suite() -> Info +%% Info = [tuple()] +%%-------------------------------------------------------------------- +suite() -> + [{timetrap,{seconds,3}}]. + +%%-------------------------------------------------------------------- +%% Function: init_per_suite(Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_suite(Config0) -> void() | {save_config,Config1} +%% Config0 = Config1 = [tuple()] +%%-------------------------------------------------------------------- +end_per_suite(_Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: init_per_group(GroupName, Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% GroupName = atom() +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%%-------------------------------------------------------------------- +init_per_group(_GroupName, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_group(GroupName, Config0) -> +%% void() | {save_config,Config1} +%% GroupName = atom() +%% Config0 = Config1 = [tuple()] +%%-------------------------------------------------------------------- +end_per_group(_GroupName, _Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: init_per_testcase(TestCase, Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% TestCase = atom() +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%%-------------------------------------------------------------------- +init_per_testcase(_TestCase, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% Function: end_per_testcase(TestCase, Config0) -> +%% void() | {save_config,Config1} +%% TestCase = atom() +%% Config0 = Config1 = [tuple()] +%%-------------------------------------------------------------------- +end_per_testcase(_TestCase, _Config) -> + ok. + +%%-------------------------------------------------------------------- +%% Function: groups() -> [Group] +%% Group = {GroupName,Properties,GroupsAndTestCases} +%% GroupName = atom() +%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}] +%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase] +%% TestCase = atom() +%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}} +%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail | +%% repeat_until_any_ok | repeat_until_any_fail +%% N = integer() | forever +%%-------------------------------------------------------------------- +groups() -> + []. + +%%-------------------------------------------------------------------- +%% Function: all() -> GroupsAndTestCases | {skip,Reason} +%% GroupsAndTestCases = [{group,GroupName} | TestCase] +%% GroupName = atom() +%% TestCase = atom() +%% Reason = term() +%%-------------------------------------------------------------------- +all() -> + [ct_fail_1, ct_fail_2, ct_fail_3, ts_fail_1, ts_fail_2, + killed_by_signal_1, killed_by_signal_2]. + +ct_fail_1(_) -> + ct:fail({error,this_is_expected}), + exit(this_should_not_be_seen), + ok. + +ct_fail_2(_) -> + ct:fail("~w", [this_is_expected]), + exit(this_should_not_be_seen), + ok. + +ct_fail_3(_) -> + fail_me(fun() -> ct:fail(this_is_expected) end), + exit(this_should_not_be_seen), + ok. + +ts_fail_1(_) -> + test_server:fail(this_is_expected), + exit(this_should_not_be_seen), + ok. + +ts_fail_2(_) -> + fail_me(fun() -> test_server:fail(this_is_expected) end), + exit(this_should_not_be_seen), + ok. + +fail_me(Fun) -> + Fun(), + ok. + +killed_by_signal_1(_) -> + spawn_link(fun() -> ct:sleep(100), + exit(i_die_now) + end), + ct:sleep(1000), + exit(this_should_not_be_seen). + +killed_by_signal_2(_) -> + TCPid = self(), + spawn_link(fun() -> ct:sleep(100), + exit(TCPid, kill) + end), + ct:sleep(1000), + exit(this_should_not_be_seen). diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_1_SUITE.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_1_SUITE.erl index cb3109349b..a44ff6d0bc 100644 --- a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_1_SUITE.erl +++ b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_1_SUITE.erl @@ -83,23 +83,11 @@ init_per_testcase(TC, Config) -> ets:insert(?MODULE, {last_case,fail}), init_per_testcase1(TC, Config). -init_per_testcase1(tc1, Config) -> - [{tc,tc1}|Config]; - -init_per_testcase1(tc2, Config) -> - [{tc,tc2}|Config]; - -init_per_testcase1(tc3, Config) -> - [{tc,tc3}|Config]; - init_per_testcase1(tc4, Config) -> [{tc,tc4},{default_timeout,5000}|Config]; -init_per_testcase1(tc5, Config) -> - [{tc,tc5}|Config]; - -init_per_testcase1(tc6, Config) -> - [{tc,tc6}|Config]. +init_per_testcase1(TC, Config) -> + [{tc,TC}|Config]. %%-------------------------------------------------------------------- %% Function: end_per_testcase(TestCase, Config0) -> @@ -145,7 +133,28 @@ end_per_testcase1(tc5, Config) -> end_per_testcase1(tc6, Config) -> ct:pal("end_per_testcase(tc6): ~p", [Config]), tc6 = ?config(tc, Config), - exit(end_per_tc_fail_after_abort). + exit(end_per_tc_fail_after_abort); + +end_per_testcase1(tc7, Config) -> + ct:pal("end_per_testcase(tc7): ~p", [Config]), + tc7 = ?config(tc, Config), + {failed,timetrap_timeout} = ?config(tc_status, Config), + ok; + +end_per_testcase1(tc8, Config) -> + ct:pal("end_per_testcase(tc8): ~p", [Config]), + tc8 = ?config(tc, Config), + {failed,timetrap_timeout} = ?config(tc_status, Config), + ok; + +end_per_testcase1(tc9, Config) -> + ct:pal("end_per_testcase(tc9): ~p", [Config]), + tc9 = ?config(tc, Config), + %% check that it's possible to send and receive synchronously + %% with the group leader process for end_per_testcase + test_server:stop_node(dummy@somehost), + ok. + %%-------------------------------------------------------------------- %% Function: groups() -> [Group] @@ -170,25 +179,46 @@ groups() -> %% Reason = term() %%-------------------------------------------------------------------- all() -> - [tc1, tc2, tc3, tc4, tc5, tc6]. + [tc1, tc2, tc3, tc4, tc5, tc6, tc7, tc8, tc9]. tc1(_) -> - timer:sleep(2000). + timer:sleep(2000), + ok. tc2(_) -> timer:sleep(2000). tc3(_) -> spawn(ct, abort_current_testcase, [testing_end_conf]), - timer:sleep(2000). + timer:sleep(2000), + ok. tc4(_) -> spawn(ct, abort_current_testcase, [testing_end_conf]), - timer:sleep(2000). + timer:sleep(2000), + ok. tc5(_) -> - timer:sleep(2000). + timer:sleep(2000), + ok. tc6(_) -> spawn(ct, abort_current_testcase, [testing_end_conf]), timer:sleep(2000). + +tc7(_) -> + sleep(2000), + ok. + +tc8(_) -> + timetrap_helper:sleep(2000), + ok. + +tc9(_) -> + sleep(2000), + ok. + +%%%----------------------------------------------------------------- +sleep(T) -> + timer:sleep(T), + ok. diff --git a/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_helper.erl b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_helper.erl new file mode 100644 index 0000000000..1389acca11 --- /dev/null +++ b/lib/common_test/test/ct_error_SUITE_data/error/test/timetrap_helper.erl @@ -0,0 +1,7 @@ +-module(timetrap_helper). + +-export([sleep/1]). + +sleep(T) -> + timer:sleep(T), + ok. diff --git a/lib/common_test/test/ct_group_info_SUITE.erl b/lib/common_test/test/ct_group_info_SUITE.erl index 2da8219196..18016c4979 100644 --- a/lib/common_test/test/ct_group_info_SUITE.erl +++ b/lib/common_test/test/ct_group_info_SUITE.erl @@ -440,72 +440,72 @@ test_events(timetrap_all_no_ipg) -> {?eh,tc_done,{group_timetrap_3_SUITE,t1,{failed,{timetrap_timeout,1000}}}}, - [{?eh,tc_start,{ct_framework,{ct_init_per_group,g1,[{suite,group_timetrap_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_init_per_group,g1,[{suite,group_timetrap_3_SUITE}]},ok}}, + [{?eh,tc_start,{ct_framework,{init_per_group,g1,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{init_per_group,g1,[{suite,group_timetrap_3_SUITE}]},ok}}, {?eh,tc_done,{group_timetrap_3_SUITE,t11,{failed,{timetrap_timeout,500}}}}, - {?eh,tc_start,{ct_framework,{ct_end_per_group,g1,[{suite,group_timetrap_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_end_per_group,g1,[{suite,group_timetrap_3_SUITE}]},ok}}], + {?eh,tc_start,{ct_framework,{end_per_group,g1,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{end_per_group,g1,[{suite,group_timetrap_3_SUITE}]},ok}}], - [{?eh,tc_start,{ct_framework,{ct_init_per_group,g2,[{suite,group_timetrap_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_init_per_group,g2,[{suite,group_timetrap_3_SUITE}]},ok}}, + [{?eh,tc_start,{ct_framework,{init_per_group,g2,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{init_per_group,g2,[{suite,group_timetrap_3_SUITE}]},ok}}, {?eh,tc_done,{group_timetrap_3_SUITE,t21,{failed,{timetrap_timeout,1500}}}}, - {?eh,tc_start,{ct_framework,{ct_end_per_group,g2,[{suite,group_timetrap_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_end_per_group,g2,[{suite,group_timetrap_3_SUITE}]},ok}}], + {?eh,tc_start,{ct_framework,{end_per_group,g2,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{end_per_group,g2,[{suite,group_timetrap_3_SUITE}]},ok}}], {?eh,tc_done,{group_timetrap_3_SUITE,t2,{failed,{timetrap_timeout,1000}}}}, - [{?eh,tc_start,{ct_framework,{ct_init_per_group,g3,[{suite,group_timetrap_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_init_per_group,g3,[{suite,group_timetrap_3_SUITE}]},ok}}, - [{?eh,tc_start,{ct_framework,{ct_init_per_group,g4,[{suite,group_timetrap_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_init_per_group,g4,[{suite,group_timetrap_3_SUITE}]},ok}}, + [{?eh,tc_start,{ct_framework,{init_per_group,g3,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{init_per_group,g3,[{suite,group_timetrap_3_SUITE}]},ok}}, + [{?eh,tc_start,{ct_framework,{init_per_group,g4,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{init_per_group,g4,[{suite,group_timetrap_3_SUITE}]},ok}}, {?eh,tc_done,{group_timetrap_3_SUITE,t41,{failed,{timetrap_timeout,250}}}}, - {?eh,tc_start,{ct_framework,{ct_end_per_group,g4,[{suite,group_timetrap_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_end_per_group,g4,[{suite,group_timetrap_3_SUITE}]},ok}}], + {?eh,tc_start,{ct_framework,{end_per_group,g4,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{end_per_group,g4,[{suite,group_timetrap_3_SUITE}]},ok}}], {?eh,tc_done,{group_timetrap_3_SUITE,t31,{failed,{timetrap_timeout,500}}}}, - [{?eh,tc_start,{ct_framework,{ct_init_per_group,g5,[{suite,group_timetrap_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_init_per_group,g5,[{suite,group_timetrap_3_SUITE}]},ok}}, + [{?eh,tc_start,{ct_framework,{init_per_group,g5,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{init_per_group,g5,[{suite,group_timetrap_3_SUITE}]},ok}}, {?eh,tc_done,{group_timetrap_3_SUITE,t51,{failed,{timetrap_timeout,1500}}}}, - {?eh,tc_start,{ct_framework,{ct_end_per_group,g5,[{suite,group_timetrap_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_end_per_group,g5,[{suite,group_timetrap_3_SUITE}]},ok}}], - {?eh,tc_start,{ct_framework,{ct_end_per_group,g3,[{suite,group_timetrap_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_end_per_group,g3,[{suite,group_timetrap_3_SUITE}]},ok}}], + {?eh,tc_start,{ct_framework,{end_per_group,g5,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{end_per_group,g5,[{suite,group_timetrap_3_SUITE}]},ok}}], + {?eh,tc_start,{ct_framework,{end_per_group,g3,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{end_per_group,g3,[{suite,group_timetrap_3_SUITE}]},ok}}], {?eh,tc_done,{group_timetrap_3_SUITE,t3,{failed,{timetrap_timeout,250}}}}, - [{?eh,tc_start,{ct_framework,{ct_init_per_group,g6,[{suite,group_timetrap_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_init_per_group,g6,[{suite,group_timetrap_3_SUITE}]},ok}}, + [{?eh,tc_start,{ct_framework,{init_per_group,g6,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{init_per_group,g6,[{suite,group_timetrap_3_SUITE}]},ok}}, {?eh,tc_done,{group_timetrap_3_SUITE,t61,{failed,{timetrap_timeout,500}}}}, - {?eh,tc_start,{ct_framework,{ct_end_per_group,g6,[{suite,group_timetrap_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_end_per_group,g6,[{suite,group_timetrap_3_SUITE}]},ok}}], + {?eh,tc_start,{ct_framework,{end_per_group,g6,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{end_per_group,g6,[{suite,group_timetrap_3_SUITE}]},ok}}], - [{?eh,tc_start,{ct_framework,{ct_init_per_group,g7,[{suite,group_timetrap_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_init_per_group,g7,[{suite,group_timetrap_3_SUITE}]},ok}}, - [{?eh,tc_start,{ct_framework,{ct_init_per_group,g8,[{suite,group_timetrap_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_init_per_group,g8,[{suite,group_timetrap_3_SUITE}]},ok}}, + [{?eh,tc_start,{ct_framework,{init_per_group,g7,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{init_per_group,g7,[{suite,group_timetrap_3_SUITE}]},ok}}, + [{?eh,tc_start,{ct_framework,{init_per_group,g8,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{init_per_group,g8,[{suite,group_timetrap_3_SUITE}]},ok}}, {?eh,tc_done,{group_timetrap_3_SUITE,t81,{failed,{timetrap_timeout,750}}}}, - {?eh,tc_start,{ct_framework,{ct_end_per_group,g8,[{suite,group_timetrap_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_end_per_group,g8,[{suite,group_timetrap_3_SUITE}]},ok}}], + {?eh,tc_start,{ct_framework,{end_per_group,g8,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{end_per_group,g8,[{suite,group_timetrap_3_SUITE}]},ok}}], {?eh,tc_done,{group_timetrap_3_SUITE,t71,{failed,{timetrap_timeout,500}}}}, - [{?eh,tc_start,{ct_framework,{ct_init_per_group,g9,[{suite,group_timetrap_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_init_per_group,g9,[{suite,group_timetrap_3_SUITE}]},ok}}, + [{?eh,tc_start,{ct_framework,{init_per_group,g9,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{init_per_group,g9,[{suite,group_timetrap_3_SUITE}]},ok}}, {?eh,tc_done,{group_timetrap_3_SUITE,t91,{failed,{timetrap_timeout,250}}}}, - {?eh,tc_start,{ct_framework,{ct_end_per_group,g9,[{suite,group_timetrap_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_end_per_group,g9,[{suite,group_timetrap_3_SUITE}]},ok}}], - {?eh,tc_start,{ct_framework,{ct_end_per_group,g7,[{suite,group_timetrap_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_end_per_group,g7,[{suite,group_timetrap_3_SUITE}]},ok}}], + {?eh,tc_start,{ct_framework,{end_per_group,g9,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{end_per_group,g9,[{suite,group_timetrap_3_SUITE}]},ok}}], + {?eh,tc_start,{ct_framework,{end_per_group,g7,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{end_per_group,g7,[{suite,group_timetrap_3_SUITE}]},ok}}], - [{?eh,tc_start,{ct_framework,{ct_init_per_group,g10,[{suite,group_timetrap_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_init_per_group,g10,[{suite,group_timetrap_3_SUITE}]},ok}}, + [{?eh,tc_start,{ct_framework,{init_per_group,g10,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{init_per_group,g10,[{suite,group_timetrap_3_SUITE}]},ok}}, {?eh,tc_done,{group_timetrap_3_SUITE,t101,{failed,{timetrap_timeout,1000}}}}, - {?eh,tc_start,{ct_framework,{ct_end_per_group,g10,[{suite,group_timetrap_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_end_per_group,g10,[{suite,group_timetrap_3_SUITE}]},ok}}], + {?eh,tc_start,{ct_framework,{end_per_group,g10,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{end_per_group,g10,[{suite,group_timetrap_3_SUITE}]},ok}}], - [{?eh,tc_start,{ct_framework,{ct_init_per_group,g11,[{suite,group_timetrap_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_init_per_group,g11,[{suite,group_timetrap_3_SUITE}]},ok}}, + [{?eh,tc_start,{ct_framework,{init_per_group,g11,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{init_per_group,g11,[{suite,group_timetrap_3_SUITE}]},ok}}, {?eh,tc_done,{group_timetrap_3_SUITE,t111,{failed,{timetrap_timeout,1000}}}}, {?eh,test_stats,{0,14,{0,0}}}, - {?eh,tc_start,{ct_framework,{ct_end_per_group,g11,[{suite,group_timetrap_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_end_per_group,g11,[{suite,group_timetrap_3_SUITE}]},ok}}], + {?eh,tc_start,{ct_framework,{end_per_group,g11,[{suite,group_timetrap_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{end_per_group,g11,[{suite,group_timetrap_3_SUITE}]},ok}}], {?eh,test_done,{'DEF','STOP_TIME'}}, {?eh,stop_logging,[]} @@ -779,78 +779,78 @@ test_events(require_no_ipg) -> {?eh,start_info,{1,1,13}}, {?eh,tc_done,{group_require_3_SUITE,t1,ok}}, - [{?eh,tc_start,{ct_framework,{ct_init_per_group,g1,[{suite,group_require_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_init_per_group,g1,[{suite,group_require_3_SUITE}]},ok}}, + [{?eh,tc_start,{ct_framework,{init_per_group,g1,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{init_per_group,g1,[{suite,group_require_3_SUITE}]},ok}}, {?eh,tc_done,{group_require_3_SUITE,t11,ok}}, - {?eh,tc_start,{ct_framework,{ct_end_per_group,g1,[{suite,group_require_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_end_per_group,g1,[{suite,group_require_3_SUITE}]},ok}}], + {?eh,tc_start,{ct_framework,{end_per_group,g1,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{end_per_group,g1,[{suite,group_require_3_SUITE}]},ok}}], - [{?eh,tc_start,{ct_framework,{ct_init_per_group,g2,[{suite,group_require_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_init_per_group,g2,[{suite,group_require_3_SUITE}]},ok}}, + [{?eh,tc_start,{ct_framework,{init_per_group,g2,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{init_per_group,g2,[{suite,group_require_3_SUITE}]},ok}}, {?eh,tc_done,{group_require_3_SUITE,t21,ok}}, - {?eh,tc_start,{ct_framework,{ct_end_per_group,g2,[{suite,group_require_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_end_per_group,g2,[{suite,group_require_3_SUITE}]},ok}}], + {?eh,tc_start,{ct_framework,{end_per_group,g2,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{end_per_group,g2,[{suite,group_require_3_SUITE}]},ok}}], - [{?eh,tc_start,{ct_framework,{ct_init_per_group,g3,[{suite,group_require_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_init_per_group,g3,[{suite,group_require_3_SUITE}]},ok}}, + [{?eh,tc_start,{ct_framework,{init_per_group,g3,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{init_per_group,g3,[{suite,group_require_3_SUITE}]},ok}}, {?eh,tc_done,{group_require_3_SUITE,t31,ok}}, - {?eh,tc_start,{ct_framework,{ct_end_per_group,g3,[{suite,group_require_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_end_per_group,g3,[{suite,group_require_3_SUITE}]},ok}}], + {?eh,tc_start,{ct_framework,{end_per_group,g3,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{end_per_group,g3,[{suite,group_require_3_SUITE}]},ok}}], - [{?eh,tc_start,{ct_framework,{ct_init_per_group,g4,[{suite,group_require_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_init_per_group,g4,[{suite,group_require_3_SUITE}]}, + [{?eh,tc_start,{ct_framework,{init_per_group,g4,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{init_per_group,g4,[{suite,group_require_3_SUITE}]}, {skipped,{require_failed,{name_in_use,common2_alias,common2}}}}}, {?eh,tc_auto_skip,{group_require_3_SUITE,t41, {require_failed,{name_in_use,common2_alias,common2}}}}, {?eh,test_stats,{4,0,{0,1}}}, - {?eh,tc_auto_skip,{ct_framework,ct_end_per_group, + {?eh,tc_auto_skip,{ct_framework,end_per_group, {require_failed,{name_in_use,common2_alias,common2}}}}], - [{?eh,tc_start,{ct_framework,{ct_init_per_group,g5,[{suite,group_require_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_init_per_group,g5,[{suite,group_require_3_SUITE}]},ok}}, - [{?eh,tc_start,{ct_framework,{ct_init_per_group,g6,[{suite,group_require_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_init_per_group,g6,[{suite,group_require_3_SUITE}]},ok}}, + [{?eh,tc_start,{ct_framework,{init_per_group,g5,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{init_per_group,g5,[{suite,group_require_3_SUITE}]},ok}}, + [{?eh,tc_start,{ct_framework,{init_per_group,g6,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{init_per_group,g6,[{suite,group_require_3_SUITE}]},ok}}, {?eh,tc_done,{group_require_3_SUITE,t61,ok}}, - {?eh,tc_start,{ct_framework,{ct_end_per_group,g6,[{suite,group_require_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_end_per_group,g6,[{suite,group_require_3_SUITE}]},ok}}], + {?eh,tc_start,{ct_framework,{end_per_group,g6,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{end_per_group,g6,[{suite,group_require_3_SUITE}]},ok}}], {?eh,tc_done,{group_require_3_SUITE,t51,ok}}, - [{?eh,tc_start,{ct_framework,{ct_init_per_group,g7,[{suite,group_require_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_init_per_group,g7,[{suite,group_require_3_SUITE}]},ok}}, + [{?eh,tc_start,{ct_framework,{init_per_group,g7,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{init_per_group,g7,[{suite,group_require_3_SUITE}]},ok}}, {?eh,tc_done,{group_require_3_SUITE,t71,ok}}, {?eh,tc_done,{group_require_3_SUITE,t72,ok}}, - {?eh,tc_start,{ct_framework,{ct_end_per_group,g7,[{suite,group_require_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_end_per_group,g7,[{suite,group_require_3_SUITE}]},ok}}], - {?eh,tc_start,{ct_framework,{ct_end_per_group,g5,[{suite,group_require_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_end_per_group,g5,[{suite,group_require_3_SUITE}]},ok}}], + {?eh,tc_start,{ct_framework,{end_per_group,g7,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{end_per_group,g7,[{suite,group_require_3_SUITE}]},ok}}], + {?eh,tc_start,{ct_framework,{end_per_group,g5,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{end_per_group,g5,[{suite,group_require_3_SUITE}]},ok}}], - [{?eh,tc_start,{ct_framework,{ct_init_per_group,g8,[{suite,group_require_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_init_per_group,g8,[{suite,group_require_3_SUITE}]}, + [{?eh,tc_start,{ct_framework,{init_per_group,g8,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{init_per_group,g8,[{suite,group_require_3_SUITE}]}, {skipped,{require_failed,{not_available,non_existing}}}}}, {?eh,tc_auto_skip,{group_require_3_SUITE,t81, {require_failed,{not_available,non_existing}}}}, {?eh,test_stats,{8,0,{0,2}}}, - {?eh,tc_auto_skip,{ct_framework,ct_end_per_group, + {?eh,tc_auto_skip,{ct_framework,end_per_group, {require_failed,{not_available,non_existing}}}}], - [{?eh,tc_start,{ct_framework,{ct_init_per_group,g9,[{suite,group_require_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_init_per_group,g9,[{suite,group_require_3_SUITE}]},ok}}, + [{?eh,tc_start,{ct_framework,{init_per_group,g9,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{init_per_group,g9,[{suite,group_require_3_SUITE}]},ok}}, {?eh,tc_done,{group_require_3_SUITE,t91, {skipped,{require_failed,{not_available,non_existing}}}}}, {?eh,test_stats,{8,0,{0,3}}}, - {?eh,tc_start,{ct_framework,{ct_end_per_group,g9,[{suite,group_require_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_end_per_group,g9,[{suite,group_require_3_SUITE}]},ok}}], + {?eh,tc_start,{ct_framework,{end_per_group,g9,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{end_per_group,g9,[{suite,group_require_3_SUITE}]},ok}}], - [{?eh,tc_start,{ct_framework,{ct_init_per_group,g10,[{suite,group_require_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_init_per_group,g10,[{suite,group_require_3_SUITE}]},ok}}, + [{?eh,tc_start,{ct_framework,{init_per_group,g10,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{init_per_group,g10,[{suite,group_require_3_SUITE}]},ok}}, {?eh,tc_done,{group_require_3_SUITE,t101,ok}}, - {?eh,tc_start,{ct_framework,{ct_end_per_group,g10,[{suite,group_require_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_end_per_group,g10,[{suite,group_require_3_SUITE}]},ok}}], + {?eh,tc_start,{ct_framework,{end_per_group,g10,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{end_per_group,g10,[{suite,group_require_3_SUITE}]},ok}}], - [{?eh,tc_start,{ct_framework,{ct_init_per_group,g11,[{suite,group_require_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_init_per_group,g11,[{suite,group_require_3_SUITE}]},ok}}, + [{?eh,tc_start,{ct_framework,{init_per_group,g11,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{init_per_group,g11,[{suite,group_require_3_SUITE}]},ok}}, {?eh,tc_done,{group_require_3_SUITE,t111,ok}}, {?eh,test_stats,{10,0,{0,3}}}, - {?eh,tc_start,{ct_framework,{ct_end_per_group,g11,[{suite,group_require_3_SUITE}]}}}, - {?eh,tc_done,{ct_framework,{ct_end_per_group,g11,[{suite,group_require_3_SUITE}]},ok}}], + {?eh,tc_start,{ct_framework,{end_per_group,g11,[{suite,group_require_3_SUITE}]}}}, + {?eh,tc_done,{ct_framework,{end_per_group,g11,[{suite,group_require_3_SUITE}]},ok}}], {?eh,test_done,{'DEF','STOP_TIME'}}, {?eh,stop_logging,[]} diff --git a/lib/common_test/test/ct_groups_test_2_SUITE.erl b/lib/common_test/test/ct_groups_test_2_SUITE.erl index 2392b0b850..c3601ba0ce 100644 --- a/lib/common_test/test/ct_groups_test_2_SUITE.erl +++ b/lib/common_test/test/ct_groups_test_2_SUITE.erl @@ -171,16 +171,16 @@ test_events(missing_conf) -> {?eh,start_logging,{'DEF','RUNDIR'}}, {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, {?eh,start_info,{1,1,2}}, - {?eh,tc_start,{ct_framework,{ct_init_per_group,group1,[]}}}, - {?eh,tc_done,{ct_framework,{ct_init_per_group,group1,[]},ok}}, + {?eh,tc_start,{ct_framework,{init_per_group,group1,[]}}}, + {?eh,tc_done,{ct_framework,{init_per_group,group1,[]},ok}}, {?eh,tc_start,{missing_conf_SUITE,tc1}}, {?eh,tc_done,{missing_conf_SUITE,tc1,ok}}, {?eh,test_stats,{1,0,{0,0}}}, {?eh,tc_start,{missing_conf_SUITE,tc2}}, {?eh,tc_done,{missing_conf_SUITE,tc2,ok}}, {?eh,test_stats,{2,0,{0,0}}}, - {?eh,tc_start,{ct_framework,{ct_end_per_group,group1,[]}}}, - {?eh,tc_done,{ct_framework,{ct_end_per_group,group1,[]},ok}}, + {?eh,tc_start,{ct_framework,{end_per_group,group1,[]}}}, + {?eh,tc_done,{ct_framework,{end_per_group,group1,[]},ok}}, {?eh,test_done,{'DEF','STOP_TIME'}}, {?eh,stop_logging,[]} ]; diff --git a/lib/common_test/test/ct_hooks_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE.erl index 2c519f08b5..efe57a7d0b 100644 --- a/lib/common_test/test/ct_hooks_SUITE.erl +++ b/lib/common_test/test/ct_hooks_SUITE.erl @@ -83,10 +83,9 @@ all(suite) -> fail_post_suite_cth, skip_pre_suite_cth, skip_post_suite_cth, recover_post_suite_cth, update_config_cth, state_update_cth, options_cth, same_id_cth, - fail_n_skip_with_minimal_cth, prio_cth + fail_n_skip_with_minimal_cth, prio_cth, no_config ] - ) - . + ). %%-------------------------------------------------------------------- @@ -214,6 +213,10 @@ prio_cth(Config) when is_list(Config) -> [{empty_cth,[1000],1000},{empty_cth,[900],900}, {prio_cth,[1100,100],100},{prio_cth,[1100]}],Config). +no_config(Config) when is_list(Config) -> + do_test(no_config, "ct_no_config_SUITE.erl", + [verify_config_cth],Config). + %%%----------------------------------------------------------------- %%% HELP FUNCTIONS %%%----------------------------------------------------------------- @@ -1078,6 +1081,56 @@ test_events(prio_cth) -> {?eh,test_done,{'DEF','STOP_TIME'}}, {?eh,stop_logging,[]}]; +test_events(no_config) -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,cth,{empty_cth,init,[verify_config_cth,[]]}}, + {?eh,start_info,{1,1,2}}, + {?eh,tc_start,{ct_framework,init_per_suite}}, + {?eh,cth,{empty_cth,pre_init_per_suite, + [ct_no_config_SUITE,'$proplist',[]]}}, + {?eh,cth,{empty_cth,post_init_per_suite, + [ct_no_config_SUITE,'$proplist','$proplist',[]]}}, + {?eh,tc_done,{ct_framework,init_per_suite,ok}}, + {?eh,tc_start,{ct_no_config_SUITE,test_case_1}}, + {?eh,cth,{empty_cth,pre_init_per_testcase, + [test_case_1,'$proplist',[]]}}, + {?eh,cth,{empty_cth,post_end_per_testcase, + [test_case_1,'$proplist',ok,[]]}}, + {?eh,tc_done,{ct_no_config_SUITE,test_case_1,ok}}, + {?eh,test_stats,{1,0,{0,0}}}, + [{?eh,tc_start,{ct_framework,{init_per_group,test_group,'$proplist'}}}, + {?eh,cth,{empty_cth,pre_init_per_group, + [test_group,'$proplist',[]]}}, + {?eh,cth,{empty_cth,post_init_per_group, + [test_group,'$proplist','$proplist',[]]}}, + {?eh,tc_done,{ct_framework, + {init_per_group,test_group,'$proplist'},ok}}, + {?eh,tc_start,{ct_no_config_SUITE,test_case_2}}, + {?eh,cth,{empty_cth,pre_init_per_testcase, + [test_case_2,'$proplist',[]]}}, + {?eh,cth,{empty_cth,post_end_per_testcase, + [test_case_2,'$proplist',ok,[]]}}, + {?eh,tc_done,{ct_no_config_SUITE,test_case_2,ok}}, + {?eh,test_stats,{2,0,{0,0}}}, + {?eh,tc_start,{ct_framework,{end_per_group,test_group,'$proplist'}}}, + {?eh,cth,{empty_cth,pre_end_per_group, + [test_group,'$proplist',[]]}}, + {?eh,cth,{empty_cth,post_end_per_group, + [test_group,'$proplist',ok,[]]}}, + {?eh,tc_done,{ct_framework,{end_per_group,test_group,'$proplist'},ok}}], + {?eh,tc_start,{ct_framework,end_per_suite}}, + {?eh,cth,{empty_cth,pre_end_per_suite, + [ct_no_config_SUITE,'$proplist',[]]}}, + {?eh,cth,{empty_cth,post_end_per_suite, + [ct_no_config_SUITE,'$proplist',ok,[]]}}, + {?eh,tc_done,{ct_framework,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,cth,{empty_cth,terminate,[[]]}}, + {?eh,stop_logging,[]} + ]; + test_events(ok) -> ok. diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_no_config_SUITE.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_no_config_SUITE.erl new file mode 100644 index 0000000000..2ad80aa1e7 --- /dev/null +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/ct_no_config_SUITE.erl @@ -0,0 +1,64 @@ +%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(ct_no_config_SUITE).
+
+%% Note: This directive should only be used in test suites.
+-compile(export_all).
+
+-include("ct.hrl").
+
+%%% This suite is used to verify 2 things:
+%%%
+%%% 1) All hook pre/post functions get called, even if no init/end
+%%% config functions exist in the suite (new from ver 1.6.1, R15B01).
+%%%
+%%% 2) The hook functions can read Config list elements, as well as
+%%% required config variables, even if no init/end config
+%%% functions exist.
+
+suite() ->
+ [{timetrap, {seconds,1}},
+ {ct_hooks, [verify_config_cth]},
+ {require,suite_cfg},
+ {default_config,suite_cfg,?MODULE}].
+
+group(test_group) ->
+ [{require,group_cfg},
+ {default_config,group_cfg,test_group}].
+
+test_case_1() ->
+ [{require,test_case_1_cfg},
+ {default_config,test_case_1_cfg,test_case_1}].
+
+test_case_2() ->
+ [{require,test_case_2_cfg},
+ {default_config,test_case_2_cfg,test_case_2}].
+
+all() ->
+ [test_case_1, {group,test_group}].
+
+groups() ->
+ [{test_group,[],[test_case_2]}].
+
+test_case_1(Config) ->
+ ok.
+
+test_case_2(Config) ->
+ ok.
diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl index 7befcfa57c..2529e806ea 100644 --- a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/empty_cth.erl @@ -1,277 +1,277 @@ -%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
-%%
-%% The contents of this file are subject to the Erlang Public License,
-%% Version 1.1, (the "License"); you may not use this file except in
-%% compliance with the License. You should have received a copy of the
-%% Erlang Public License along with this software. If not, it can be
-%% retrieved online at http://www.erlang.org/.
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
-%% the License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% %CopyrightEnd%
-%%
-
-%%% @doc Common Test Example Suite Callback module.
-%%%
-%%% <p>This module gives an example of a common test CTH (Common Test Hook).
-%%% There are many ways to add a CTH to a test run, you can do it either in
-%%% the command line using -ct_hook, in a test spec using
-%%% {ct_hook,M} or in the suite it self by returning ct_hook
-%%% from either suite/0, init_per_suite/1, init_per_group/2 and
-%%% init_per_testcase/2. The scope of the CTH is determined by where is it
-%%% started. If it is started in the command line or test spec then it will
-%%% be stopped at the end of all tests. If it is started in init_per_suite,
-%%% it will be stopped after end_per_suite and so on. See terminate
-%%% documentation for a table describing the scoping machanics.
-%%%
-%%% All of callbacks except init/1 in a CTH are optional.</p>
-
--module(empty_cth).
-
-%% CT Hooks
--export([id/1]).
--export([init/2]).
-
--export([pre_init_per_suite/3]).
--export([post_init_per_suite/4]).
--export([pre_end_per_suite/3]).
--export([post_end_per_suite/4]).
-
--export([pre_init_per_group/3]).
--export([post_init_per_group/4]).
--export([pre_end_per_group/3]).
--export([post_end_per_group/4]).
-
--export([pre_init_per_testcase/3]).
--export([post_end_per_testcase/4]).
-
--export([on_tc_fail/3]).
--export([on_tc_skip/3]).
-
--export([terminate/1]).
-
--include_lib("common_test/src/ct_util.hrl").
--include_lib("common_test/include/ct_event.hrl").
-
+%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2010-2011. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%%% @doc Common Test Example Suite Callback module. +%%% +%%% <p>This module gives an example of a common test CTH (Common Test Hook). +%%% There are many ways to add a CTH to a test run, you can do it either in +%%% the command line using -ct_hook, in a test spec using +%%% {ct_hook,M} or in the suite it self by returning ct_hook +%%% from either suite/0, init_per_suite/1, init_per_group/2 and +%%% init_per_testcase/2. The scope of the CTH is determined by where is it +%%% started. If it is started in the command line or test spec then it will +%%% be stopped at the end of all tests. If it is started in init_per_suite, +%%% it will be stopped after end_per_suite and so on. See terminate +%%% documentation for a table describing the scoping machanics. +%%% +%%% All of callbacks except init/1 in a CTH are optional.</p> + +-module(empty_cth). + +%% CT Hooks +-export([id/1]). +-export([init/2]). + +-export([pre_init_per_suite/3]). +-export([post_init_per_suite/4]). +-export([pre_end_per_suite/3]). +-export([post_end_per_suite/4]). + +-export([pre_init_per_group/3]). +-export([post_init_per_group/4]). +-export([pre_end_per_group/3]). +-export([post_end_per_group/4]). + +-export([pre_init_per_testcase/3]). +-export([post_end_per_testcase/4]). + +-export([on_tc_fail/3]). +-export([on_tc_skip/3]). + +-export([terminate/1]). + +-include_lib("common_test/src/ct_util.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + -type config() :: proplists:proplist(). --type reason() :: term().
--type skip_or_fail() :: {skip, reason()} |
- {auto_skip, reason()} |
- {fail, reason()} |
- {'EXIT',reason()}.
-
--record(state, { id = ?MODULE :: term()}).
-
-%% @doc Always called before any other callback function. Use this to initiate
-%% any common state. It should return an state for this CTH.
+-type reason() :: term(). +-type skip_or_fail() :: {skip, reason()} | + {auto_skip, reason()} | + {fail, reason()} | + {'EXIT',reason()}. + +-record(state, { id = ?MODULE :: term()}). + +%% @doc Always called before any other callback function. Use this to initiate +%% any common state. It should return an state for this CTH. -spec init(Id :: term(), Opts :: proplists:proplist()) -> - {ok, State :: #state{}}.
-init(Id, Opts) ->
- gen_event:notify(?CT_EVMGR_REF, #event{ name = cth, node = node(),
- data = {?MODULE, init, [Id, Opts]}}),
- {ok,Opts}.
-
-%% @doc The ID is used to uniquly identify an CTH instance, if two CTH's
-%% return the same ID the seconds CTH is ignored. This function should NOT
-%% have any side effects as it might be called multiple times by common test.
+ {ok, State :: #state{}}. +init(Id, Opts) -> + gen_event:notify(?CT_EVMGR_REF, #event{ name = cth, node = node(), + data = {?MODULE, init, [Id, Opts]}}), + {ok,Opts}. + +%% @doc The ID is used to uniquly identify an CTH instance, if two CTH's +%% return the same ID the seconds CTH is ignored. This function should NOT +%% have any side effects as it might be called multiple times by common test. -spec id(Opts :: proplists:proplist()) -> - Id :: term().
-id(Opts) ->
- gen_event:notify(?CT_EVMGR_REF, #event{ name = cth, node = node(),
- data = {?MODULE, id, [Opts]}}),
- now().
-
-%% @doc Called before init_per_suite is called. Note that this callback is
-%% only called if the CTH is added before init_per_suite is run (eg. in a test
-%% specification, suite/0 function etc).
-%% You can change the config in the this function.
--spec pre_init_per_suite(Suite :: atom(),
- Config :: config(),
- State :: #state{}) ->
- {config() | skip_or_fail(), NewState :: #state{}}.
-pre_init_per_suite(Suite,Config,State) ->
- gen_event:notify(
- ?CT_EVMGR_REF, #event{ name = cth, node = node(),
- data = {?MODULE, pre_init_per_suite,
- [Suite,Config,State]}}),
- {Config, State}.
-
-%% @doc Called after init_per_suite.
-%% you can change the return value in this function.
--spec post_init_per_suite(Suite :: atom(),
- Config :: config(),
- Return :: config() | skip_or_fail(),
- State :: #state{}) ->
- {config() | skip_or_fail(), NewState :: #state{}}.
-post_init_per_suite(Suite,Config,Return,State) ->
- gen_event:notify(
- ?CT_EVMGR_REF, #event{ name = cth, node = node(),
- data = {?MODULE, post_init_per_suite,
- [Suite,Config,Return,State]}}),
- {Return, State}.
-
-%% @doc Called before end_per_suite. The config/state can be changed here,
-%% though it will only affect the *end_per_suite function.
--spec pre_end_per_suite(Suite :: atom(),
- Config :: config() | skip_or_fail(),
- State :: #state{}) ->
- {ok | skip_or_fail(), NewState :: #state{}}.
-pre_end_per_suite(Suite,Config,State) ->
- gen_event:notify(
- ?CT_EVMGR_REF, #event{ name = cth, node = node(),
- data = {?MODULE, pre_end_per_suite,
- [Suite,Config,State]}}),
- {Config, State}.
-
-%% @doc Called after end_per_suite. Note that the config cannot be
-%% changed here, only the status of the suite.
--spec post_end_per_suite(Suite :: atom(),
- Config :: config(),
- Return :: term(),
- State :: #state{}) ->
- {ok | skip_or_fail(), NewState :: #state{}}.
-post_end_per_suite(Suite,Config,Return,State) ->
- gen_event:notify(
- ?CT_EVMGR_REF, #event{ name = cth, node = node(),
- data = {?MODULE, post_end_per_suite,
- [Suite,Config,Return,State]}}),
- {Return, State}.
-
-%% @doc Called before each init_per_group.
-%% You can change the config in this function.
--spec pre_init_per_group(Group :: atom(),
- Config :: config(),
- State :: #state{}) ->
- {config() | skip_or_fail(), NewState :: #state{}}.
-pre_init_per_group(Group,Config,State) ->
- gen_event:notify(
- ?CT_EVMGR_REF, #event{ name = cth, node = node(),
- data = {?MODULE, pre_init_per_group,
- [Group,Config,State]}}),
- {Config, State}.
-
-%% @doc Called after each init_per_group.
-%% You can change the return value in this function.
--spec post_init_per_group(Group :: atom(),
- Config :: config(),
- Return :: config() | skip_or_fail(),
- State :: #state{}) ->
- {config() | skip_or_fail(), NewState :: #state{}}.
-post_init_per_group(Group,Config,Return,State) ->
- gen_event:notify(
- ?CT_EVMGR_REF, #event{ name = cth, node = node(),
- data = {?MODULE, post_init_per_group,
- [Group,Config,Return,State]}}),
- {Return, State}.
-
-%% @doc Called after each end_per_group. The config/state can be changed here,
-%% though it will only affect the *end_per_group functions.
--spec pre_end_per_group(Group :: atom(),
- Config :: config() | skip_or_fail(),
- State :: #state{}) ->
- {ok | skip_or_fail(), NewState :: #state{}}.
-pre_end_per_group(Group,Config,State) ->
- gen_event:notify(
- ?CT_EVMGR_REF, #event{ name = cth, node = node(),
- data = {?MODULE, pre_end_per_group,
- [Group,Config,State]}}),
- {Config, State}.
-
-%% @doc Called after each end_per_group. Note that the config cannot be
-%% changed here, only the status of the group.
--spec post_end_per_group(Group :: atom(),
- Config :: config(),
- Return :: term(),
- State :: #state{}) ->
- {ok | skip_or_fail(), NewState :: #state{}}.
-post_end_per_group(Group,Config,Return,State) ->
- gen_event:notify(
- ?CT_EVMGR_REF, #event{ name = cth, node = node(),
- data = {?MODULE, post_end_per_group,
- [Group,Config,Return,State]}}),
- {Return, State}.
-
-%% @doc Called before each test case.
-%% You can change the config in this function.
--spec pre_init_per_testcase(TC :: atom(),
- Config :: config(),
- State :: #state{}) ->
- {config() | skip_or_fail(), NewState :: #state{}}.
-pre_init_per_testcase(TC,Config,State) ->
- gen_event:notify(
- ?CT_EVMGR_REF, #event{ name = cth, node = node(),
- data = {?MODULE, pre_init_per_testcase,
- [TC,Config,State]}}),
- {Config, State}.
-
-%% @doc Called after each test case. Note that the config cannot be
-%% changed here, only the status of the test case.
--spec post_end_per_testcase(TC :: atom(),
- Config :: config(),
- Return :: term(),
- State :: #state{}) ->
- {ok | skip_or_fail(), NewState :: #state{}}.
-post_end_per_testcase(TC,Config,Return,State) ->
- gen_event:notify(
- ?CT_EVMGR_REF, #event{ name = cth, node = node(),
- data = {?MODULE, post_end_per_testcase,
- [TC,Config,Return,State]}}),
- {Return, State}.
-
-%% @doc Called after post_init_per_suite, post_end_per_suite, post_init_per_group,
-%% post_end_per_group and post_end_per_tc if the suite, group or test case failed.
-%% This function should be used for extra cleanup which might be needed.
-%% It is not possible to modify the config or the status of the test run.
--spec on_tc_fail(TC :: init_per_suite | end_per_suite |
- init_per_group | end_per_group | atom(),
- Reason :: term(), State :: #state{}) ->
- NewState :: #state{}.
-on_tc_fail(TC, Reason, State) ->
- gen_event:notify(
- ?CT_EVMGR_REF, #event{ name = cth, node = node(),
- data = {?MODULE, on_tc_fail,
- [TC,Reason,State]}}),
- State.
-
-%% @doc Called when a test case is skipped by either user action
-%% or due to an init function failing. Test case can be
-%% end_per_suite, init_per_group, end_per_group and the actual test cases.
--spec on_tc_skip(TC :: end_per_suite |
- init_per_group | end_per_group | atom(),
- {tc_auto_skip, {failed, {Mod :: atom(), Function :: atom(), Reason :: term()}}} |
- {tc_user_skip, {skipped, Reason :: term()}},
- State :: #state{}) ->
- NewState :: #state{}.
-on_tc_skip(TC, Reason, State) ->
- gen_event:notify(
- ?CT_EVMGR_REF, #event{ name = cth, node = node(),
- data = {?MODULE, on_tc_skip,
- [TC,Reason,State]}}),
- State.
-
-%% @doc Called when the scope of the CTH is done, this depends on
-%% when the CTH was specified. This translation table describes when this
-%% function is called.
-%%
-%% | Started in | terminate called |
-%% |---------------------|-------------------------|
-%% | command_line | after all tests are run |
-%% | test spec | after all tests are run |
-%% | suite/0 | after SUITE is done |
-%% | init_per_suite/1 | after SUITE is done |
-%% | init_per_group/2 | after group is done |
-%% |-----------------------------------------------|
-%%
--spec terminate(State :: #state{}) ->
- term().
-terminate(State) ->
- gen_event:notify(
- ?CT_EVMGR_REF, #event{ name = cth, node = node(),
- data = {?MODULE, terminate, [State]}}),
- ok.
+ Id :: term(). +id(Opts) -> + gen_event:notify(?CT_EVMGR_REF, #event{ name = cth, node = node(), + data = {?MODULE, id, [Opts]}}), + now(). + +%% @doc Called before init_per_suite is called. Note that this callback is +%% only called if the CTH is added before init_per_suite is run (eg. in a test +%% specification, suite/0 function etc). +%% You can change the config in the this function. +-spec pre_init_per_suite(Suite :: atom(), + Config :: config(), + State :: #state{}) -> + {config() | skip_or_fail(), NewState :: #state{}}. +pre_init_per_suite(Suite,Config,State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = cth, node = node(), + data = {?MODULE, pre_init_per_suite, + [Suite,Config,State]}}), + {Config, State}. + +%% @doc Called after init_per_suite. +%% you can change the return value in this function. +-spec post_init_per_suite(Suite :: atom(), + Config :: config(), + Return :: config() | skip_or_fail(), + State :: #state{}) -> + {config() | skip_or_fail(), NewState :: #state{}}. +post_init_per_suite(Suite,Config,Return,State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = cth, node = node(), + data = {?MODULE, post_init_per_suite, + [Suite,Config,Return,State]}}), + {Return, State}. + +%% @doc Called before end_per_suite. The config/state can be changed here, +%% though it will only affect the *end_per_suite function. +-spec pre_end_per_suite(Suite :: atom(), + Config :: config() | skip_or_fail(), + State :: #state{}) -> + {ok | skip_or_fail(), NewState :: #state{}}. +pre_end_per_suite(Suite,Config,State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = cth, node = node(), + data = {?MODULE, pre_end_per_suite, + [Suite,Config,State]}}), + {Config, State}. + +%% @doc Called after end_per_suite. Note that the config cannot be +%% changed here, only the status of the suite. +-spec post_end_per_suite(Suite :: atom(), + Config :: config(), + Return :: term(), + State :: #state{}) -> + {ok | skip_or_fail(), NewState :: #state{}}. +post_end_per_suite(Suite,Config,Return,State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = cth, node = node(), + data = {?MODULE, post_end_per_suite, + [Suite,Config,Return,State]}}), + {Return, State}. + +%% @doc Called before each init_per_group. +%% You can change the config in this function. +-spec pre_init_per_group(Group :: atom(), + Config :: config(), + State :: #state{}) -> + {config() | skip_or_fail(), NewState :: #state{}}. +pre_init_per_group(Group,Config,State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = cth, node = node(), + data = {?MODULE, pre_init_per_group, + [Group,Config,State]}}), + {Config, State}. + +%% @doc Called after each init_per_group. +%% You can change the return value in this function. +-spec post_init_per_group(Group :: atom(), + Config :: config(), + Return :: config() | skip_or_fail(), + State :: #state{}) -> + {config() | skip_or_fail(), NewState :: #state{}}. +post_init_per_group(Group,Config,Return,State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = cth, node = node(), + data = {?MODULE, post_init_per_group, + [Group,Config,Return,State]}}), + {Return, State}. + +%% @doc Called after each end_per_group. The config/state can be changed here, +%% though it will only affect the *end_per_group functions. +-spec pre_end_per_group(Group :: atom(), + Config :: config() | skip_or_fail(), + State :: #state{}) -> + {ok | skip_or_fail(), NewState :: #state{}}. +pre_end_per_group(Group,Config,State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = cth, node = node(), + data = {?MODULE, pre_end_per_group, + [Group,Config,State]}}), + {Config, State}. + +%% @doc Called after each end_per_group. Note that the config cannot be +%% changed here, only the status of the group. +-spec post_end_per_group(Group :: atom(), + Config :: config(), + Return :: term(), + State :: #state{}) -> + {ok | skip_or_fail(), NewState :: #state{}}. +post_end_per_group(Group,Config,Return,State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = cth, node = node(), + data = {?MODULE, post_end_per_group, + [Group,Config,Return,State]}}), + {Return, State}. + +%% @doc Called before each test case. +%% You can change the config in this function. +-spec pre_init_per_testcase(TC :: atom(), + Config :: config(), + State :: #state{}) -> + {config() | skip_or_fail(), NewState :: #state{}}. +pre_init_per_testcase(TC,Config,State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = cth, node = node(), + data = {?MODULE, pre_init_per_testcase, + [TC,Config,State]}}), + {Config, State}. + +%% @doc Called after each test case. Note that the config cannot be +%% changed here, only the status of the test case. +-spec post_end_per_testcase(TC :: atom(), + Config :: config(), + Return :: term(), + State :: #state{}) -> + {ok | skip_or_fail(), NewState :: #state{}}. +post_end_per_testcase(TC,Config,Return,State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = cth, node = node(), + data = {?MODULE, post_end_per_testcase, + [TC,Config,Return,State]}}), + {Return, State}. + +%% @doc Called after post_init_per_suite, post_end_per_suite, post_init_per_group, +%% post_end_per_group and post_end_per_tc if the suite, group or test case failed. +%% This function should be used for extra cleanup which might be needed. +%% It is not possible to modify the config or the status of the test run. +-spec on_tc_fail(TC :: init_per_suite | end_per_suite | + init_per_group | end_per_group | atom(), + Reason :: term(), State :: #state{}) -> + NewState :: #state{}. +on_tc_fail(TC, Reason, State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = cth, node = node(), + data = {?MODULE, on_tc_fail, + [TC,Reason,State]}}), + State. + +%% @doc Called when a test case is skipped by either user action +%% or due to an init function failing. Test case can be +%% end_per_suite, init_per_group, end_per_group and the actual test cases. +-spec on_tc_skip(TC :: end_per_suite | + init_per_group | end_per_group | atom(), + {tc_auto_skip, {failed, {Mod :: atom(), Function :: atom(), Reason :: term()}}} | + {tc_user_skip, {skipped, Reason :: term()}}, + State :: #state{}) -> + NewState :: #state{}. +on_tc_skip(TC, Reason, State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = cth, node = node(), + data = {?MODULE, on_tc_skip, + [TC,Reason,State]}}), + State. + +%% @doc Called when the scope of the CTH is done, this depends on +%% when the CTH was specified. This translation table describes when this +%% function is called. +%% +%% | Started in | terminate called | +%% |---------------------|-------------------------| +%% | command_line | after all tests are run | +%% | test spec | after all tests are run | +%% | suite/0 | after SUITE is done | +%% | init_per_suite/1 | after SUITE is done | +%% | init_per_group/2 | after group is done | +%% |-----------------------------------------------| +%% +-spec terminate(State :: #state{}) -> + term(). +terminate(State) -> + gen_event:notify( + ?CT_EVMGR_REF, #event{ name = cth, node = node(), + data = {?MODULE, terminate, [State]}}), + ok. diff --git a/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/verify_config_cth.erl b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/verify_config_cth.erl new file mode 100644 index 0000000000..99ea261e14 --- /dev/null +++ b/lib/common_test/test/ct_hooks_SUITE_data/cth/tests/verify_config_cth.erl @@ -0,0 +1,130 @@ +%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2010-2011. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+%%
+
+-module(verify_config_cth).
+
+-include_lib("common_test/src/ct_util.hrl").
+
+%% CT Hooks
+-compile(export_all).
+
+-define(val(K, L), proplists:get_value(K, L)).
+
+id(Opts) ->
+ ?MODULE.
+
+init(Id, Opts) ->
+ {ok, State} = empty_cth:init(Id, Opts),
+ {ok, State}.
+
+pre_init_per_suite(Suite, Config, State) ->
+ ct_no_config_SUITE = ct:get_config(suite_cfg),
+ empty_cth:pre_init_per_suite(Suite,
+ [{pre_init_per_suite,true} | Config],
+ State).
+
+post_init_per_suite(Suite,Config,Return,State) ->
+ true = ?val(pre_init_per_suite, Return),
+ ct_no_config_SUITE = ct:get_config(suite_cfg),
+ empty_cth:post_init_per_suite(Suite,
+ Config,
+ [{post_init_per_suite,true} | Return],
+ State).
+
+pre_end_per_suite(Suite,Config,State) ->
+ true = ?val(post_init_per_suite, Config),
+ ct_no_config_SUITE = ct:get_config(suite_cfg),
+ empty_cth:pre_end_per_suite(Suite,
+ [{pre_end_per_suite,true} | Config],
+ State).
+
+post_end_per_suite(Suite,Config,Return,State) ->
+ true = ?val(pre_end_per_suite, Config),
+ ct_no_config_SUITE = ct:get_config(suite_cfg),
+ empty_cth:post_end_per_suite(Suite,Config,Return,State).
+
+pre_init_per_group(Group,Config,State) ->
+ true = ?val(post_init_per_suite, Config),
+ ct_no_config_SUITE = ct:get_config(suite_cfg),
+ test_group = ct:get_config(group_cfg),
+ empty_cth:pre_init_per_group(Group,
+ [{pre_init_per_group,true} | Config],
+ State).
+
+post_init_per_group(Group,Config,Return,State) ->
+ true = ?val(pre_init_per_group, Return),
+ test_group = ct:get_config(group_cfg),
+ empty_cth:post_init_per_group(Group,
+ Config,
+ [{post_init_per_group,true} | Return],
+ State).
+
+pre_end_per_group(Group,Config,State) ->
+ true = ?val(post_init_per_group, Config),
+ ct_no_config_SUITE = ct:get_config(suite_cfg),
+ test_group = ct:get_config(group_cfg),
+ empty_cth:pre_end_per_group(Group,
+ [{pre_end_per_group,true} | Config],
+ State).
+
+post_end_per_group(Group,Config,Return,State) ->
+ true = ?val(pre_end_per_group, Config),
+ ct_no_config_SUITE = ct:get_config(suite_cfg),
+ test_group = ct:get_config(group_cfg),
+ empty_cth:post_end_per_group(Group,Config,Return,State).
+
+pre_init_per_testcase(TC,Config,State) ->
+ true = ?val(post_init_per_suite, Config),
+ case ?val(name, ?val(tc_group_properties, Config)) of
+ undefined ->
+ ok;
+ _ ->
+ true = ?val(post_init_per_group, Config),
+ test_group = ct:get_config(group_cfg)
+ end,
+ ct_no_config_SUITE = ct:get_config(suite_cfg),
+ CfgKey = list_to_atom(atom_to_list(TC) ++ "_cfg"),
+ TC = ct:get_config(CfgKey),
+ empty_cth:pre_init_per_testcase(TC,
+ [{pre_init_per_testcase,true} | Config],
+ State).
+
+post_end_per_testcase(TC,Config,Return,State) ->
+ true = ?val(post_init_per_suite, Config),
+ true = ?val(pre_init_per_testcase, Config),
+ case ?val(name, ?val(tc_group_properties, Config)) of
+ undefined ->
+ ok;
+ _ ->
+ true = ?val(post_init_per_group, Config),
+ test_group = ct:get_config(group_cfg)
+ end,
+ ct_no_config_SUITE = ct:get_config(suite_cfg),
+ CfgKey = list_to_atom(atom_to_list(TC) ++ "_cfg"),
+ TC = ct:get_config(CfgKey),
+ empty_cth:post_end_per_testcase(TC,Config,Return,State).
+
+on_tc_fail(TC, Reason, State) ->
+ empty_cth:on_tc_fail(TC,Reason,State).
+
+on_tc_skip(TC, Reason, State) ->
+ empty_cth:on_tc_skip(TC,Reason,State).
+
+terminate(State) ->
+ empty_cth:terminate(State).
diff --git a/lib/common_test/test/ct_priv_dir_SUITE.erl b/lib/common_test/test/ct_priv_dir_SUITE.erl new file mode 100644 index 0000000000..f6942d59bf --- /dev/null +++ b/lib/common_test/test/ct_priv_dir_SUITE.erl @@ -0,0 +1,277 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009-2011. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%%%------------------------------------------------------------------- +%%% File: ct_priv_dir_SUITE +%%% +%%% Description: +%%% Test that it works to use the create_priv_dir option. +%%% +%%%------------------------------------------------------------------- +-module(ct_priv_dir_SUITE). + +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). +-include_lib("common_test/include/ct_event.hrl"). + +-define(eh, ct_test_support_eh). + +%%-------------------------------------------------------------------- +%% TEST SERVER CALLBACK FUNCTIONS +%%-------------------------------------------------------------------- + +%%-------------------------------------------------------------------- +%% Description: Since Common Test starts another Test Server +%% instance, the tests need to be performed on a separate node (or +%% there will be clashes with logging processes etc). +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + Config1 = ct_test_support:init_per_suite(Config), + Config1. + +end_per_suite(Config) -> + ct_test_support:end_per_suite(Config). + +init_per_testcase(TestCase, Config) -> + ct_test_support:init_per_testcase(TestCase, Config). + +end_per_testcase(TestCase, Config) -> + ct_test_support:end_per_testcase(TestCase, Config). + +suite() -> [{ct_hooks,[ts_install_cth]}]. + +all() -> + [ + default, + auto_per_run, + auto_per_tc, + manual_per_tc, + spec_default, + spec_auto_per_run, + spec_auto_per_run, + spec_manual_per_tc + ]. + +%%-------------------------------------------------------------------- +%% TEST CASES +%%-------------------------------------------------------------------- + +%%%----------------------------------------------------------------- +%%% +default(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + Suite = filename:join(DataDir, "priv_dir_SUITE"), + {Opts,ERPid} = setup([{suite,Suite},{testcase,default}, + {label,default}], Config), + ok = execute(default, Opts, ERPid, Config). + +%%%----------------------------------------------------------------- +%%% +auto_per_run(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + Suite = filename:join(DataDir, "priv_dir_SUITE"), + {Opts,ERPid} = setup([{suite,Suite},{testcase,default}, + {label,auto_per_run}, + {create_priv_dir,auto_per_run}], Config), + ok = execute(auto_per_run, Opts, ERPid, Config). + +%%%----------------------------------------------------------------- +%%% +auto_per_tc(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + Suite = filename:join(DataDir, "priv_dir_SUITE"), + {Opts,ERPid} = setup([{suite,Suite},{testcase,auto_per_tc}, + {label,auto_per_tc}, + {create_priv_dir,auto_per_tc}], Config), + ok = execute(auto_per_tc, Opts, ERPid, Config). + +%%%----------------------------------------------------------------- +%%% +manual_per_tc(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + Suite = filename:join(DataDir, "priv_dir_SUITE"), + {Opts,ERPid} = setup([{suite,Suite},{testcase,manual_per_tc}, + {label,manual_per_tc}, + {create_priv_dir,manual_per_tc}], Config), + ok = execute(manual_per_tc, Opts, ERPid, Config). + +%%%----------------------------------------------------------------- +%%% +spec_default(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + Spec = filename:join(DataDir, "default.spec"), + {Opts,ERPid} = setup([{spec,Spec}, + {label,spec_default}], Config), + ok = execute(spec_default, Opts, ERPid, Config). + +%%%----------------------------------------------------------------- +%%% +spec_auto_per_run(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + Spec = filename:join(DataDir, "auto_per_run.spec"), + {Opts,ERPid} = setup([{spec,Spec}, + {label,spec_auto_per_run}], Config), + ok = execute(spec_auto_per_run, Opts, ERPid, Config). + +%%%----------------------------------------------------------------- +%%% +spec_auto_per_tc(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + Spec = filename:join(DataDir, "auto_per_tc.spec"), + {Opts,ERPid} = setup([{spec,Spec}, + {label,spec_auto_per_tc}], Config), + ok = execute(spec_auto_per_tc, Opts, ERPid, Config). + +%%%----------------------------------------------------------------- +%%% +spec_manual_per_tc(Config) when is_list(Config) -> + DataDir = ?config(data_dir, Config), + Spec = filename:join(DataDir, "manual_per_tc.spec"), + {Opts,ERPid} = setup([{spec,Spec}, + {label,spec_manual_per_tc}], Config), + ok = execute(spec_manual_per_tc, Opts, ERPid, Config). + + +%%%----------------------------------------------------------------- +%%% HELP FUNCTIONS +%%%----------------------------------------------------------------- + +setup(Test, Config) -> + Opts0 = ct_test_support:get_opts(Config), + Level = ?config(trace_level, Config), + EvHArgs = [{cbm,ct_test_support},{trace_level,Level}], + Opts = Opts0 ++ [{event_handler,{?eh,EvHArgs}}|Test], + ERPid = ct_test_support:start_event_receiver(Config), + {Opts,ERPid}. + +execute(Name, Opts, ERPid, Config) -> + ok = ct_test_support:run(Opts, Config), + Events = ct_test_support:get_events(ERPid, Config), + + ct_test_support:log_events(Name, + reformat(Events, ?eh), + ?config(priv_dir, Config), + Opts), + + TestEvents = events_to_check(Name), + ct_test_support:verify_events(TestEvents, Events, Config). + +reformat(Events, EH) -> + ct_test_support:reformat(Events, EH). + +%%%----------------------------------------------------------------- +%%% TEST EVENTS +%%%----------------------------------------------------------------- +events_to_check(Test) -> + %% 2 tests (ct:run_test + script_start) is default + events_to_check(Test, 2). + +events_to_check(_, 0) -> + []; +events_to_check(Test, N) -> + test_events(Test) ++ events_to_check(Test, N-1). + + +test_events(DEF) when DEF == default ; DEF == auto_per_run -> + [ + {?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,start_info,{1,1,1}}, + {?eh,tc_start,{priv_dir_SUITE,init_per_suite}}, + {?eh,tc_done,{priv_dir_SUITE,init_per_suite,ok}}, + {?eh,tc_start,{priv_dir_SUITE,default}}, + {?eh,tc_done,{priv_dir_SUITE,default,ok}}, + {?eh,test_stats,{1,0,{0,0}}}, + {?eh,tc_start,{priv_dir_SUITE,end_per_suite}}, + {?eh,tc_done,{priv_dir_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]}]; + +test_events(auto_per_tc) -> + [{?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,start_info,{1,1,1}}, + {?eh,tc_start,{priv_dir_SUITE,init_per_suite}}, + {?eh,tc_done,{priv_dir_SUITE,init_per_suite,ok}}, + {?eh,tc_start,{priv_dir_SUITE,auto_per_tc}}, + {?eh,tc_done,{priv_dir_SUITE,auto_per_tc,ok}}, + {?eh,test_stats,{1,0,{0,0}}}, + {?eh,tc_start,{priv_dir_SUITE,end_per_suite}}, + {?eh,tc_done,{priv_dir_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]}]; + +test_events(manual_per_tc) -> + [{?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,start_info,{1,1,1}}, + {?eh,tc_start,{priv_dir_SUITE,init_per_suite}}, + {?eh,tc_done,{priv_dir_SUITE,init_per_suite,ok}}, + {?eh,tc_start,{priv_dir_SUITE,manual_per_tc}}, + {?eh,tc_done,{priv_dir_SUITE,manual_per_tc,ok}}, + {?eh,test_stats,{1,0,{0,0}}}, + {?eh,tc_start,{priv_dir_SUITE,end_per_suite}}, + {?eh,tc_done,{priv_dir_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]}]; + +test_events(SPECDEF) when SPECDEF == spec_default ; + SPECDEF == spec_auto_per_run -> + [{?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,start_info,{1,1,1}}, + {?eh,tc_start,{priv_dir_SUITE,init_per_suite}}, + {?eh,tc_done,{priv_dir_SUITE,init_per_suite,ok}}, + {?eh,tc_start,{priv_dir_SUITE,default}}, + {?eh,tc_done,{priv_dir_SUITE,default,ok}}, + {?eh,test_stats,{1,0,{0,0}}}, + {?eh,tc_start,{priv_dir_SUITE,end_per_suite}}, + {?eh,tc_done,{priv_dir_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]}]; + +test_events(spec_auto_per_tc) -> + [{?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,start_info,{1,1,1}}, + {?eh,tc_start,{priv_dir_SUITE,init_per_suite}}, + {?eh,tc_done,{priv_dir_SUITE,init_per_suite,ok}}, + {?eh,tc_start,{priv_dir_SUITE,auto_per_tc}}, + {?eh,tc_done,{priv_dir_SUITE,auto_per_tc,ok}}, + {?eh,test_stats,{1,0,{0,0}}}, + {?eh,tc_start,{priv_dir_SUITE,end_per_suite}}, + {?eh,tc_done,{priv_dir_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]}]; + +test_events(spec_manual_per_tc) -> + [{?eh,start_logging,{'DEF','RUNDIR'}}, + {?eh,test_start,{'DEF',{'START_TIME','LOGDIR'}}}, + {?eh,start_info,{1,1,1}}, + {?eh,tc_start,{priv_dir_SUITE,init_per_suite}}, + {?eh,tc_done,{priv_dir_SUITE,init_per_suite,ok}}, + {?eh,tc_start,{priv_dir_SUITE,manual_per_tc}}, + {?eh,tc_done,{priv_dir_SUITE,manual_per_tc,ok}}, + {?eh,test_stats,{1,0,{0,0}}}, + {?eh,tc_start,{priv_dir_SUITE,end_per_suite}}, + {?eh,tc_done,{priv_dir_SUITE,end_per_suite,ok}}, + {?eh,test_done,{'DEF','STOP_TIME'}}, + {?eh,stop_logging,[]}]. + diff --git a/lib/common_test/test/ct_priv_dir_SUITE_data/auto_per_run.spec b/lib/common_test/test/ct_priv_dir_SUITE_data/auto_per_run.spec new file mode 100644 index 0000000000..4dde0ed1f4 --- /dev/null +++ b/lib/common_test/test/ct_priv_dir_SUITE_data/auto_per_run.spec @@ -0,0 +1,5 @@ +{create_priv_dir, auto_per_run}. + +{alias, curr, "./"}. + +{cases, curr, priv_dir_SUITE, default}.
\ No newline at end of file diff --git a/lib/common_test/test/ct_priv_dir_SUITE_data/auto_per_tc.spec b/lib/common_test/test/ct_priv_dir_SUITE_data/auto_per_tc.spec new file mode 100644 index 0000000000..c265500865 --- /dev/null +++ b/lib/common_test/test/ct_priv_dir_SUITE_data/auto_per_tc.spec @@ -0,0 +1,5 @@ +{create_priv_dir, auto_per_tc}. + +{alias, curr, "./"}. + +{cases, curr, priv_dir_SUITE, auto_per_tc}.
\ No newline at end of file diff --git a/lib/common_test/test/ct_priv_dir_SUITE_data/default.spec b/lib/common_test/test/ct_priv_dir_SUITE_data/default.spec new file mode 100644 index 0000000000..2f053e792f --- /dev/null +++ b/lib/common_test/test/ct_priv_dir_SUITE_data/default.spec @@ -0,0 +1,3 @@ +{alias, curr, "./"}. + +{cases, curr, priv_dir_SUITE, default}.
\ No newline at end of file diff --git a/lib/common_test/test/ct_priv_dir_SUITE_data/manual_per_tc.spec b/lib/common_test/test/ct_priv_dir_SUITE_data/manual_per_tc.spec new file mode 100644 index 0000000000..4f98734d5f --- /dev/null +++ b/lib/common_test/test/ct_priv_dir_SUITE_data/manual_per_tc.spec @@ -0,0 +1,5 @@ +{create_priv_dir, manual_per_tc}. + +{alias, curr, "./"}. + +{cases, curr, priv_dir_SUITE, manual_per_tc}.
\ No newline at end of file diff --git a/lib/common_test/test/ct_priv_dir_SUITE_data/priv_dir_SUITE.erl b/lib/common_test/test/ct_priv_dir_SUITE_data/priv_dir_SUITE.erl new file mode 100644 index 0000000000..423cb2999b --- /dev/null +++ b/lib/common_test/test/ct_priv_dir_SUITE_data/priv_dir_SUITE.erl @@ -0,0 +1,127 @@ +%%%------------------------------------------------------------------- +%%% @author Peter Andersson <[email protected]> +%%% @copyright (C) 2012, Peter Andersson +%%% @doc +%%% +%%% @end +%%% Created : 23 Jan 2012 by Peter Andersson <[email protected]> +%%%------------------------------------------------------------------- +-module(priv_dir_SUITE). + +-compile(export_all). + +-include_lib("common_test/include/ct.hrl"). + +%%-------------------------------------------------------------------- +%% @spec suite() -> Info +%% Info = [tuple()] +%% @end +%%-------------------------------------------------------------------- +suite() -> + [{timetrap,{seconds,30}}]. + +%%-------------------------------------------------------------------- +%% @spec init_per_suite(Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%% @end +%%-------------------------------------------------------------------- +init_per_suite(Config) -> + Config. + +%%-------------------------------------------------------------------- +%% @spec end_per_suite(Config0) -> void() | {save_config,Config1} +%% Config0 = Config1 = [tuple()] +%% @end +%%-------------------------------------------------------------------- +end_per_suite(_Config) -> + ok. + +%%-------------------------------------------------------------------- +%% @spec init_per_group(GroupName, Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% GroupName = atom() +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%% @end +%%-------------------------------------------------------------------- +init_per_group(_GroupName, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% @spec end_per_group(GroupName, Config0) -> +%% void() | {save_config,Config1} +%% GroupName = atom() +%% Config0 = Config1 = [tuple()] +%% @end +%%-------------------------------------------------------------------- +end_per_group(_GroupName, _Config) -> + ok. + +%%-------------------------------------------------------------------- +%% @spec init_per_testcase(TestCase, Config0) -> +%% Config1 | {skip,Reason} | {skip_and_save,Reason,Config1} +%% TestCase = atom() +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%% @end +%%-------------------------------------------------------------------- +init_per_testcase(_TestCase, Config) -> + Config. + +%%-------------------------------------------------------------------- +%% @spec end_per_testcase(TestCase, Config0) -> +%% void() | {save_config,Config1} | {fail,Reason} +%% TestCase = atom() +%% Config0 = Config1 = [tuple()] +%% Reason = term() +%% @end +%%-------------------------------------------------------------------- +end_per_testcase(_TestCase, _Config) -> + ok. + +%%-------------------------------------------------------------------- +%% @spec groups() -> [Group] +%% Group = {GroupName,Properties,GroupsAndTestCases} +%% GroupName = atom() +%% Properties = [parallel | sequence | Shuffle | {RepeatType,N}] +%% GroupsAndTestCases = [Group | {group,GroupName} | TestCase] +%% TestCase = atom() +%% Shuffle = shuffle | {shuffle,{integer(),integer(),integer()}} +%% RepeatType = repeat | repeat_until_all_ok | repeat_until_all_fail | +%% repeat_until_any_ok | repeat_until_any_fail +%% N = integer() | forever +%% @end +%%-------------------------------------------------------------------- +groups() -> + []. + +%%-------------------------------------------------------------------- +%% @spec all() -> GroupsAndTestCases | {skip,Reason} +%% GroupsAndTestCases = [{group,GroupName} | TestCase] +%% GroupName = atom() +%% TestCase = atom() +%% Reason = term() +%% @end +%%-------------------------------------------------------------------- +all() -> + []. + +default(Config) -> + PrivDir = proplists:get_value(priv_dir, Config), + "log_private" = filename:basename(PrivDir), + {ok,_} = file:list_dir(PrivDir). + +auto_per_tc(Config) -> + PrivDir = proplists:get_value(priv_dir, Config), + ["log_private",_] = string:tokens(filename:basename(PrivDir), "."), + {ok,_} = file:list_dir(PrivDir). + +manual_per_tc(Config) -> + PrivDir = proplists:get_value(priv_dir, Config), + ["log_private",_] = string:tokens(filename:basename(PrivDir), "."), + {error,_} = file:list_dir(PrivDir), + ok = ct:make_priv_dir(), + {ok,_} = file:list_dir(PrivDir). + diff --git a/lib/common_test/test/ct_test_server_if_1_SUITE.erl b/lib/common_test/test/ct_test_server_if_1_SUITE.erl index efc0309781..8825d84884 100644 --- a/lib/common_test/test/ct_test_server_if_1_SUITE.erl +++ b/lib/common_test/test/ct_test_server_if_1_SUITE.erl @@ -242,25 +242,28 @@ test_events(ts_if_1) -> {?eh,tc_auto_skip,{ts_if_5_SUITE,end_per_suite, {require_failed_in_suite0,{not_available,undef_variable}}}}, - {?eh,tc_start,{ts_if_6_SUITE,tc1}}, - {?eh,tc_done,{ts_if_6_SUITE,tc1,{failed,{error,{suite0_failed,{exited,suite0_byebye}}}}}}, - {?eh,test_stats,{3,5,{6,8}}}, + {?eh,tc_start,{ct_framework,init_per_suite}}, + {?eh,tc_done,{ct_framework,init_per_suite, + {failed,{error,{suite0_failed,{exited,suite0_byebye}}}}}}, + {?eh,tc_auto_skip,{ts_if_6_SUITE,tc1, + {failed,{error,{suite0_failed,{exited,suite0_byebye}}}}}}, + {?eh,test_stats,{3,5,{5,9}}}, {?eh,tc_start,{ts_if_7_SUITE,tc1}}, {?eh,tc_done,{ts_if_7_SUITE,tc1,ok}}, - {?eh,test_stats,{4,5,{6,8}}}, + {?eh,test_stats,{4,5,{5,9}}}, {?eh,tc_start,{ts_if_8_SUITE,tc1}}, {?eh,tc_done,{ts_if_8_SUITE,tc1,{failed,{error,failed_on_purpose}}}}, - {?eh,test_stats,{4,6,{6,8}}}, + {?eh,test_stats,{4,6,{5,9}}}, {?eh,tc_user_skip,{skipped_by_spec_1_SUITE,all,"should be skipped"}}, - {?eh,test_stats,{4,6,{7,8}}}, + {?eh,test_stats,{4,6,{6,9}}}, {?eh,tc_start,{skipped_by_spec_2_SUITE,init_per_suite}}, {?eh,tc_done,{skipped_by_spec_2_SUITE,init_per_suite,ok}}, {?eh,tc_user_skip,{skipped_by_spec_2_SUITE,tc1,"should be skipped"}}, - {?eh,test_stats,{4,6,{8,8}}}, + {?eh,test_stats,{4,6,{7,9}}}, {?eh,tc_start,{skipped_by_spec_2_SUITE,end_per_suite}}, {?eh,tc_done,{skipped_by_spec_2_SUITE,end_per_suite,ok}}, diff --git a/lib/common_test/vsn.mk b/lib/common_test/vsn.mk index 2f43c1bc17..b94f7f7593 100644 --- a/lib/common_test/vsn.mk +++ b/lib/common_test/vsn.mk @@ -1 +1 @@ -COMMON_TEST_VSN = 1.6 +COMMON_TEST_VSN = 1.6.1 diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl index 5b155398dc..4e67639805 100644 --- a/lib/compiler/src/sys_core_fold.erl +++ b/lib/compiler/src/sys_core_fold.erl @@ -150,14 +150,26 @@ guard(Expr, Sub) -> opt_guard_try(#c_seq{arg=Arg,body=Body0}=Seq) -> Body = opt_guard_try(Body0), case {Arg,Body} of - {#c_call{},#c_literal{val=false}} -> - %% We have sequence consisting of a call (evaluted - %% for a possible exception only), followed by 'false'. - %% Since the sequence is inside a try block that will + {#c_call{module=#c_literal{val=Mod}, + name=#c_literal{val=Name}, + args=Args},#c_literal{val=false}} -> + %% We have sequence consisting of a call (evaluated + %% for a possible exception and/or side effect only), + %% followed by 'false'. + %% Since the sequence is inside a try block that will %% default to 'false' if any exception occurs, not %% evalutating the call will not change the behaviour - %% of the guard. - Body; + %% provided that the call has no side effects. + case erl_bifs:is_pure(Mod, Name, length(Args)) of + false -> + %% Not a pure BIF (meaning that this is not + %% a guard and that we must keep the call). + Seq#c_seq{body=Body}; + true -> + %% The BIF has no side effects, so it can + %% be safely removed. + Body + end; {_,_} -> Seq#c_seq{body=Body} end; @@ -1747,36 +1759,26 @@ opt_bool_clauses([_|_], _, _) -> %% end. NewVar -> %% erlang:error(badarg) %% end. -%% -%% We add the extra match-all clause at the end only if Expr is -%% not guaranteed to evaluate to a boolean. opt_bool_not(#c_case{arg=Arg,clauses=Cs0}=Case0) -> case Arg of #c_call{anno=Anno,module=#c_literal{val=erlang}, name=#c_literal{val='not'}, args=[Expr]} -> - Cs = opt_bool_not(Anno, Expr, Cs0), + Cs = [opt_bool_not_invert(C) || C <- Cs0] ++ + [#c_clause{anno=[compiler_generated], + pats=[#c_var{name=cor_variable}], + guard=#c_literal{val=true}, + body=#c_call{anno=Anno, + module=#c_literal{val=erlang}, + name=#c_literal{val=error}, + args=[#c_literal{val=badarg}]}}], Case = Case0#c_case{arg=Expr,clauses=Cs}, opt_bool_not(Case); _ -> opt_bool_case_redundant(Case0) end. -opt_bool_not(Anno, Expr, Cs) -> - Tail = case is_bool_expr(Expr) of - false -> - [#c_clause{anno=[compiler_generated], - pats=[#c_var{name=cor_variable}], - guard=#c_literal{val=true}, - body=#c_call{anno=Anno, - module=#c_literal{val=erlang}, - name=#c_literal{val=error}, - args=[#c_literal{val=badarg}]}}]; - true -> [] - end, - [opt_bool_not_invert(C) || C <- Cs] ++ Tail. - opt_bool_not_invert(#c_clause{pats=[#c_literal{val=Bool}]}=C) -> C#c_clause{pats=[#c_literal{val=not Bool}]}. @@ -2065,32 +2067,7 @@ opt_case_in_let_2(V, Arg0, (_) -> false end, Es), %Only variables in tuple false = core_lib:is_var_used(V, B), %Built tuple must not be used. Arg1 = tuple_to_values(Arg0, length(Es)), %Might fail. - #c_let{vars=Es,arg=Arg1,body=B}; -opt_case_in_let_2(_, Arg, Cs) -> - %% simplify_bool_case(Case0) -> Case - %% Remove unecessary cases like - %% - %% case BoolExpr of - %% true -> true; - %% false -> false; - %% .... - %% end - %% - %% where BoolExpr is an expression that can only return true - %% or false (or throw an exception). - - true = is_bool_case(Cs) andalso is_bool_expr(Arg), - Arg. - -is_bool_case([A,B|_]) -> - (is_bool_clause(true, A) andalso is_bool_clause(false, B)) - orelse (is_bool_clause(false, A) andalso is_bool_clause(true, B)). - -is_bool_clause(Bool, #c_clause{pats=[#c_literal{val=Bool}], - guard=#c_literal{val=true}, - body=#c_literal{val=Bool}}) -> - true; -is_bool_clause(_, _) -> false. + #c_let{vars=Es,arg=Arg1,body=B}. %% is_simple_case_arg(Expr) -> true|false %% Determine whether the Expr is simple enough to be worth @@ -2612,14 +2589,14 @@ bsm_maybe_ctx_to_binary(V, B) -> body=B} end. -previous_ctx_to_binary(V, #c_seq{arg=#c_primop{name=Name,args=As}}) -> - case {Name,As} of - {#c_literal{val=bs_context_to_binary},[#c_var{name=V}]} -> +previous_ctx_to_binary(V, Core) -> + case Core of + #c_seq{arg=#c_primop{name=#c_literal{val=bs_context_to_binary}, + args=[#c_var{name=V}]}} -> true; - {_,_} -> + _ -> false - end; -previous_ctx_to_binary(_, _) -> false. + end. %% bsm_leftmost(Cs) -> none | ArgumentNumber %% Find the leftmost argument that does binary matching. Return @@ -2764,22 +2741,20 @@ add_bin_opt_info(Core, Term) -> end. add_warning(Core, Term) -> - Anno = core_lib:get_anno(Core), - case lists:member(compiler_generated, Anno) of - true -> ok; + case is_compiler_generated(Core) of + true -> + ok; false -> - case get_line(Anno) of - Line when Line >= 0 -> %Must be positive. - File = get_file(Anno), - Key = {?MODULE,warnings}, - case get(Key) of - [{File,[{Line,?MODULE,Term}]}|_] -> - ok; %We already have + Anno = core_lib:get_anno(Core), + Line = get_line(Anno), + File = get_file(Anno), + Key = {?MODULE,warnings}, + case get(Key) of + [{File,[{Line,?MODULE,Term}]}|_] -> + ok; %We already have %an identical warning. - Ws -> - put(Key, [{File,[{Line,?MODULE,Term}]}|Ws]) - end; - _ -> ok %Compiler-generated code. + Ws -> + put(Key, [{File,[{Line,?MODULE,Term}]}|Ws]) end end. @@ -2793,14 +2768,7 @@ get_file([]) -> "no_file". % should not happen is_compiler_generated(Core) -> Anno = core_lib:get_anno(Core), - case lists:member(compiler_generated, Anno) of - true -> true; - false -> - case get_line(Anno) of - Line when Line >= 0 -> false; - _ -> true - end - end. + member(compiler_generated, Anno). get_warnings() -> ordsets:from_list((erase({?MODULE,warnings}))). diff --git a/lib/compiler/src/v3_codegen.erl b/lib/compiler/src/v3_codegen.erl index 6623485609..36d35a8122 100644 --- a/lib/compiler/src/v3_codegen.erl +++ b/lib/compiler/src/v3_codegen.erl @@ -1423,20 +1423,7 @@ set_cg([{var,R}], Con, Le, Vdb, Bef, St) -> Other -> [{move,Other,Ret}] end, - {Ais,clear_dead(Int, Le#l.i, Vdb),St}; -set_cg([], {binary,Segs}, Le, Vdb, Bef, St) -> - Fail = {f,St#cg.bfail}, - Target = find_scratch_reg(Bef#sr.reg), - Temp = find_scratch_reg(put_reg(Target, Bef#sr.reg)), - PutCode = cg_bin_put(Segs, Fail, Bef), - MaxRegs = max_reg(Bef#sr.reg), - Code = cg_binary(PutCode, Target, Temp, Fail, MaxRegs, Le#l.a), - Aft = clear_dead(Bef, Le#l.i, Vdb), - {Code,Aft,St}; -set_cg([], _, Le, Vdb, Bef, St) -> - %% This should have been stripped by compiler, just cleanup. - {[],clear_dead(Bef, Le#l.i, Vdb), St}. - + {Ais,clear_dead(Int, Le#l.i, Vdb),St}. %%% %%% Code generation for constructing binaries. @@ -2067,7 +2054,7 @@ line_1(_, 0) -> %% Missing line number or line number 0. {line,[]}; line_1(Name, Line) -> - {line,[{location,Name,abs(Line)}]}. + {line,[{location,Name,Line}]}. find_loc([Line|T], File, _) when is_integer(Line) -> find_loc(T, File, Line); diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl index 6885405ae0..ad0a8a7654 100644 --- a/lib/compiler/src/v3_core.erl +++ b/lib/compiler/src/v3_core.erl @@ -2085,7 +2085,12 @@ bitstr_vars(Segs, Vs) -> lineno_anno(L, St) -> {line, Line} = erl_parse:get_attribute(L, line), - [Line] ++ St#core.file. + if + Line < 0 -> + [-Line] ++ St#core.file ++ [compiler_generated]; + true -> + [Line] ++ St#core.file + end. get_ianno(Ce) -> case get_anno(Ce) of diff --git a/lib/compiler/src/v3_kernel.erl b/lib/compiler/src/v3_kernel.erl index f2eaa37617..abe94ad991 100644 --- a/lib/compiler/src/v3_kernel.erl +++ b/lib/compiler/src/v3_kernel.erl @@ -88,8 +88,6 @@ -include("core_parse.hrl"). -include("v3_kernel.hrl"). --define(EXPENSIVE_BINARY_LIMIT, 256). - %% These are not defined in v3_kernel.hrl. get_kanno(Kthing) -> element(2, Kthing). set_kanno(Kthing, Anno) -> setelement(2, Kthing, Anno). @@ -120,7 +118,6 @@ copy_anno(Kdst, Ksrc) -> funs=[], %Fun functions free=[], %Free variables ws=[] :: [warning()], %Warnings. - lit, %Constant pool for literals. guard_refc=0}). %> 0 means in guard -spec module(cerl:c_module(), [compile:option()]) -> @@ -129,7 +126,7 @@ copy_anno(Kdst, Ksrc) -> module(#c_module{anno=A,name=M,exports=Es,attrs=As,defs=Fs}, _Options) -> Kas = attributes(As), Kes = map(fun (#c_var{name={_,_}=Fname}) -> Fname end, Es), - St0 = #kern{lit=dict:new()}, + St0 = #kern{}, {Kfs,St} = mapfoldl(fun function/2, St0, Fs), {ok,#k_mdef{anno=A,name=M#c_literal.val,exports=Kes,attributes=Kas, body=Kfs ++ St#kern.funs},lists:sort(St#kern.ws)}. @@ -250,26 +247,20 @@ expr(#c_var{anno=A,name={_Name,Arity}}=Fname, Sub, St) -> expr(Fun, Sub, St); expr(#c_var{anno=A,name=V}, Sub, St) -> {#k_var{anno=A,name=get_vsub(V, Sub)},[],St}; -expr(#c_literal{}=Lit, Sub, St) -> - Core = handle_literal(Lit), - expr(Core, Sub, St); -expr(#k_literal{val=Val0}=Klit, _Sub, #kern{lit=Literals0}=St) -> - %% Share identical literals to save some space and time during compilation. - case dict:find(Val0, Literals0) of - {ok,Val} -> - {Klit#k_literal{val=Val},[],St}; - error -> - Literals = dict:store(Val0, Val0, Literals0), - {Klit,[],St#kern{lit=Literals}} - end; -expr(#k_nil{}=V, _Sub, St) -> - {V,[],St}; -expr(#k_int{}=V, _Sub, St) -> - {V,[],St}; -expr(#k_float{}=V, _Sub, St) -> - {V,[],St}; -expr(#k_atom{}=V, _Sub, St) -> - {V,[],St}; +expr(#c_literal{anno=A,val=V}, _Sub, St) -> + Klit = case V of + [] -> + #k_nil{anno=A}; + V when is_integer(V) -> + #k_int{anno=A,val=V}; + V when is_float(V) -> + #k_float{anno=A,val=V}; + V when is_atom(V) -> + #k_atom{anno=A,val=V}; + _ -> + #k_literal{anno=A,val=V} + end, + {Klit,[],St}; expr(#c_cons{anno=A,hd=Ch,tl=Ct}, Sub, St0) -> %% Do cons in two steps, first the expressions left to right, then %% any remaining literals right to left. @@ -610,7 +601,6 @@ is_atomic(#k_int{}) -> true; is_atomic(#k_float{}) -> true; is_atomic(#k_atom{}) -> true; %%is_atomic(#k_char{}) -> true; %No characters -%%is_atomic(#k_string{}) -> true; is_atomic(#k_nil{}) -> true; is_atomic(#k_var{}) -> true; is_atomic(_) -> false. @@ -919,9 +909,8 @@ match_guard_1([#iclause{anno=A,osub=Osub,guard=G,body=B}|Cs0], Def0, St0) -> true -> %% The true clause body becomes the default. {Kb,Pb,St1} = body(B, Osub, St0), - Line = get_line(A), - St2 = maybe_add_warning(Cs0, Line, St1), - St = maybe_add_warning(Def0, Line, St2), + St2 = maybe_add_warning(Cs0, A, St1), + St = maybe_add_warning(Def0, A, St2), {[],pre_seq(Pb, Kb),St}; false -> {Kg,St1} = guard(G, Osub, St0), @@ -932,15 +921,18 @@ match_guard_1([#iclause{anno=A,osub=Osub,guard=G,body=B}|Cs0], Def0, St0) -> end; match_guard_1([], Def, St) -> {[],Def,St}. -maybe_add_warning([C|_], Line, St) -> - maybe_add_warning(C, Line, St); -maybe_add_warning([], _Line, St) -> St; -maybe_add_warning(fail, _Line, St) -> St; -maybe_add_warning(Ke, MatchLine, St) -> - case get_kanno(Ke) of - [compiler_generated|_] -> St; - Anno -> +maybe_add_warning([C|_], MatchAnno, St) -> + maybe_add_warning(C, MatchAnno, St); +maybe_add_warning([], _MatchAnno, St) -> St; +maybe_add_warning(fail, _MatchAnno, St) -> St; +maybe_add_warning(Ke, MatchAnno, St) -> + case is_compiler_generated(Ke) of + true -> + St; + false -> + Anno = get_kanno(Ke), Line = get_line(Anno), + MatchLine = get_line(MatchAnno), Warn = case MatchLine of none -> nomatch_shadow; _ -> {nomatch_shadow,MatchLine} @@ -1122,7 +1114,6 @@ select_bin_int([#iclause{pats=[#k_bin_seg{anno=A,type=integer, end, select_assert_match_possible(Bits, Val, Fl), P = #k_bin_int{anno=A,size=Sz,unit=U,flags=Fl,val=Val,next=N}, - select_assert_match_possible(Bits, Val, Fl), case member(native, Fl) of true -> throw(not_possible); false -> ok @@ -1264,8 +1255,6 @@ match_clause([U|Us], [C|_]=Cs0, Def, St0) -> sub_size_var(#k_bin_seg{size=#k_var{name=Name}=Kvar}=BinSeg, [#iclause{isub=Sub}|_]) -> BinSeg#k_bin_seg{size=Kvar#k_var{name=get_vsub(Name, Sub)}}; -sub_size_var(#k_bin_int{size=#k_var{name=Name}=Kvar}=BinSeg, [#iclause{isub=Sub}|_]) -> - BinSeg#k_bin_int{size=Kvar#k_var{name=get_vsub(Name, Sub)}}; sub_size_var(K, _) -> K. get_con([C|_]) -> arg_arg(clause_arg(C)). %Get the constructor @@ -1383,7 +1372,6 @@ arg_con(Arg) -> #k_tuple{} -> k_tuple; #k_binary{} -> k_binary; #k_bin_end{} -> k_bin_end; - #k_bin_int{} -> k_bin_int; #k_bin_seg{} -> k_bin_seg; #k_var{} -> k_var end. @@ -1394,15 +1382,9 @@ arg_val(Arg) -> #k_int{val=I} -> I; #k_float{val=F} -> F; #k_atom{val=A} -> A; - #k_nil{} -> 0; - #k_cons{} -> 2; #k_tuple{es=Es} -> length(Es); #k_bin_seg{size=S,unit=U,type=T,flags=Fs} -> - {set_kanno(S, []),U,T,Fs}; - #k_bin_int{} -> - 0; - #k_bin_end{} -> 0; - #k_binary{} -> 0 + {set_kanno(S, []),U,T,Fs} end. %% ubody_used_vars(Expr, State) -> [UsedVar] @@ -1432,14 +1414,12 @@ ubody(#ivalues{anno=A,args=As}, return, St) -> {#k_return{anno=#k{us=Au,ns=[],a=A},args=As},Au,St}; ubody(#ivalues{anno=A,args=As}, {break,_Vbs}, St) -> Au = lit_list_vars(As), - if St#kern.guard_refc > 0 -> + case is_in_guard(St) of + true -> {#k_guard_break{anno=#k{us=Au,ns=[],a=A},args=As},Au,St}; - true -> + false -> {#k_break{anno=#k{us=Au,ns=[],a=A},args=As},Au,St} end; -ubody(#ivalues{anno=A,args=As}, {guard_break,_Vbs}, St) -> - Au = lit_list_vars(As), - {#k_guard_break{anno=#k{us=Au,ns=[],a=A},args=As},Au,St}; ubody(E, return, St0) -> %% Enterable expressions need no trailing return. case is_enter_expr(E) of @@ -1456,12 +1436,7 @@ ubody(E, {break,_Rs} = Break, St0) -> false -> {Ea,Pa,St1} = force_atomic(E, St0), ubody(pre_seq(Pa, #ivalues{args=[Ea]}), Break, St1) - end; -ubody(E, {guard_break,_Rs} = GuardBreak, St0) -> - %%ok = io:fwrite("ubody ~w:~p~n", [?LINE,{E,Br}]), - %% Exiting expressions need no trailing break. - {Ea,Pa,St1} = force_atomic(E, St0), - ubody(pre_seq(Pa, #ivalues{args=[Ea]}), GuardBreak, St1). + end. iletrec_funs(#iletrec{defs=Fs}, St0) -> %% Use union of all free variables. @@ -1513,64 +1488,21 @@ is_enter_expr(#k_receive{}) -> true; is_enter_expr(#k_receive_next{}) -> true; is_enter_expr(_) -> false. -%% uguard(Expr, State) -> {Expr,[UsedVar],State}. -%% Tag the guard sequence with its used variables. - -uguard(#k_try{anno=A,arg=B0,vars=[#k_var{name=X}],body=#k_var{name=X}, - handler=#k_atom{val=false}}=Try, St0) -> - {B1,Bu,St1} = uguard(B0, St0), - {Try#k_try{anno=#k{us=Bu,ns=[],a=A},arg=B1},Bu,St1}; -uguard(T, St) -> - %%ok = io:fwrite("~w: ~p~n", [?LINE,T]), - uguard_test(T, St). - -%% uguard_test(Expr, State) -> {Test,[UsedVar],State}. -%% At this stage tests are just expressions which don't return any -%% values. - -uguard_test(T, St) -> uguard_expr(T, [], St). +%% uexpr(Expr, Break, State) -> {Expr,[UsedVar],State}. +%% Tag an expression with its used variables. +%% Break = return | {break,[RetVar]}. -uguard_expr(#iset{anno=A,vars=Vs,arg=E0,body=B0}, Rs, St0) -> - Ns = lit_list_vars(Vs), - {E1,Eu,St1} = uguard_expr(E0, Vs, St0), - {B1,Bu,St2} = uguard_expr(B0, Rs, St1), - Used = union(Eu, subtract(Bu, Ns)), - {#k_seq{anno=#k{us=Used,ns=Ns,a=A},arg=E1,body=B1},Used,St2}; -uguard_expr(#k_try{anno=A,arg=B0,vars=[#k_var{name=X}],body=#k_var{name=X}, - handler=#k_atom{val=false}}=Try, Rs, St0) -> - {B1,Bu,St1} = uguard_expr(B0, Rs, St0), - {Try#k_try{anno=#k{us=Bu,ns=lit_list_vars(Rs),a=A},arg=B1,ret=Rs}, - Bu,St1}; -uguard_expr(#k_test{anno=A,op=Op,args=As}=Test, Rs, St) -> +uexpr(#k_test{anno=A,op=Op,args=As}=Test, {break,Rs}, St) -> [] = Rs, %Sanity check Used = union(op_vars(Op), lit_list_vars(As)), {Test#k_test{anno=#k{us=Used,ns=lit_list_vars(Rs),a=A}}, Used,St}; -uguard_expr(#k_bif{anno=A,op=Op,args=As}=Bif, Rs, St) -> - Used = union(op_vars(Op), lit_list_vars(As)), - {Bif#k_bif{anno=#k{us=Used,ns=lit_list_vars(Rs),a=A},ret=Rs}, - Used,St}; -uguard_expr(#ivalues{anno=A,args=As}, Rs, St) -> - Sets = foldr2(fun (V, Arg, Rhs) -> - #iset{anno=A,vars=[V],arg=Arg,body=Rhs} - end, #k_atom{val=true}, Rs, As), - uguard_expr(Sets, [], St); -uguard_expr(#k_match{anno=A,vars=Vs,body=B0}, Rs, St0) -> - %% Experimental support for andalso/orelse in guards. - Br = {guard_break,Rs}, - {B1,Bu,St1} = umatch(B0, Br, St0), - {#k_guard_match{anno=#k{us=Bu,ns=lit_list_vars(Rs),a=A}, - vars=Vs,body=B1,ret=Rs},Bu,St1}; -uguard_expr(Lit, Rs, St) -> - %% Transform literals to puts here. - Used = lit_vars(Lit), - {#k_put{anno=#k{us=Used,ns=lit_list_vars(Rs),a=get_kanno(Lit)}, - arg=Lit,ret=Rs},Used,St}. - -%% uexpr(Expr, Break, State) -> {Expr,[UsedVar],State}. -%% Tag an expression with its used variables. -%% Break = return | {break,[RetVar]}. - +uexpr(#iset{anno=A,vars=Vs,arg=E0,body=B0}, {break,_}=Br, St0) -> + Ns = lit_list_vars(Vs), + {E1,Eu,St1} = uexpr(E0, {break,Vs}, St0), + {B1,Bu,St2} = uexpr(B0, Br, St1), + Used = union(Eu, subtract(Bu, Ns)), + {#k_seq{anno=#k{us=Used,ns=Ns,a=A},arg=E1,body=B1},Used,St2}; uexpr(#k_call{anno=A,op=#k_local{name=F,arity=Ar}=Op,args=As0}=Call, Br, St) -> Free = get_free(F, Ar, St), As1 = As0 ++ Free, %Add free variables LAST! @@ -1602,10 +1534,11 @@ uexpr(#k_match{anno=A,vars=Vs0,body=B0}, Br, St0) -> Vs = handle_reuse_annos(Vs0, St0), Rs = break_rets(Br), {B1,Bu,St1} = umatch(B0, Br, St0), - if St0#kern.guard_refc > 0 -> + case is_in_guard(St1) of + true -> {#k_guard_match{anno=#k{us=Bu,ns=lit_list_vars(Rs),a=A}, vars=Vs,body=B1,ret=Rs},Bu,St1}; - true -> + false -> {#k_match{anno=#k{us=Bu,ns=lit_list_vars(Rs),a=A}, vars=Vs,body=B1,ret=Rs},Bu,St1} end; @@ -1622,24 +1555,27 @@ uexpr(#k_receive_accept{anno=A}, _, St) -> {#k_receive_accept{anno=#k{us=[],ns=[],a=A}},[],St}; uexpr(#k_receive_next{anno=A}, _, St) -> {#k_receive_next{anno=#k{us=[],ns=[],a=A}},[],St}; -uexpr(#k_try{anno=A,arg=A0,vars=Vs,body=B0,evars=Evs,handler=H0}, - {break,Rs0}, St0) -> - {Avs,St1} = new_vars(length(Vs), St0), %Need dummy names here - {A1,Au,St2} = ubody(A0, {break,Avs}, St1), %Must break to clean up here! - {B1,Bu,St3} = ubody(B0, {break,Rs0}, St2), - {H1,Hu,St4} = ubody(H0, {break,Rs0}, St3), - %% Guarantee ONE return variable. - NumNew = if - Rs0 =:= [] -> 1; - true -> 0 - end, - {Ns,St5} = new_vars(NumNew, St4), - Rs1 = Rs0 ++ Ns, - Used = union([Au,subtract(Bu, lit_list_vars(Vs)), - subtract(Hu, lit_list_vars(Evs))]), - {#k_try{anno=#k{us=Used,ns=lit_list_vars(Rs1),a=A}, - arg=A1,vars=Vs,body=B1,evars=Evs,handler=H1,ret=Rs1}, - Used,St5}; +uexpr(#k_try{anno=A,arg=A0,vars=Vs,body=B0,evars=Evs,handler=H0}=Try, + {break,Rs0}=Br, St0) -> + case is_in_guard(St0) of + true -> + {[#k_var{name=X}],#k_var{name=X}} = {Vs,B0}, %Assertion. + #k_atom{val=false} = H0, %Assertion. + {A1,Bu,St1} = uexpr(A0, Br, St0), + {Try#k_try{anno=#k{us=Bu,ns=lit_list_vars(Rs0),a=A}, + arg=A1,ret=Rs0},Bu,St1}; + false -> + {Avs,St1} = new_vars(length(Vs), St0), + {A1,Au,St2} = ubody(A0, {break,Avs}, St1), + {B1,Bu,St3} = ubody(B0, Br, St2), + {H1,Hu,St4} = ubody(H0, Br, St3), + {Rs1,St5} = ensure_return_vars(Rs0, St4), + Used = union([Au,subtract(Bu, lit_list_vars(Vs)), + subtract(Hu, lit_list_vars(Evs))]), + {#k_try{anno=#k{us=Used,ns=lit_list_vars(Rs1),a=A}, + arg=A1,vars=Vs,body=B1,evars=Evs,handler=H1,ret=Rs1}, + Used,St5} + end; uexpr(#k_try{anno=A,arg=A0,vars=Vs,body=B0,evars=Evs,handler=H0}, return, St0) -> {Avs,St1} = new_vars(length(Vs), St0), %Need dummy names here @@ -1685,12 +1621,13 @@ uexpr(#ifun{anno=A,vars=Vs,body=B0}, {break,Rs}, St0) -> #k_int{val=Index},#k_int{val=Uniq}|Fvs], ret=Rs}, Free,add_local_function(Fun, St)}; -uexpr(Lit, {break,Rs}, St) -> +uexpr(Lit, {break,Rs0}, St0) -> %% Transform literals to puts here. %%ok = io:fwrite("uexpr ~w:~p~n", [?LINE,Lit]), Used = lit_vars(Lit), + {Rs,St1} = ensure_return_vars(Rs0, St0), {#k_put{anno=#k{us=Used,ns=lit_list_vars(Rs),a=get_kanno(Lit)}, - arg=Lit,ret=Rs},Used,St}. + arg=Lit,ret=Rs},Used,St1}. add_local_function(_, #kern{funs=ignore}=St) -> St; add_local_function(F, #kern{funs=Funs}=St) -> St#kern{funs=[F|Funs]}. @@ -1747,6 +1684,11 @@ bif_returns(#k_internal{name=N,arity=Ar}, Rs, St0) -> {Ns,St1} = new_vars(bif_vals(N, Ar) - length(Rs), St0), {Rs ++ Ns,St1}. +%% ensure_return_vars([Ret], State) -> {[Ret],State}. + +ensure_return_vars([], St) -> new_vars(1, St); +ensure_return_vars([_]=Rs, St) -> {Rs,St}. + %% umatch(Match, Break, State) -> {Match,[UsedVar],State}. %% Tag a match expression with its used variables. @@ -1779,7 +1721,8 @@ umatch(#k_guard{anno=A,clauses=Gs0}, Br, St0) -> {#k_guard{anno=#k{us=Gus,ns=[],a=A},clauses=Gs1},Gus,St1}; umatch(#k_guard_clause{anno=A,guard=G0,body=B0}, Br, St0) -> %%ok = io:fwrite("~w: ~p~n", [?LINE,G0]), - {G1,Gu,St1} = uguard(G0, St0#kern{guard_refc=St0#kern.guard_refc+1}), + {G1,Gu,St1} = uexpr(G0, {break,[]}, + St0#kern{guard_refc=St0#kern.guard_refc+1}), %%ok = io:fwrite("~w: ~p~n", [?LINE,G1]), {B1,Bu,St2} = umatch(B0, Br, St1#kern{guard_refc=St1#kern.guard_refc-1}), Used = union(Gu, Bu), @@ -1827,7 +1770,6 @@ lit_list_vars(Ps) -> pat_vars(#k_var{name=N}) -> {[],[N]}; %%pat_vars(#k_char{}) -> {[],[]}; -%%pat_vars(#k_string{}) -> {[],[]}; pat_vars(#k_literal{}) -> {[],[]}; pat_vars(#k_int{}) -> {[],[]}; pat_vars(#k_float{}) -> {[],[]}; @@ -1854,34 +1796,6 @@ pat_list_vars(Ps) -> {union(Used0, Used),union(New0, New)} end, {[],[]}, Ps). -%% handle_literal(Literal, Anno) -> Kernel -%% Examine the literal. Complex (heap-based) literals such as lists, -%% tuples, and binaries should be kept as literals and put into the constant pool. -%% -%% (If necessary, this function could be extended to go through the literal -%% and convert huge binary literals to bit syntax expressions. We don't do that -%% because v3_core does not produce huge binary literals, and the optimizations in -%% sys_core_fold don't do much optimizations of binaries. IF THAT CHANGE IS MADE, -%% ALSO CHANGE sys_core_dsetel.) - -handle_literal(#c_literal{anno=A,val=V}) -> - case V of - [_|_] -> - #k_literal{anno=A,val=V}; - [] -> - #k_nil{anno=A}; - V when is_tuple(V) -> - #k_literal{anno=A,val=V}; - V when is_bitstring(V) -> - #k_literal{anno=A,val=V}; - V when is_integer(V) -> - #k_int{anno=A,val=V}; - V when is_float(V) -> - #k_float{anno=A,val=V}; - V when is_atom(V) -> - #k_atom{anno=A,val=V} - end. - make_list(Es) -> foldr(fun(E, Acc) -> #c_cons{hd=E,tl=Acc} @@ -1893,6 +1807,11 @@ integers(N, M) when N =< M -> [N|integers(N + 1, M)]; integers(_, _) -> []. +%% is_in_guard(State) -> true|false. + +is_in_guard(#kern{guard_refc=Refc}) -> + Refc > 0. + %%% %%% Handling of errors and warnings. %%% @@ -1913,7 +1832,10 @@ format_error(bad_call) -> add_warning(none, Term, Anno, #kern{ws=Ws}=St) -> File = get_file(Anno), St#kern{ws=[{File,[{?MODULE,Term}]}|Ws]}; -add_warning(Line, Term, Anno, #kern{ws=Ws}=St) when Line >= 0 -> +add_warning(Line, Term, Anno, #kern{ws=Ws}=St) -> File = get_file(Anno), - St#kern{ws=[{File,[{Line,?MODULE,Term}]}|Ws]}; -add_warning(_, _, _, St) -> St. + St#kern{ws=[{File,[{Line,?MODULE,Term}]}|Ws]}. + +is_compiler_generated(Ke) -> + Anno = get_kanno(Ke), + member(compiler_generated, Anno). diff --git a/lib/compiler/src/v3_kernel.hrl b/lib/compiler/src/v3_kernel.hrl index 37f2fdcf7e..17904c37da 100644 --- a/lib/compiler/src/v3_kernel.hrl +++ b/lib/compiler/src/v3_kernel.hrl @@ -35,7 +35,6 @@ -record(k_int, {anno=[],val}). -record(k_float, {anno=[],val}). -record(k_atom, {anno=[],val}). --record(k_string, {anno=[],val}). -record(k_nil, {anno=[]}). -record(k_tuple, {anno=[],es}). diff --git a/lib/compiler/src/v3_life.erl b/lib/compiler/src/v3_life.erl index 93f8034230..22f3e3c2d2 100644 --- a/lib/compiler/src/v3_life.erl +++ b/lib/compiler/src/v3_life.erl @@ -112,53 +112,14 @@ guard(#k_try{anno=A,arg=Ts,vars=[#k_var{name=X}],body=#k_var{name=X}, %% Lock variables that are alive before try and used afterwards. %% Don't lock variables that are only used inside the try expression. Pdb0 = vdb_sub(I, I+1, Vdb), - {T,MaxI,Pdb1} = guard_body(Ts, I+1, Pdb0), + {T,MaxI,Pdb1} = body(Ts, I+1, Pdb0), Pdb2 = use_vars(A#k.ns, MaxI+1, Pdb1), %Save "return" values - #l{ke={protected,T,var_list(Rs)},i=I,a=A#k.a,vdb=Pdb2}; -guard(#k_seq{}=G, I, Vdb0) -> - {Es,_,Vdb1} = guard_body(G, I, Vdb0), - #l{ke={block,Es},i=I,vdb=Vdb1,a=[]}; -guard(G, I, Vdb) -> guard_expr(G, I, Vdb). - -%% guard_body(Kbody, I, Vdb) -> {[Expr],MaxI,Vdb}. - -guard_body(#k_seq{arg=Ke,body=Kb}, I, Vdb0) -> - A = get_kanno(Ke), - Vdb1 = use_vars(A#k.us, I, new_vars(A#k.ns, I, Vdb0)), - {Es,MaxI,Vdb2} = guard_body(Kb, I+1, Vdb1), - E = guard_expr(Ke, I, Vdb2), - {[E|Es],MaxI,Vdb2}; -guard_body(Ke, I, Vdb0) -> - A = get_kanno(Ke), - Vdb1 = use_vars(A#k.us, I, new_vars(A#k.ns, I, Vdb0)), - E = guard_expr(Ke, I, Vdb1), - {[E],I,Vdb1}. - -%% guard_expr(Call, I, Vdb) -> Expr - -guard_expr(#k_test{anno=A,op=Op,args=As}, I, _Vdb) -> - #l{ke={test,test_op(Op),atomic_list(As)},i=I,a=A#k.a}; -guard_expr(#k_bif{anno=A,op=Op,args=As,ret=Rs}, I, _Vdb) -> - Name = bif_op(Op), - Ar = length(As), - case is_gc_bif(Name, Ar) of - false -> - #l{ke={bif,Name,atomic_list(As),var_list(Rs)},i=I,a=A#k.a}; - true -> - #l{ke={gc_bif,Name,atomic_list(As),var_list(Rs)},i=I,a=A#k.a} - end; -guard_expr(#k_put{anno=A,arg=Arg,ret=Rs}, I, _Vdb) -> - #l{ke={set,var_list(Rs),literal(Arg, [])},i=I,a=A#k.a}; -guard_expr(#k_guard_match{anno=A,body=Kb,ret=Rs}, I, Vdb) -> - %% Support for andalso/orelse in guards. - %% Work out imported variables which need to be locked. - Mdb = vdb_sub(I, I+1, Vdb), - M = match(Kb, A#k.us, I+1, [], Mdb), - #l{ke={guard_match,M,var_list(Rs)},i=I,vdb=use_vars(A#k.us, I+1, Mdb),a=A#k.a}; -guard_expr(G, I, Vdb) -> guard(G, I, Vdb). + #l{ke={protected,T,var_list(Rs)},i=I,a=A#k.a,vdb=Pdb2}. %% expr(Kexpr, I, Vdb) -> Expr. +expr(#k_test{anno=A,op=Op,args=As}, I, _Vdb) -> + #l{ke={test,test_op(Op),atomic_list(As)},i=I,a=A#k.a}; expr(#k_call{anno=A,op=Op,args=As,ret=Rs}, I, _Vdb) -> #l{ke={call,call_op(Op),atomic_list(As),var_list(Rs)},i=I,a=A#k.a}; expr(#k_enter{anno=A,op=Op,args=As}, I, _Vdb) -> @@ -176,25 +137,11 @@ expr(#k_guard_match{anno=A,body=Kb,ret=Rs}, I, Vdb) -> Mdb = vdb_sub(I, I+1, Vdb), M = match(Kb, A#k.us, I+1, [], Mdb), #l{ke={guard_match,M,var_list(Rs)},i=I,vdb=use_vars(A#k.us, I+1, Mdb),a=A#k.a}; -expr(#k_try{anno=A,arg=Ka,vars=Vs,body=Kb,evars=Evs,handler=Kh,ret=Rs}, I, Vdb) -> - %% Lock variables that are alive before the catch and used afterwards. - %% Don't lock variables that are only used inside the try. - Tdb0 = vdb_sub(I, I+1, Vdb), - %% This is the tricky bit. Lock variables in Arg that are used in - %% the body and handler. Add try tag 'variable'. - Ab = get_kanno(Kb), - Ah = get_kanno(Kh), - Tdb1 = use_vars(Ab#k.us, I+3, use_vars(Ah#k.us, I+3, Tdb0)), - Tdb2 = vdb_sub(I, I+2, Tdb1), - Vnames = fun (Kvar) -> Kvar#k_var.name end, %Get the variable names - {Aes,_,Adb} = body(Ka, I+2, add_var({catch_tag,I+1}, I+1, locked, Tdb2)), - {Bes,_,Bdb} = body(Kb, I+4, new_vars(map(Vnames, Vs), I+3, Tdb2)), - {Hes,_,Hdb} = body(Kh, I+4, new_vars(map(Vnames, Evs), I+3, Tdb2)), - #l{ke={'try',#l{ke={block,Aes},i=I+1,vdb=Adb,a=[]}, - var_list(Vs),#l{ke={block,Bes},i=I+3,vdb=Bdb,a=[]}, - var_list(Evs),#l{ke={block,Hes},i=I+3,vdb=Hdb,a=[]}, - var_list(Rs)}, - i=I,vdb=Tdb1,a=A#k.a}; +expr(#k_try{}=Try, I, Vdb) -> + case is_in_guard() of + false -> body_try(Try, I, Vdb); + true -> guard(Try, I, Vdb) + end; expr(#k_try_enter{anno=A,arg=Ka,vars=Vs,body=Kb,evars=Evs,handler=Kh}, I, Vdb) -> %% Lock variables that are alive before the catch and used afterwards. %% Don't lock variables that are only used inside the try. @@ -243,6 +190,27 @@ expr(#k_guard_break{anno=A,args=As}, I, Vdb) -> expr(#k_return{anno=A,args=As}, I, _Vdb) -> #l{ke={return,atomic_list(As)},i=I,a=A#k.a}. +body_try(#k_try{anno=A,arg=Ka,vars=Vs,body=Kb,evars=Evs,handler=Kh,ret=Rs}, + I, Vdb) -> + %% Lock variables that are alive before the catch and used afterwards. + %% Don't lock variables that are only used inside the try. + Tdb0 = vdb_sub(I, I+1, Vdb), + %% This is the tricky bit. Lock variables in Arg that are used in + %% the body and handler. Add try tag 'variable'. + Ab = get_kanno(Kb), + Ah = get_kanno(Kh), + Tdb1 = use_vars(Ab#k.us, I+3, use_vars(Ah#k.us, I+3, Tdb0)), + Tdb2 = vdb_sub(I, I+2, Tdb1), + Vnames = fun (Kvar) -> Kvar#k_var.name end, %Get the variable names + {Aes,_,Adb} = body(Ka, I+2, add_var({catch_tag,I+1}, I+1, locked, Tdb2)), + {Bes,_,Bdb} = body(Kb, I+4, new_vars(map(Vnames, Vs), I+3, Tdb2)), + {Hes,_,Hdb} = body(Kh, I+4, new_vars(map(Vnames, Evs), I+3, Tdb2)), + #l{ke={'try',#l{ke={block,Aes},i=I+1,vdb=Adb,a=[]}, + var_list(Vs),#l{ke={block,Bes},i=I+3,vdb=Bdb,a=[]}, + var_list(Evs),#l{ke={block,Hes},i=I+3,vdb=Hdb,a=[]}, + var_list(Rs)}, + i=I,vdb=Tdb1,a=A#k.a}. + %% call_op(Op) -> Op. %% bif_op(Op) -> Op. %% test_op(Op) -> Op. @@ -373,7 +341,6 @@ atomic(#k_int{val=I}) -> {integer,I}; atomic(#k_float{val=F}) -> {float,F}; atomic(#k_atom{val=N}) -> {atom,N}; %%atomic(#k_char{val=C}) -> {char,C}; -%%atomic(#k_string{val=S}) -> {string,S}; atomic(#k_nil{}) -> nil. atomic_list(Ks) -> [atomic(K) || K <- Ks]. @@ -535,3 +502,7 @@ vdb_sub(Min, Max, Vdb) -> true -> Vd end || {V,F,L}=Vd <- Vdb, F < Min, L >= Min ]. +%% is_in_guard() -> true|false. + +is_in_guard() -> + get(guard_refc) > 0. diff --git a/lib/compiler/test/core_SUITE.erl b/lib/compiler/test/core_SUITE.erl index 874e02803d..fd1539e7fd 100644 --- a/lib/compiler/test/core_SUITE.erl +++ b/lib/compiler/test/core_SUITE.erl @@ -22,7 +22,7 @@ init_per_group/2,end_per_group/2, init_per_testcase/2,end_per_testcase/2, dehydrated_itracer/1,nested_tries/1, - make_effect_seq/1,eval_is_boolean/1, + seq_in_guard/1,make_effect_seq/1,eval_is_boolean/1, unsafe_case/1,nomatch_shadow/1,reversed_annos/1]). -include_lib("test_server/include/test_server.hrl"). @@ -43,7 +43,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> test_lib:recompile(?MODULE), - [dehydrated_itracer,nested_tries,make_effect_seq, + [dehydrated_itracer,nested_tries,seq_in_guard,make_effect_seq, eval_is_boolean,unsafe_case,nomatch_shadow,reversed_annos]. groups() -> @@ -64,6 +64,7 @@ end_per_group(_GroupName, Config) -> ?comp(dehydrated_itracer). ?comp(nested_tries). +?comp(seq_in_guard). ?comp(make_effect_seq). ?comp(eval_is_boolean). ?comp(unsafe_case). diff --git a/lib/compiler/test/core_SUITE_data/seq_in_guard.core b/lib/compiler/test/core_SUITE_data/seq_in_guard.core new file mode 100644 index 0000000000..44686a7187 --- /dev/null +++ b/lib/compiler/test/core_SUITE_data/seq_in_guard.core @@ -0,0 +1,66 @@ +module 'seq_in_guard' ['seq_in_guard'/0, + 't'/1] + attributes [] +'seq_in_guard'/0 = + %% Line 4 + fun () -> + case <> of + <> when 'true' -> + let <_cor0> = + catch + %% Line 5 + apply 't'/1 + ({}) + in %% Line 5 + case _cor0 of + <{'EXIT',{'function_clause',_cor4}}> when 'true' -> + let <_cor2> = + catch + %% Line 6 + apply 't'/1 + ('atom') + in %% Line 6 + case _cor2 of + <{'EXIT',{'function_clause',_cor5}}> when 'true' -> + %% Line 7 + apply 't'/1 + ({'a','b'}) + ( <_cor3> when 'true' -> + primop 'match_fail' + ({'badmatch',_cor3}) + -| ['compiler_generated'] ) + end + ( <_cor1> when 'true' -> + primop 'match_fail' + ({'badmatch',_cor1}) + -| ['compiler_generated'] ) + end + ( <> when 'true' -> + ( primop 'match_fail' + ({'function_clause'}) + -| [{'function_name',{'seq_in_guard',0}}] ) + -| ['compiler_generated'] ) + end +'t'/1 = + %% Line 9 + fun (_cor0) -> + case _cor0 of + <X> + when try + do + call 'erlang':'element' + (2, X) + 'true' + of <Try> -> + Try + catch <T,R> -> + 'false' -> + %% Line 10 + 'ok' + ( <_cor3> when 'true' -> + ( primop 'match_fail' + ({'function_clause',_cor3}) + -| [{'function_name',{'t',1}}] ) + -| ['compiler_generated'] ) + end +end diff --git a/lib/compiler/test/core_fold_SUITE.erl b/lib/compiler/test/core_fold_SUITE.erl index fb5ec88c9f..54bd52947e 100644 --- a/lib/compiler/test/core_fold_SUITE.erl +++ b/lib/compiler/test/core_fold_SUITE.erl @@ -21,7 +21,7 @@ -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, init_per_group/2,end_per_group/2, t_element/1,setelement/1,t_length/1,append/1,t_apply/1,bifs/1, - eq/1,nested_call_in_case/1,coverage/1]). + eq/1,nested_call_in_case/1,guard_try_catch/1,coverage/1]). -export([foo/0,foo/1,foo/2,foo/3]). @@ -32,7 +32,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> test_lib:recompile(?MODULE), [t_element, setelement, t_length, append, t_apply, bifs, - eq, nested_call_in_case, coverage]. + eq, nested_call_in_case, guard_try_catch, coverage]. groups() -> []. @@ -207,6 +207,23 @@ nested_call_in_case(Config) when is_list(Config) -> ?line {'EXIT',_} = (catch Mod:a(not_a_list, 42)), ok. +guard_try_catch(_Config) -> + false = do_guard_try_catch(key, value), + value = get(key), + ok. + +do_guard_try_catch(K, V) -> + %% This try...catch block looks like a guard. + %% Make sure that it is not optimized like a guard + %% (the put/2 call must not be optimized away). + try + put(K, V), + false + catch + _:_ -> + false + end. + coverage(Config) when is_list(Config) -> ?line {'EXIT',{{case_clause,{a,b,c}},_}} = (catch cover_will_match_list_type({a,b,c})), diff --git a/lib/debugger/src/dbg_iserver.erl b/lib/debugger/src/dbg_iserver.erl index 1bb73a43b9..31a856545f 100644 --- a/lib/debugger/src/dbg_iserver.erl +++ b/lib/debugger/src/dbg_iserver.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2011. All Rights Reserved. +%% Copyright Ericsson AB 1998-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -188,10 +188,7 @@ handle_call({new_break, Point, Options}, _From, State) -> handle_call(all_breaks, _From, State) -> {reply, State#state.breaks, State}; handle_call({all_breaks, Mod}, _From, State) -> - Reply = lists:filter(fun({{M,_L}, _Options}) -> - M =/= Mod - end, - State#state.breaks), + Reply = [Break || Break = {{M, _},_} <- State#state.breaks, M =:= Mod], {reply, Reply, State}; %% From Meta process diff --git a/lib/debugger/test/int_break_SUITE.erl b/lib/debugger/test/int_break_SUITE.erl index 159678a1f9..7bb0fc2018 100644 --- a/lib/debugger/test/int_break_SUITE.erl +++ b/lib/debugger/test/int_break_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2011. All Rights Reserved. +%% Copyright Ericsson AB 1999-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -76,6 +76,9 @@ basic(Config) when list(Config) -> ?line S3 = [xxx,y] = ordsets1:add_element(y, S2), ?line ok = i:ib(ordsets1, union, 2), ?line [xxx,y,z] = ordsets1:union(S3, [z]), + All = [{{ordsets1,86}, _}, {{ordsets1,_},_}|_] = lists:sort(int:all_breaks()), + [] = lists:sort(int:all_breaks(foobar)), + All = lists:sort(int:all_breaks(ordsets1)), ok. cleanup(doc) -> "Make sure that the auto-attach flag is turned off."; diff --git a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl index 458f3a4c81..5be870d78f 100644 --- a/lib/dialyzer/src/dialyzer_analysis_callgraph.erl +++ b/lib/dialyzer/src/dialyzer_analysis_callgraph.erl @@ -170,33 +170,32 @@ analysis_start(Parent, Analysis) -> rcv_and_send_ext_types(Parent), NonExports = sets:subtract(sets:from_list(AllNodes), Exports), NonExportsList = sets:to_list(NonExports), - Plt3 = dialyzer_plt:delete_list(State3#analysis_state.plt, NonExportsList), - Plt4 = dialyzer_plt:delete_contract_list(Plt3, NonExportsList), + Plt2 = dialyzer_plt:delete_list(State3#analysis_state.plt, NonExportsList), send_codeserver_plt(Parent, CServer, State3#analysis_state.plt), - send_analysis_done(Parent, Plt4, State3#analysis_state.doc_plt). + send_analysis_done(Parent, Plt2, State3#analysis_state.doc_plt). analyze_callgraph(Callgraph, State) -> Codeserver = State#analysis_state.codeserver, - Plt = dialyzer_plt:insert_callbacks(State#analysis_state.plt, Codeserver), Parent = State#analysis_state.parent, - case State#analysis_state.analysis_type of - plt_build -> - Callgraph1 = dialyzer_callgraph:finalize(Callgraph), - NewPlt = dialyzer_succ_typings:analyze_callgraph(Callgraph1, Plt, - Codeserver, Parent), - dialyzer_callgraph:delete(Callgraph1), - State#analysis_state{plt = NewPlt}; - succ_typings -> - NoWarn = State#analysis_state.no_warn_unused, - DocPlt = State#analysis_state.doc_plt, - Callgraph1 = dialyzer_callgraph:finalize(Callgraph), - {Warnings, NewPlt, NewDocPlt} = - dialyzer_succ_typings:get_warnings(Callgraph1, Plt, DocPlt, - Codeserver, NoWarn, Parent), - dialyzer_callgraph:delete(Callgraph1), - send_warnings(State#analysis_state.parent, Warnings), - State#analysis_state{plt = NewPlt, doc_plt = NewDocPlt} - end. + DocPlt = State#analysis_state.doc_plt, + Plt = dialyzer_plt:insert_callbacks(State#analysis_state.plt, Codeserver), + Callgraph1 = dialyzer_callgraph:finalize(Callgraph), + {NewPlt, NewDocPlt} = + case State#analysis_state.analysis_type of + plt_build -> + {dialyzer_succ_typings:analyze_callgraph(Callgraph1, Plt, + Codeserver, Parent), + DocPlt}; + succ_typings -> + NoWarn = State#analysis_state.no_warn_unused, + {Warnings, NewPlt0, NewDocPlt0} = + dialyzer_succ_typings:get_warnings(Callgraph1, Plt, DocPlt, + Codeserver, NoWarn, Parent), + send_warnings(State#analysis_state.parent, Warnings), + {NewPlt0, NewDocPlt0} + end, + dialyzer_callgraph:delete(Callgraph1), + State#analysis_state{plt = NewPlt, doc_plt = NewDocPlt}. %%-------------------------------------------------------------------- %% Build the callgraph and fill the codeserver. @@ -282,10 +281,10 @@ cleanup_callgraph(#analysis_state{plt = InitPlt, parent = Parent, if ExtCalls1 =:= [] -> {[], []}; true -> ModuleSet = sets:from_list(Modules), - lists:partition(fun({_From, {M, _F, _A}}) -> - sets:is_element(M, ModuleSet) orelse - dialyzer_plt:contains_module(InitPlt, M) - end, ExtCalls1) + PltModuleSet = dialyzer_plt:all_modules(InitPlt), + AllModules = sets:union(ModuleSet, PltModuleSet), + Pred = fun({_From, {M, _F, _A}}) -> sets:is_element(M, AllModules) end, + lists:partition(Pred, ExtCalls1) end, NonLocalCalls = dialyzer_callgraph:non_local_calls(Callgraph1), BadCalls2 = [Call || Call = {_From, To} <- NonLocalCalls, @@ -366,9 +365,11 @@ abs_get_nowarn(Abs, M) -> false -> [{M, F, A} || {function, _, F, A, _} <- Abs]; % all functions true -> - [{M, F, A} || - {nowarn_unused_function, FAs} <- Opts, - {F, A} <- lists:flatten([FAs])] + OnLoad = + lists:flatten([{M, F, A} || {attribute, _, on_load, {F, A}} <- Abs]), + OnLoad ++ [{M, F, A} || + {nowarn_unused_function, FAs} <- Opts, + {F, A} <- lists:flatten([FAs])] end. get_exported_types_from_core(Core) -> diff --git a/lib/dialyzer/src/dialyzer_behaviours.erl b/lib/dialyzer/src/dialyzer_behaviours.erl index e89c08df7d..fdaa8b663c 100644 --- a/lib/dialyzer/src/dialyzer_behaviours.erl +++ b/lib/dialyzer/src/dialyzer_behaviours.erl @@ -72,9 +72,11 @@ check_callbacks(Module, Attrs, Plt, Codeserver) -> %%-------------------------------------------------------------------- get_behaviours(Attrs) -> - BehaviourListsAndLine = [{cerl:concrete(L2), hd(cerl:get_ann(L2))} || - {L1, L2} <- Attrs, cerl:is_literal(L1), - cerl:is_literal(L2), cerl:concrete(L1) =:= 'behaviour'], + BehaviourListsAndLine = + [{cerl:concrete(L2), hd(cerl:get_ann(L2))} || + {L1, L2} <- Attrs, cerl:is_literal(L1), + cerl:is_literal(L2), cerl:concrete(L1) =:= 'behaviour' orelse + cerl:concrete(L1) =:= 'behavior'], Behaviours = lists:append([Behs || {Behs,_} <- BehaviourListsAndLine]), BehLines = [{B,L} || {L1,L} <- BehaviourListsAndLine, B <- L1], {Behaviours, BehLines}. @@ -239,12 +241,12 @@ translatable_behaviours(Tree) -> get_behaviour_apis(Behaviours) -> get_behaviour_apis(Behaviours, []). --spec translate_behaviour_api_call(dialyzer_races:mfa_or_funlbl(), +-spec translate_behaviour_api_call(dialyzer_callgraph:mfa_or_funlbl(), [erl_types:erl_type()], [dialyzer_races:core_vars()], module(), behaviour_api_dict()) -> - {dialyzer_races:mfa_or_funlbl(), + {dialyzer_callgraph:mfa_or_funlbl(), [erl_types:erl_type()], [dialyzer_races:core_vars()]} | 'plain_call'. diff --git a/lib/dialyzer/src/dialyzer_callgraph.erl b/lib/dialyzer/src/dialyzer_callgraph.erl index d3de5aaf45..4767c02f77 100644 --- a/lib/dialyzer/src/dialyzer_callgraph.erl +++ b/lib/dialyzer/src/dialyzer_callgraph.erl @@ -59,7 +59,7 @@ put_named_tables/2, put_public_tables/2, put_behaviour_api_calls/2, get_behaviour_api_calls/1]). --export_type([callgraph/0]). +-export_type([callgraph/0, mfa_or_funlbl/0]). -include("dialyzer.hrl"). @@ -177,14 +177,14 @@ is_escaping(Label, #callgraph{esc = Esc}) when is_integer(Label) -> add_edges([], CG) -> CG; -add_edges(Edges, #callgraph{digraph = Callgraph} = CG) -> - CG#callgraph{digraph = digraph_add_edges(Edges, Callgraph)}. +add_edges(Edges, #callgraph{digraph = Digraph} = CG) -> + CG#callgraph{digraph = digraph_add_edges(Edges, Digraph)}. -spec add_edges([callgraph_edge()], [mfa_or_funlbl()], callgraph()) -> callgraph(). add_edges(Edges, MFAs, #callgraph{digraph = DG} = CG) -> - DG1 = digraph_confirm_vertices(MFAs, DG), - add_edges(Edges, CG#callgraph{digraph = DG1}). + DG = digraph_confirm_vertices(MFAs, DG), + add_edges(Edges, CG). -spec take_scc(callgraph()) -> 'none' | {'ok', scc(), callgraph()}. @@ -196,8 +196,8 @@ take_scc(#callgraph{postorder = []}) -> -spec remove_external(callgraph()) -> {callgraph(), [tuple()]}. remove_external(#callgraph{digraph = DG} = CG) -> - {NewDG, External} = digraph_remove_external(DG), - {CG#callgraph{digraph = NewDG}, External}. + {DG, External} = digraph_remove_external(DG), + {CG, External}. -spec non_local_calls(callgraph()) -> mfa_calls(). @@ -241,30 +241,30 @@ modules(#callgraph{digraph = DG}) -> -spec module_postorder(callgraph()) -> [[module()]]. module_postorder(#callgraph{digraph = DG}) -> + {MDG, _Nodes} = get_module_digraph_and_nodes(DG), + MDG1 = digraph_utils:condensation(MDG), + PostOrder = digraph_utils:postorder(MDG1), + PostOrder1 = sort_sccs_internally(PostOrder, MDG), + digraph:delete(MDG1), + digraph_delete(MDG), + PostOrder1. + +get_module_digraph_and_nodes(DG) -> Edges = digraph_edges(DG), Nodes = ordsets:from_list([M || {M,_F,_A} <- digraph_vertices(DG)]), MDG = digraph:new(), - MDG1 = digraph_confirm_vertices(Nodes, MDG), - MDG2 = create_module_digraph(Edges, MDG1), - MDG3 = digraph_utils:condensation(MDG2), - PostOrder = digraph_utils:postorder(MDG3), - PostOrder1 = sort_sccs_internally(PostOrder, MDG2), - digraph:delete(MDG2), - digraph_delete(MDG3), - PostOrder1. + MDG = digraph_confirm_vertices(Nodes, MDG), + MDG = create_module_digraph(Edges, MDG), + {MDG, Nodes}. %% The module deps of a module are modules that depend on the module -spec module_deps(callgraph()) -> dict(). module_deps(#callgraph{digraph = DG}) -> - Edges = digraph_edges(DG), - Nodes = ordsets:from_list([M || {M,_F,_A} <- digraph_vertices(DG)]), - MDG = digraph:new(), - MDG1 = digraph_confirm_vertices(Nodes, MDG), - MDG2 = create_module_digraph(Edges, MDG1), - Deps = [{N, ordsets:from_list(digraph:in_neighbours(MDG2, N))} + {MDG, Nodes} = get_module_digraph_and_nodes(DG), + Deps = [{N, ordsets:from_list(digraph:in_neighbours(MDG, N))} || N <- Nodes], - digraph_delete(MDG2), + digraph_delete(MDG), dict:from_list(Deps). -spec strip_module_deps(dict(), set()) -> dict(). diff --git a/lib/dialyzer/src/dialyzer_codeserver.erl b/lib/dialyzer/src/dialyzer_codeserver.erl index 13ca65e4dd..f1e87affbd 100644 --- a/lib/dialyzer/src/dialyzer_codeserver.erl +++ b/lib/dialyzer/src/dialyzer_codeserver.erl @@ -292,15 +292,11 @@ table__loop(Cached, Map) -> {NewCached, Ans} = case Cached of {M, Tree} -> - [Val] = [VarFun || {Var, _Fun} = VarFun <- cerl:module_defs(Tree), - cerl:fname_id(Var) =:= F, - cerl:fname_arity(Var) =:= A], + Val = find_fun(F, A, Tree), {Cached, Val}; _ -> Tree = fetch_and_expand(M, Map), - [Val] = [VarFun || {Var, _Fun} = VarFun <- cerl:module_defs(Tree), - cerl:fname_id(Var) =:= F, - cerl:fname_arity(Var) =:= A], + Val = find_fun(F, A, Tree), {{M, Tree}, Val} end, Pid ! {self(), MFA, Ans}, @@ -329,3 +325,12 @@ fetch_and_expand(Mod, Map) -> Msg = "found no module named '" ++ S ++ "' in the analyzed files", exit({error, Msg}) end. + +find_fun(F, A, Tree) -> + Pred = + fun({Var, _Fun}) -> + (cerl:fname_id(Var) =/= F) orelse + (cerl:fname_arity(Var) =/= A) + end, + [Val|_] = lists:dropwhile(Pred, cerl:module_defs(Tree)), + Val. diff --git a/lib/dialyzer/src/dialyzer_dataflow.erl b/lib/dialyzer/src/dialyzer_dataflow.erl index 6008dba080..aba13278ff 100644 --- a/lib/dialyzer/src/dialyzer_dataflow.erl +++ b/lib/dialyzer/src/dialyzer_dataflow.erl @@ -67,7 +67,6 @@ %%-define(DEBUG, true). %%-define(DEBUG_PP, true). -%%-define(DEBUG_TIME, true). %%-define(DOT, true). -ifdef(DEBUG). @@ -77,9 +76,6 @@ -define(debug(S_, L_), ok). -endif. -%%-define(debug1(S_, L_), io:format(S_, L_)). -%%-define(debug1(S_, L_), ok). - %%-------------------------------------------------------------------- -define(no_arg, no_arg). @@ -276,6 +272,7 @@ analyze_module(Tree, Plt, Callgraph, Records, GetWarnings) -> debug_pp(Tree, false), Module = cerl:atom_val(cerl:module_name(Tree)), RaceDetection = dialyzer_callgraph:get_race_detection(Callgraph), + RaceCode = dialyzer_callgraph:get_race_code(Callgraph), BehaviourTranslations = case RaceDetection of true -> dialyzer_behaviours:translatable_behaviours(Tree); @@ -286,9 +283,6 @@ analyze_module(Tree, Plt, Callgraph, Records, GetWarnings) -> TopFun, Plt, Module, Records, BehaviourTranslations), State1 = state__race_analysis(not GetWarnings, State), State2 = analyze_loop(State1), - RaceCode = dialyzer_callgraph:get_race_code(Callgraph), - Callgraph1 = State2#state.callgraph, - RaceCode1 = dialyzer_callgraph:get_race_code(Callgraph1), case GetWarnings of true -> State3 = state__set_warning_mode(State2), @@ -313,6 +307,8 @@ analyze_module(Tree, Plt, Callgraph, Records, GetWarnings) -> St#state{callgraph = Callgraph3} end; false -> + Callgraph1 = State2#state.callgraph, + RaceCode1 = dialyzer_callgraph:get_race_code(Callgraph1), state__restore_race_code( dict:merge(fun (_K, V1, _V2) -> V1 end, RaceCode, RaceCode1), State2) @@ -320,27 +316,26 @@ analyze_module(Tree, Plt, Callgraph, Records, GetWarnings) -> analyze_loop(#state{callgraph = Callgraph, races = Races} = State) -> case state__get_work(State) of - none -> state__clean_not_called(State); - {Fun, NewState} -> - ArgTypes = state__get_args(Fun, NewState), - case any_none(ArgTypes) of + none -> State; + {Fun, NewState1} -> + {ArgTypes, IsCalled} = state__get_args_and_status(Fun, NewState1), + case not IsCalled of true -> - ?debug("Not handling1 ~w: ~s\n", + ?debug("Not handling (not called) ~w: ~s\n", [state__lookup_name(get_label(Fun), State), t_to_string(t_product(ArgTypes))]), - analyze_loop(NewState); + analyze_loop(NewState1); false -> - case state__fun_env(Fun, NewState) of + case state__fun_env(Fun, NewState1) of none -> - ?debug("Not handling2 ~w: ~s\n", + ?debug("Not handling (no env) ~w: ~s\n", [state__lookup_name(get_label(Fun), State), t_to_string(t_product(ArgTypes))]), - analyze_loop(NewState); + analyze_loop(NewState1); Map -> ?debug("Handling fun ~p: ~s\n", [state__lookup_name(get_label(Fun), State), - t_to_string(state__fun_type(Fun, NewState))]), - NewState1 = state__mark_fun_as_handled(NewState, Fun), + t_to_string(state__fun_type(Fun, NewState1))]), Vars = cerl:fun_vars(Fun), Map1 = enter_type_lists(Vars, ArgTypes, Map), Body = cerl:fun_body(Fun), @@ -2892,28 +2887,22 @@ state__new(Callgraph, Tree, Plt, Module, Records, BehaviourTranslations) -> TreeMap = build_tree_map(Tree), Funs = dict:fetch_keys(TreeMap), FunTab = init_fun_tab(Funs, dict:new(), TreeMap, Callgraph, Plt, Opaques), - Work = init_work([get_label(Tree)]), - Env = dict:store(top, map__new(), dict:new()), + ExportedFuns = + [Fun || Fun <- Funs--[top], dialyzer_callgraph:is_escaping(Fun, Callgraph)], + Work = init_work(ExportedFuns), + Env = lists:foldl(fun(Fun, Env) -> dict:store(Fun, map__new(), Env) end, + dict:new(), Funs), #state{callgraph = Callgraph, envs = Env, fun_tab = FunTab, opaques = Opaques, plt = Plt, races = dialyzer_races:new(), records = Records, warning_mode = false, warnings = [], work = Work, tree_map = TreeMap, module = Module, behaviour_api_dict = BehaviourTranslations}. -state__mark_fun_as_handled(#state{fun_tab = FunTab} = State, Fun0) -> - Fun = get_label(Fun0), - case dict:find(Fun, FunTab) of - {ok, {not_handled, Entry}} -> - State#state{fun_tab = dict:store(Fun, Entry, FunTab)}; - {ok, {_, _}} -> - State - end. - state__warning_mode(#state{warning_mode = WM}) -> WM. state__set_warning_mode(#state{tree_map = TreeMap, fun_tab = FunTab, races = Races} = State) -> - ?debug("Starting warning pass\n", []), + ?debug("==========\nStarting warning pass\n==========\n", []), Funs = dict:fetch_keys(TreeMap), State#state{work = init_work([top|Funs--[top]]), fun_tab = FunTab, warning_mode = true, @@ -2985,7 +2974,7 @@ state__get_warnings(#state{tree_map = TreeMap, fun_tab = FunTab, {NotCalled, Ret} = case dict:fetch(get_label(Fun), FunTab) of {not_handled, {_Args0, Ret0}} -> {true, Ret0}; - {Args0, Ret0} -> {any_none(Args0), Ret0} + {_Args0, Ret0} -> {false, Ret0} end, case NotCalled of true -> @@ -3079,11 +3068,11 @@ state__lookup_record(Tag, Arity, #state{records = Records}) -> error end. -state__get_args(Tree, #state{fun_tab = FunTab}) -> +state__get_args_and_status(Tree, #state{fun_tab = FunTab}) -> Fun = get_label(Tree), case dict:find(Fun, FunTab) of - {ok, {not_handled, {ArgTypes, _}}} -> ArgTypes; - {ok, {ArgTypes, _}} -> ArgTypes + {ok, {not_handled, {ArgTypes, _}}} -> {ArgTypes, false}; + {ok, {ArgTypes, _}} -> {ArgTypes, true} end. build_tree_map(Tree) -> @@ -3099,7 +3088,7 @@ build_tree_map(Tree) -> cerl_trees:fold(Fun, dict:new(), Tree). init_fun_tab([top|Left], Dict, TreeMap, Callgraph, Plt, Opaques) -> - NewDict = dict:store(top, {not_handled, {[], t_none()}}, Dict), + NewDict = dict:store(top, {[], t_none()}, Dict), init_fun_tab(Left, NewDict, TreeMap, Callgraph, Plt, Opaques); init_fun_tab([Fun|Left], Dict, TreeMap, Callgraph, Plt, Opaques) -> Arity = cerl:fun_arity(dict:fetch(Fun, TreeMap)), @@ -3115,9 +3104,9 @@ init_fun_tab([Fun|Left], Dict, TreeMap, Callgraph, Plt, Opaques) -> false -> {Args, t_unit()} end end; - false -> {lists:duplicate(Arity, t_none()), t_unit()} + false -> {not_handled, {lists:duplicate(Arity, t_none()), t_unit()}} end, - NewDict = dict:store(Fun, {not_handled, FunEntry}, Dict), + NewDict = dict:store(Fun, FunEntry, Dict), init_fun_tab(Left, NewDict, TreeMap, Callgraph, Plt, Opaques); init_fun_tab([], Dict, _TreeMap, _Callgraph, _Plt, _Opaques) -> Dict. @@ -3141,7 +3130,8 @@ state__clean_not_called(#state{fun_tab = FunTab} = State) -> end, FunTab), State#state{fun_tab = NewFunTab}. -state__all_fun_types(#state{fun_tab = FunTab}) -> +state__all_fun_types(State) -> + #state{fun_tab = FunTab} = state__clean_not_called(State), Tab1 = dict:erase(top, FunTab), dict:map(fun(_Fun, {Args, Ret}) -> t_fun(Args, Ret)end, Tab1). diff --git a/lib/dialyzer/src/dialyzer_gui.erl b/lib/dialyzer/src/dialyzer_gui.erl index f60194e01f..bac659548f 100644 --- a/lib/dialyzer/src/dialyzer_gui.erl +++ b/lib/dialyzer/src/dialyzer_gui.erl @@ -511,6 +511,16 @@ gui_loop(#gui_state{add_all = AddAll, add_file = AddFile, add_rec = AddRec, [ExtCalls]), free_editor(State, "Analysis done", Msg), gui_loop(State); + {BackendPid, ext_types, ExtTypes} -> + Map = fun({M,F,A}) -> io_lib:format("~p:~p/~p",[M,F,A]) end, + ExtTypeString = string:join(lists:map(Map, ExtTypes), "\n"), + Msg = io_lib:format("The following remote types are being used " + "but information about them is not available.\n" + "The analysis might get more precise by including " + "the modules containing these types and making sure " + "that they are exported:\n~s\n", [ExtTypeString]), + free_editor(State, "Analysis done", Msg), + gui_loop(State); {BackendPid, log, LogMsg} -> update_editor(Log, LogMsg), gui_loop(State); diff --git a/lib/dialyzer/src/dialyzer_gui_wx.erl b/lib/dialyzer/src/dialyzer_gui_wx.erl index e711c15ea7..9ff32bd8b1 100644 --- a/lib/dialyzer/src/dialyzer_gui_wx.erl +++ b/lib/dialyzer/src/dialyzer_gui_wx.erl @@ -503,6 +503,16 @@ gui_loop(#gui_state{backend_pid = BackendPid, doc_plt = DocPlt, [ExtCalls]), free_editor(State,"Analysis Done", Msg), gui_loop(State); + {BackendPid, ext_types, ExtTypes} -> + Map = fun({M,F,A}) -> io_lib:format("~p:~p/~p",[M,F,A]) end, + ExtTypeString = string:join(lists:map(Map, ExtTypes), "\n"), + Msg = io_lib:format("The following remote types are being used " + "but information about them is not available.\n" + "The analysis might get more precise by including " + "the modules containing these types and making sure " + "that they are exported:\n~s\n", [ExtTypeString]), + free_editor(State, "Analysis done", Msg), + gui_loop(State); {BackendPid, log, LogMsg} -> update_editor(Log, LogMsg), gui_loop(State); diff --git a/lib/dialyzer/src/dialyzer_plt.erl b/lib/dialyzer/src/dialyzer_plt.erl index 206c43e4e2..74892d1668 100644 --- a/lib/dialyzer/src/dialyzer_plt.erl +++ b/lib/dialyzer/src/dialyzer_plt.erl @@ -31,8 +31,7 @@ -export([check_plt/3, compute_md5_from_files/1, contains_mfa/2, - contains_module/2, - delete_contract_list/2, + all_modules/1, delete_list/2, delete_module/2, included_files/1, @@ -153,10 +152,8 @@ lookup_contract(#plt{contracts = Contracts}, {M, F, _} = MFA) when is_atom(M), is_atom(F) -> table_lookup(Contracts, MFA). --spec lookup_callbacks(plt(), module()) -> [{mfa(), - {{Filename::string(), - Line::pos_integer()}, - #contract{}}}]. +-spec lookup_callbacks(plt(), module()) -> + [{mfa(), {{Filename::string(), Line::pos_integer()}, #contract{}}}]. lookup_callbacks(#plt{callbacks = Callbacks}, Mod) when is_atom(Mod) -> FunModFilter = @@ -166,18 +163,6 @@ lookup_callbacks(#plt{callbacks = Callbacks}, Mod) when is_atom(Mod) -> ModCallbacks = dict:filter(FunModFilter, Callbacks), dict:to_list(ModCallbacks). --spec delete_contract_list(plt(), [mfa()]) -> plt(). - -delete_contract_list(#plt{contracts = Contracts, - callbacks = Callbacks} = PLT, List) -> - PLT#plt{contracts = table_delete_list(Contracts, List), - callbacks = table_delete_list(Callbacks, List)}. - -%% -spec insert(plt(), mfa() | integer(), {_, _}) -> plt(). -%% -%% insert(#plt{info = Info} = PLT, Id, Types) -> -%% PLT#plt{info = table_insert(Info, Id, Types)}. - -type ret_args_types() :: {erl_types:erl_type(), [erl_types:erl_type()]}. -spec insert_list(plt(), [{mfa() | integer(), ret_args_types()}]) -> plt(). @@ -220,10 +205,10 @@ get_exported_types(#plt{exported_types = ExpTypes}) -> lookup_module(#plt{info = Info}, M) when is_atom(M) -> table_lookup_module(Info, M). --spec contains_module(plt(), atom()) -> boolean(). +-spec all_modules(plt()) -> set(). -contains_module(#plt{info = Info, contracts = Cs}, M) when is_atom(M) -> - table_contains_module(Info, M) orelse table_contains_module(Cs, M). +all_modules(#plt{info = Info, contracts = Cs}) -> + sets:union(table_all_modules(Info), table_all_modules(Cs)). -spec contains_mfa(plt(), mfa()) -> boolean(). @@ -623,10 +608,12 @@ table_lookup_module(Plt, Mod) -> false -> {value, List} end. -table_contains_module(Plt, Mod) -> - dict:fold(fun({M, _F, _A}, _Val, _Acc) when M =:= Mod -> true; - (_, _, Acc) -> Acc - end, false, Plt). +table_all_modules(Plt) -> + Fold = + fun({M, _F, _A}, _Val, Acc) -> sets:add_element(M, Acc); + (_, _, Acc) -> Acc + end, + dict:fold(Fold, sets:new(), Plt). table_merge([H|T]) -> table_merge(T, H). diff --git a/lib/dialyzer/src/dialyzer_races.erl b/lib/dialyzer/src/dialyzer_races.erl index ee9d5e88a3..b9594f5301 100644 --- a/lib/dialyzer/src/dialyzer_races.erl +++ b/lib/dialyzer/src/dialyzer_races.erl @@ -39,7 +39,7 @@ let_tag_new/2, new/0, put_curr_fun/3, put_fun_args/2, put_race_analysis/2, put_race_list/3]). --export_type([races/0, mfa_or_funlbl/0, core_vars/0]). +-export_type([races/0, core_vars/0]). -include("dialyzer.hrl"). @@ -66,8 +66,6 @@ %%% %%% =========================================================================== --type mfa_or_funlbl() :: label() | mfa(). - -type label_type() :: label() | [label()] | {label()} | ?no_label. -type args() :: [label_type() | [string()]]. -type core_vars() :: cerl:cerl() | ?no_arg | ?bypassed. @@ -94,7 +92,7 @@ guard :: cerl:cerl()}). -record(end_case, {clauses :: [#end_clause{}]}). -record(curr_fun, {status :: 'in' | 'out', - mfa :: mfa_or_funlbl(), + mfa :: dialyzer_callgraph:mfa_or_funlbl(), label :: label(), def_vars :: [core_vars()], arg_types :: [erl_types:erl_type()], @@ -107,8 +105,8 @@ state :: _, %% XXX: recursive file_line :: file_line(), var_map :: dict()}). --record(fun_call, {caller :: mfa_or_funlbl(), - callee :: mfa_or_funlbl(), +-record(fun_call, {caller :: dialyzer_callgraph:mfa_or_funlbl(), + callee :: dialyzer_callgraph:mfa_or_funlbl(), arg_types :: [erl_types:erl_type()], vars :: [core_vars()]}). -record(let_tag, {var :: var_to_map1(), @@ -130,10 +128,10 @@ vars :: [core_vars()], file_line :: file_line(), index :: non_neg_integer(), - fun_mfa :: mfa_or_funlbl(), + fun_mfa :: dialyzer_callgraph:mfa_or_funlbl(), fun_label :: label()}). --record(races, {curr_fun :: mfa_or_funlbl(), +-record(races, {curr_fun :: dialyzer_callgraph:mfa_or_funlbl(), curr_fun_label :: label(), curr_fun_args = 'empty' :: core_args(), new_table = 'no_t' :: table(), @@ -158,7 +156,8 @@ %%% %%% =========================================================================== --spec store_race_call(mfa_or_funlbl(), [erl_types:erl_type()], [core_vars()], +-spec store_race_call(dialyzer_callgraph:mfa_or_funlbl(), + [erl_types:erl_type()], [core_vars()], file_line(), dialyzer_dataflow:state()) -> dialyzer_dataflow:state(). @@ -2405,7 +2404,7 @@ end_case_new(Clauses) -> end_clause_new(Arg, Pats, Guard) -> #end_clause{arg = Arg, pats = Pats, guard = Guard}. --spec get_curr_fun(races()) -> mfa_or_funlbl(). +-spec get_curr_fun(races()) -> dialyzer_callgraph:mfa_or_funlbl(). get_curr_fun(#races{curr_fun = CurrFun}) -> CurrFun. @@ -2444,7 +2443,7 @@ let_tag_new(Var, Arg) -> new() -> #races{}. --spec put_curr_fun(mfa_or_funlbl(), label(), races()) -> +-spec put_curr_fun(dialyzer_callgraph:mfa_or_funlbl(), label(), races()) -> races(). put_curr_fun(CurrFun, CurrFunLabel, Races) -> diff --git a/lib/dialyzer/src/dialyzer_succ_typings.erl b/lib/dialyzer/src/dialyzer_succ_typings.erl index 4d86bb34a7..de4c8a32a3 100644 --- a/lib/dialyzer/src/dialyzer_succ_typings.erl +++ b/lib/dialyzer/src/dialyzer_succ_typings.erl @@ -204,7 +204,7 @@ refine_one_module(M, State) -> #st{callgraph = Callgraph, codeserver = CodeServer, plt = PLT} = State, ModCode = dialyzer_codeserver:lookup_mod_code(M, CodeServer), AllFuns = collect_fun_info([ModCode]), - FunTypes = get_fun_types_from_plt(AllFuns, State), + FunTypes = get_fun_types_from_plt(AllFuns, Callgraph, PLT), Records = dialyzer_codeserver:lookup_mod_records(M, CodeServer), {NewFunTypes, RaceCode, PublicTables, NamedTables} = dialyzer_dataflow:get_fun_types(ModCode, PLT, Callgraph, Records), @@ -321,7 +321,9 @@ find_succ_typings(#st{callgraph = Callgraph, parent = Parent} = State, end end. -analyze_scc(SCC, #st{codeserver = Codeserver} = State) -> +analyze_scc(SCC, #st{codeserver = Codeserver, + callgraph = Callgraph, + plt = Plt} = State) -> SCC_Info = [{MFA, dialyzer_codeserver:lookup_mfa_code(MFA, Codeserver), dialyzer_codeserver:lookup_mod_records(M, Codeserver)} @@ -330,23 +332,19 @@ analyze_scc(SCC, #st{codeserver = Codeserver} = State) -> || {_, _, _} = MFA <- SCC], Contracts2 = [{MFA, Contract} || {MFA, {ok, Contract}} <- Contracts1], Contracts3 = orddict:from_list(Contracts2), + NextLabel = dialyzer_codeserver:get_next_core_label(Codeserver), {SuccTypes, PltContracts, NotFixpoint} = - find_succ_types_for_scc(SCC_Info, Contracts3, State), + find_succ_types_for_scc(SCC_Info, Contracts3, NextLabel, Callgraph, Plt), State1 = insert_into_plt(SuccTypes, State), ContrPlt = dialyzer_plt:insert_contract_list(State1#st.plt, PltContracts), {State1#st{plt = ContrPlt}, NotFixpoint}. -find_succ_types_for_scc(SCC_Info, Contracts, - #st{codeserver = Codeserver, - callgraph = Callgraph, plt = Plt} = State) -> +find_succ_types_for_scc(SCC_Info, Contracts, NextLabel, Callgraph, Plt) -> %% Assume that the PLT contains the current propagated types AllFuns = collect_fun_info([Fun || {_MFA, {_Var, Fun}, _Rec} <- SCC_Info]), - PropTypes = get_fun_types_from_plt(AllFuns, State), - MFAs = [MFA || {MFA, {_Var, _Fun}, _Rec} <- SCC_Info], - NextLabel = dialyzer_codeserver:get_next_core_label(Codeserver), - Plt1 = dialyzer_plt:delete_contract_list(Plt, MFAs), + PropTypes = get_fun_types_from_plt(AllFuns, Callgraph, Plt), FunTypes = dialyzer_typesig:analyze_scc(SCC_Info, NextLabel, - Callgraph, Plt1, PropTypes), + Callgraph, Plt, PropTypes), AllFunSet = sets:from_list([X || {X, _} <- AllFuns]), FilteredFunTypes = dict:filter(fun(X, _) -> sets:is_element(X, AllFunSet) @@ -372,13 +370,13 @@ find_succ_types_for_scc(SCC_Info, Contracts, ordsets:from_list([Fun || {Fun, _Arity} <- AllFuns])} end. -get_fun_types_from_plt(FunList, State) -> - get_fun_types_from_plt(FunList, State, dict:new()). +get_fun_types_from_plt(FunList, Callgraph, Plt) -> + get_fun_types_from_plt(FunList, Callgraph, Plt, dict:new()). -get_fun_types_from_plt([{FunLabel, Arity}|Left], State, Map) -> - Type = lookup_fun_type(FunLabel, Arity, State), - get_fun_types_from_plt(Left, State, dict:store(FunLabel, Type, Map)); -get_fun_types_from_plt([], _State, Map) -> +get_fun_types_from_plt([{FunLabel, Arity}|Left], Callgraph, Plt, Map) -> + Type = lookup_fun_type(FunLabel, Arity, Callgraph, Plt), + get_fun_types_from_plt(Left, Callgraph, Plt, dict:store(FunLabel, Type, Map)); +get_fun_types_from_plt([], _Callgraph, _Plt, Map) -> Map. collect_fun_info(Trees) -> @@ -396,7 +394,7 @@ collect_fun_info([Tree|Trees], List) -> collect_fun_info([], List) -> List. -lookup_fun_type(Label, Arity, #st{callgraph = Callgraph, plt = Plt}) -> +lookup_fun_type(Label, Arity, Callgraph, Plt) -> ID = lookup_name(Label, Callgraph), case dialyzer_plt:lookup(Plt, ID) of none -> erl_types:t_fun(Arity, erl_types:t_any()); diff --git a/lib/dialyzer/src/dialyzer_typesig.erl b/lib/dialyzer/src/dialyzer_typesig.erl index 4268814859..04ff8e4941 100644 --- a/lib/dialyzer/src/dialyzer_typesig.erl +++ b/lib/dialyzer/src/dialyzer_typesig.erl @@ -91,22 +91,24 @@ -type typesig_scc() :: [{mfa(), {cerl:c_var(), cerl:c_fun()}, dict()}]. -type typesig_funmap() :: [{type_var(), type_var()}]. %% Orddict --record(state, {callgraph :: dialyzer_callgraph:callgraph(), - cs = [] :: [constr()], - cmap = dict:new() :: dict(), - fun_map = [] :: typesig_funmap(), - fun_arities = dict:new() :: dict(), - in_match = false :: boolean(), - in_guard = false :: boolean(), - module :: module(), - name_map = dict:new() :: dict(), - next_label :: label(), - non_self_recs = [] :: [label()], - plt :: dialyzer_plt:plt(), - prop_types = dict:new() :: dict(), - records = dict:new() :: dict(), - opaques = [] :: [erl_types:erl_type()], - scc = [] :: [type_var()]}). +-record(state, {callgraph :: dialyzer_callgraph:callgraph(), + cs = [] :: [constr()], + cmap = dict:new() :: dict(), + fun_map = [] :: typesig_funmap(), + fun_arities = dict:new() :: dict(), + in_match = false :: boolean(), + in_guard = false :: boolean(), + module :: module(), + name_map = dict:new() :: dict(), + next_label :: label(), + self_recs :: [label()], + plt :: dialyzer_plt:plt(), + prop_types = dict:new() :: dict(), + records = dict:new() :: dict(), + opaques = [] :: [erl_types:erl_type()], + scc = [] :: [type_var()], + mfas = [] :: [dialyzer_callgraph:mfa_or_funlbl()] + }). %%----------------------------------------------------------------------------- @@ -448,7 +450,8 @@ traverse(Tree, DefinedVars, State) -> %% Check if a record is constructed. _ -> Arity = length(Fields), - case state__lookup_record(State2, cerl:atom_val(Tag), Arity) of + Records = State2#state.records, + case lookup_record(Records, cerl:atom_val(Tag), Arity) of error -> {State2, TupleType}; {ok, RecType} -> State3 = state__store_conj(TupleType, sub, RecType, State2), @@ -646,8 +649,14 @@ get_plt_constr(MFA, Dst, ArgVars, State) -> PltRes = dialyzer_plt:lookup(Plt, MFA), Opaques = State#state.opaques, Module = State#state.module, + SCCMFAs = State#state.mfas, {FunModule, _, _} = MFA, - case dialyzer_plt:lookup_contract(Plt, MFA) of + Contract = + case lists:member(MFA, SCCMFAs) of + true -> none; + false -> dialyzer_plt:lookup_contract(Plt, MFA) + end, + case Contract of none -> case PltRes of none -> State; @@ -1246,6 +1255,8 @@ get_bif_constr({erlang, is_record, 2}, Dst, [Var, Tag] = Args, _State) -> mk_constraint(Var, sub, ArgV)]); get_bif_constr({erlang, is_record, 3}, Dst, [Var, Tag, Arity] = Args, State) -> %% TODO: Revise this to make it precise for Tag and Arity. + Records = State#state.records, + AllOpaques = State#state.opaques, ArgFun = fun(Map) -> case t_is_atom(true, lookup_type(Dst, Map)) of @@ -1262,10 +1273,8 @@ get_bif_constr({erlang, is_record, 3}, Dst, [Var, Tag, Arity] = Args, State) -> GenRecord = t_tuple([TagType|AnyElems]), case t_atom_vals(TagType) of [TagVal] -> - case state__lookup_record(State, TagVal, - ArityVal - 1) of + case lookup_record(Records, TagVal, ArityVal - 1) of {ok, Type} -> - AllOpaques = State#state.opaques, case t_opaque_match_record(Type, AllOpaques) of [Opaque] -> Opaque; _ -> Type @@ -1287,7 +1296,7 @@ get_bif_constr({erlang, is_record, 3}, Dst, [Var, Tag, Arity] = Args, State) -> DstFun = fun(Map) -> [TmpVar, TmpTag, TmpArity] = TmpArgTypes = lookup_type_list(Args, Map), TmpArgTypes2 = - case lists:member(TmpVar, State#state.opaques) of + case lists:member(TmpVar, AllOpaques) of true -> case t_is_integer(TmpArity) of true -> @@ -1297,7 +1306,8 @@ get_bif_constr({erlang, is_record, 3}, Dst, [Var, Tag, Arity] = Args, State) -> true -> case t_atom_vals(TmpTag) of [TmpTagVal] -> - case state__lookup_record(State, TmpTagVal, TmpArityVal - 1) of + case lookup_record(Records, TmpTagVal, + TmpArityVal - 1) of {ok, TmpType} -> case t_is_none(t_inf(TmpType, TmpVar, opaque)) of true -> TmpArgTypes; @@ -1526,9 +1536,10 @@ get_bif_constr({erlang, element, 2} = _BIF, Dst, Args, case t_is_none(GenType) of true -> ?debug("Bif: ~w failed\n", [_BIF]), throw(error); false -> + Opaques = State#state.opaques, Fun = fun(Map) -> [I, T] = ATs = lookup_type_list(Args, Map), - ATs2 = case lists:member(T, State#state.opaques) of + ATs2 = case lists:member(T, Opaques) of true -> [I, erl_types:t_opaque_structure(T)]; false -> ATs end, @@ -1546,7 +1557,7 @@ get_bif_constr({erlang, element, 2} = _BIF, Dst, Args, end; get_bif_constr({M, F, A} = _BIF, Dst, Args, State) -> GenType = erl_bif_types:type(M, F, A), - Opaques = State#state.opaques, + Opaques = State#state.opaques, case t_is_none(GenType) of true -> ?debug("Bif: ~w failed\n", [_BIF]), throw(error); false -> @@ -1612,11 +1623,12 @@ get_bif_test_constr(Dst, Arg, Type, State) -> end end, ArgV = ?mk_fun_var(ArgFun, [Dst]), + Opaques = State#state.opaques, DstFun = fun(Map) -> ArgType = lookup_type(Arg, Map), case t_is_none(t_inf(ArgType, Type)) of true -> - case lists:member(ArgType, State#state.opaques) of + case lists:member(ArgType, Opaques) of true -> OpaqueStruct = erl_types:t_opaque_structure(ArgType), case t_is_none(t_inf(OpaqueStruct, Type)) of @@ -1743,33 +1755,29 @@ solve_ref_or_list(#constraint_ref{id = Id, deps = Deps}, true -> solve_self_recursive(Cs, Map, MapDict, Id, t_none(), State); false -> solve_ref_or_list(Cs, Map, MapDict, State) end, - case Res of - {error, NewMapDict} -> - ?debug("Error solving for function ~p\n", [debug_lookup_name(Id)]), - Arity = state__fun_arity(Id, State), - FunType = - case state__prop_domain(t_var_name(Id), State) of - error -> t_fun(Arity, t_none()); - {ok, Dom} -> t_fun(Dom, t_none()) - end, - NewMap1 = enter_type(Id, FunType, Map), - NewMap2 = - case state__get_rec_var(Id, State) of - {ok, Var} -> enter_type(Var, FunType, NewMap1); - error -> NewMap1 - end, - {ok, dict:store(Id, NewMap2, NewMapDict), NewMap2}; - {ok, NewMapDict, NewMap} -> - ?debug("Done solving fun: ~p\n", [debug_lookup_name(Id)]), - FunType = lookup_type(Id, NewMap), - NewMap1 = enter_type(Id, FunType, Map), - NewMap2 = - case state__get_rec_var(Id, State) of - {ok, Var} -> enter_type(Var, FunType, NewMap1); - error -> NewMap1 - end, - {ok, dict:store(Id, NewMap2, NewMapDict), NewMap2} - end + {NewMapDict, FunType} = + case Res of + {error, NewMapDict0} -> + ?debug("Error solving for function ~p\n", [debug_lookup_name(Id)]), + Arity = state__fun_arity(Id, State), + FunType0 = + case state__prop_domain(t_var_name(Id), State) of + error -> t_fun(Arity, t_none()); + {ok, Dom} -> t_fun(Dom, t_none()) + end, + {NewMapDict0, FunType0}; + {ok, NewMapDict0, NewMap} -> + ?debug("Done solving fun: ~p\n", [debug_lookup_name(Id)]), + FunType0 = lookup_type(Id, NewMap), + {NewMapDict0, FunType0} + end, + NewMap1 = enter_type(Id, FunType, Map), + NewMap2 = + case state__get_rec_var(Id, State) of + {ok, Var} -> enter_type(Var, FunType, NewMap1); + error -> NewMap1 + end, + {ok, dict:store(Id, NewMap2, NewMapDict), NewMap2} end; solve_ref_or_list(#constraint_list{type=Type, list = Cs, deps = Deps, id = Id}, Map, MapDict, State) -> @@ -2078,10 +2086,15 @@ mk_var_no_lit_list(List) -> %% ============================================================================ new_state(SCC0, NextLabel, CallGraph, Plt, PropTypes) -> - NameMap = dict:from_list([{MFA, Var} || {MFA, {Var, _Fun}, _Rec} <- SCC0]), + List = [{MFA, Var} || {MFA, {Var, _Fun}, _Rec} <- SCC0], + NameMap = dict:from_list(List), + MFAs = [MFA || {MFA, _Var} <- List], SCC = [mk_var(Fun) || {_MFA, {_Var, Fun}, _Rec} <- SCC0], + SelfRecs = [F || F <- SCC, + dialyzer_callgraph:is_self_rec(t_var_name(F), CallGraph)], #state{callgraph = CallGraph, name_map = NameMap, next_label = NextLabel, - prop_types = PropTypes, plt = Plt, scc = ordsets:from_list(SCC)}. + prop_types = PropTypes, plt = Plt, scc = ordsets:from_list(SCC), + mfas = MFAs, self_recs = ordsets:from_list(SelfRecs)}. state__set_rec_dict(State, RecDict) -> State#state{records = RecDict}. @@ -2091,15 +2104,6 @@ state__set_opaques(#state{records = RecDict} = State, {M, _F, _A}) -> erl_types:module_builtin_opaques(M) ++ t_opaque_from_records(RecDict), State#state{opaques = Opaques, module = M}. -state__lookup_record(#state{records = Records}, Tag, Arity) -> - case erl_types:lookup_record(Tag, Arity, Records) of - {ok, Fields} -> - {ok, t_tuple([t_from_term(Tag)| - [FieldType || {_FieldName, FieldType} <- Fields]])}; - error -> - error - end. - state__set_in_match(State, Bool) -> State#state{in_match = Bool}. @@ -2268,14 +2272,12 @@ state__get_cs(Var, #state{cmap = Dict}) -> %% The functions here will not be treated as self recursive. %% These functions will need to be handled as such manually. -state__mark_as_non_self_rec(SCC, #state{non_self_recs = NS} = State) -> - State#state{non_self_recs = ordsets:union(NS, ordsets:from_list(SCC))}. +state__mark_as_non_self_rec(SCC, #state{self_recs = SelfRecs} = State) -> + %% TODO: Check if the result is always empty and just set it to [] if so. + State#state{self_recs = ordsets:subtract(SelfRecs, ordsets:from_list(SCC))}. -state__is_self_rec(Fun, #state{callgraph = CallGraph, non_self_recs = NS}) -> - case ordsets:is_element(Fun, NS) of - true -> false; - false -> dialyzer_callgraph:is_self_rec(t_var_name(Fun), CallGraph) - end. +state__is_self_rec(Fun, #state{self_recs = SelfRecs}) -> + ordsets:is_element(Fun, SelfRecs). state__store_funs(Vars0, Funs0, #state{fun_map = Map} = State) -> debug_make_name_map(Vars0, Funs0), @@ -2689,6 +2691,15 @@ find_constraint(Tuple, [#constraint_list{list = List}|Cs]) -> find_constraint(Tuple, [_|Cs]) -> find_constraint(Tuple, Cs). +lookup_record(Records, Tag, Arity) -> + case erl_types:lookup_record(Tag, Arity, Records) of + {ok, Fields} -> + {ok, t_tuple([t_from_term(Tag)| + [FieldType || {_FieldName, FieldType} <- Fields]])}; + error -> + error + end. + %% ============================================================================ %% %% Pretty printer and debug facilities. diff --git a/lib/dialyzer/test/Makefile b/lib/dialyzer/test/Makefile index 47deb17f1d..6a1abce943 100644 --- a/lib/dialyzer/test/Makefile +++ b/lib/dialyzer/test/Makefile @@ -30,5 +30,5 @@ release_tests_spec: $(INSTALL_DATA) $(AUXILIARY_FILES) $(RELSYSDIR) @tar cf - *_SUITE_data | (cd $(RELSYSDIR); tar xf -) cd $(RELSYSDIR);\ - erl -make;\ + erlc dialyzer_common.erl file_utils.erl;\ erl -noshell -run dialyzer_common create_all_suites -s erlang halt diff --git a/lib/dialyzer/test/behaviour_SUITE_data/results/sample_behaviour b/lib/dialyzer/test/behaviour_SUITE_data/results/sample_behaviour index a38e662ccf..8cecabccaa 100644 --- a/lib/dialyzer/test/behaviour_SUITE_data/results/sample_behaviour +++ b/lib/dialyzer/test/behaviour_SUITE_data/results/sample_behaviour @@ -1,9 +1,9 @@ -sample_callback_wrong.erl:15: The inferred return type of sample_callback_2/0 (42) has nothing in common with atom(), which is the expected return type for the callback of sample_behaviour behaviour -sample_callback_wrong.erl:16: The inferred return type of sample_callback_3/0 ('fair') has nothing in common with 'fail' | {'ok',1..255}, which is the expected return type for the callback of sample_behaviour behaviour -sample_callback_wrong.erl:17: The inferred return type of sample_callback_4/1 ('fail') has nothing in common with 'ok', which is the expected return type for the callback of sample_behaviour behaviour -sample_callback_wrong.erl:19: The inferred return type of sample_callback_5/1 (string()) has nothing in common with 'fail' | 'ok', which is the expected return type for the callback of sample_behaviour behaviour -sample_callback_wrong.erl:19: The inferred type for the 1st argument of sample_callback_5/1 (atom()) is not a supertype of 1..255, which is expected type for this argument in the callback of the sample_behaviour behaviour -sample_callback_wrong.erl:21: The inferred return type of sample_callback_6/3 ({'okk',number()}) has nothing in common with 'fail' | {'ok',1..255}, which is the expected return type for the callback of sample_behaviour behaviour -sample_callback_wrong.erl:21: The inferred type for the 3rd argument of sample_callback_6/3 (atom()) is not a supertype of string(), which is expected type for this argument in the callback of the sample_behaviour behaviour -sample_callback_wrong.erl:3: Undefined callback function sample_callback_1/0 (behaviour 'sample_behaviour') +sample_callback_wrong.erl:16: The inferred return type of sample_callback_2/0 (42) has nothing in common with atom(), which is the expected return type for the callback of sample_behaviour behaviour +sample_callback_wrong.erl:17: The inferred return type of sample_callback_3/0 ('fair') has nothing in common with 'fail' | {'ok',1..255}, which is the expected return type for the callback of sample_behaviour behaviour +sample_callback_wrong.erl:18: The inferred return type of sample_callback_4/1 ('fail') has nothing in common with 'ok', which is the expected return type for the callback of sample_behaviour behaviour +sample_callback_wrong.erl:20: The inferred return type of sample_callback_5/1 (string()) has nothing in common with 'fail' | 'ok', which is the expected return type for the callback of sample_behaviour behaviour +sample_callback_wrong.erl:20: The inferred type for the 1st argument of sample_callback_5/1 (atom()) is not a supertype of 1..255, which is expected type for this argument in the callback of the sample_behaviour behaviour +sample_callback_wrong.erl:22: The inferred return type of sample_callback_6/3 ({'okk',number()}) has nothing in common with 'fail' | {'ok',1..255}, which is the expected return type for the callback of sample_behaviour behaviour +sample_callback_wrong.erl:22: The inferred type for the 3rd argument of sample_callback_6/3 (atom()) is not a supertype of string(), which is expected type for this argument in the callback of the sample_behaviour behaviour +sample_callback_wrong.erl:4: Undefined callback function sample_callback_1/0 (behaviour 'sample_behaviour') diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/custom_sup.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/custom_sup.erl new file mode 100644 index 0000000000..8ec84d798f --- /dev/null +++ b/lib/dialyzer/test/behaviour_SUITE_data/src/custom_sup.erl @@ -0,0 +1,37 @@ +%%% Dialyzer was giving a warning with this input because of a bug in the +%%% substitution of remote types in specs. Remote types in the first element of +%%% a tuple would not update the tuple's tag set and we could end up with a +%%% non-normalized representation. +%%% +%%% Reported by Damian Dobroczyński on 29/02/2012 + +-module(custom_sup). + +-behavior(supervisor). + +-export([init/1]). + +-spec init(atom()) -> + {ok, {{supervisor:strategy(), non_neg_integer(), non_neg_integer()}, + [supervisor:child_spec()]}} | ignore. + +init(StorageName) -> + Strategy = {one_for_all, 100, 1}, + %% get application-wide storage parameters + case application:get_env(storage) of + undefined -> + ignore; + {ok, Storage} -> + BackendId = proplists:get_value(backend, Storage), + BackendArgs = proplists:get_value(args, Storage), + if + (BackendId =:= undefined) orelse (BackendArgs =:= undefined) -> + ignore; + true -> + {ok, {Strategy, + [{id1, {a_module, start_link, []}, + permanent, 5000, worker, [a_module]}, + {id2, {another_module, start_link, []}, + permanent, 5000, worker, [another_module]}]}} + end + end. diff --git a/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_callback_wrong.erl b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_callback_wrong.erl index 02a063fab7..430494c48c 100644 --- a/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_callback_wrong.erl +++ b/lib/dialyzer/test/behaviour_SUITE_data/src/sample_behaviour/sample_callback_wrong.erl @@ -1,6 +1,7 @@ -module(sample_callback_wrong). --behaviour(sample_behaviour). +%% This attribute uses the american spelling of 'behaviour'. +-behavior(sample_behaviour). -export([ % sample_callback_1/0, diff --git a/lib/dialyzer/test/dialyzer_common.erl b/lib/dialyzer/test/dialyzer_common.erl index 51766a4604..d2b1026c06 100644 --- a/lib/dialyzer/test/dialyzer_common.erl +++ b/lib/dialyzer/test/dialyzer_common.erl @@ -216,10 +216,13 @@ get_suites(Dir) -> end. suffix(String, Suffix) -> - Index = string:rstr(String, Suffix), - case string:substr(String, Index) =:= Suffix of - true -> {yes, string:sub_string(String,1,Index-1)}; - false -> no + case string:rstr(String, Suffix) of + 0 -> no; + Index -> + case string:substr(String, Index) =:= Suffix of + true -> {yes, string:sub_string(String,1,Index-1)}; + false -> no + end end. -spec create_suite(string()) -> 'ok'. diff --git a/lib/dialyzer/test/opaque_SUITE_data/results/multiple_wrong_opaques b/lib/dialyzer/test/opaque_SUITE_data/results/multiple_wrong_opaques new file mode 100644 index 0000000000..18ece8820c --- /dev/null +++ b/lib/dialyzer/test/opaque_SUITE_data/results/multiple_wrong_opaques @@ -0,0 +1,2 @@ + +multiple_wrong_opaques.erl:5: Invalid type specification for function multiple_wrong_opaques:weird/1. The success typing is ('gazonk') -> 42 diff --git a/lib/dialyzer/test/opaque_SUITE_data/src/multiple_wrong_opaques.erl b/lib/dialyzer/test/opaque_SUITE_data/src/multiple_wrong_opaques.erl new file mode 100644 index 0000000000..9e695cec1d --- /dev/null +++ b/lib/dialyzer/test/opaque_SUITE_data/src/multiple_wrong_opaques.erl @@ -0,0 +1,8 @@ +-module(multiple_wrong_opaques). + +-export([weird/1]). + +-spec weird(dict() | gb_tree()) -> 42. + +weird(gazonk) -> 42. + diff --git a/lib/dialyzer/test/options1_SUITE_data/results/compiler b/lib/dialyzer/test/options1_SUITE_data/results/compiler index e82087ae86..6399e3e36b 100644 --- a/lib/dialyzer/test/options1_SUITE_data/results/compiler +++ b/lib/dialyzer/test/options1_SUITE_data/results/compiler @@ -20,6 +20,7 @@ cerl_inline.erl:2333: The pattern 'true' can never match the type 'false' cerl_inline.erl:2355: The pattern 'true' can never match the type 'false' cerl_inline.erl:238: The pattern 'true' can never match the type 'false' cerl_inline.erl:2436: Function filename/1 will never be called +cerl_inline.erl:244: Function counter_stats/0 will never be called cerl_inline.erl:2700: The pattern 'true' can never match the type 'false' cerl_inline.erl:2730: The pattern <{F, L, D}, Vs> can never match the type <[1..255,...],[any()]> cerl_inline.erl:2738: The pattern <{F, L, D}, Vs> can never match the type <[1..255,...],[any()]> diff --git a/lib/dialyzer/test/r9c_SUITE_data/results/inets b/lib/dialyzer/test/r9c_SUITE_data/results/inets index 24cb39e52b..773525eb7f 100644 --- a/lib/dialyzer/test/r9c_SUITE_data/results/inets +++ b/lib/dialyzer/test/r9c_SUITE_data/results/inets @@ -8,6 +8,7 @@ http_lib.erl:424: The variable _ can never match since previous clauses complete http_lib.erl:438: The variable _ can never match since previous clauses completely covered the type any() http_lib.erl:99: Function getHeaderValue/2 will never be called httpc_handler.erl:660: Function exit_session_ok/2 has no local return +httpc_handler.erl:676: Function format_time/0 will never be called httpc_manager.erl:145: The pattern {ErrorReply, State2} can never match the type {{'ok',number()},number(),#state{reqid::number()}} httpc_manager.erl:160: The pattern {ErrorReply, State2} can never match the type {{'ok',number()},number(),#state{reqid::number()}} httpc_manager.erl:478: The pattern {'error', Reason} can never match the type 'ok' | {number(),#session{clientclose::boolean(),pipeline::[],quelength::1}} diff --git a/lib/dialyzer/test/small_SUITE_data/results/cerl_hipeify b/lib/dialyzer/test/small_SUITE_data/results/cerl_hipeify index 87bf6f309f..06dc0d63ee 100644 --- a/lib/dialyzer/test/small_SUITE_data/results/cerl_hipeify +++ b/lib/dialyzer/test/small_SUITE_data/results/cerl_hipeify @@ -1,4 +1,4 @@ cerl_hipeify.erl:370: Function will never be called -cerl_hipeify.erl:370: Guard test fun((none()) -> none()) =:= F::{_,_,_} | {_,_,_,_} | {_,_,_,_,_} | {_,_,_,_,_,_} | {_,_,_,_,_,_,_} can never succeed +cerl_hipeify.erl:370: Guard test fun((none()) -> no_return()) =:= F::{_,_,_} | {_,_,_,_} | {_,_,_,_,_} | {_,_,_,_,_,_} | {_,_,_,_,_,_,_} can never succeed cerl_hipeify.erl:641: Function env__new_function_name/2 will never be called diff --git a/lib/dialyzer/test/small_SUITE_data/results/inf_loop2 b/lib/dialyzer/test/small_SUITE_data/results/inf_loop2 index 7e9972ad98..142e4b2c37 100644 --- a/lib/dialyzer/test/small_SUITE_data/results/inf_loop2 +++ b/lib/dialyzer/test/small_SUITE_data/results/inf_loop2 @@ -1,4 +1,4 @@ inf_loop2.erl:18: Function test/0 has no local return inf_loop2.erl:19: The call lists:reverse('gazonk') will never return since it differs in the 1st argument from the success typing arguments: ([any()]) -inf_loop2.erl:22: Function loop/0 has no local return +inf_loop2.erl:22: Function loop/0 will never be called diff --git a/lib/dialyzer/test/small_SUITE_data/results/no_local_return b/lib/dialyzer/test/small_SUITE_data/results/no_local_return new file mode 100644 index 0000000000..6ca1ed51d8 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/results/no_local_return @@ -0,0 +1,3 @@ + +no_local_return.erl:11: Function bar/1 will never be called +no_local_return.erl:8: Function foo/0 will never be called diff --git a/lib/dialyzer/test/small_SUITE_data/src/no_local_return.erl b/lib/dialyzer/test/small_SUITE_data/src/no_local_return.erl new file mode 100644 index 0000000000..4e1a0b015a --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/no_local_return.erl @@ -0,0 +1,12 @@ +-module(no_local_return). + +%% NOTE: No function is exported. Dialyzer produced a bogus +%% 'Function foo/0 has no local return' warning +%% when in fact typer was finding correct return values for both +%% these functions. + +foo() -> + bar(42). + +bar(X) -> + lists:duplicate(X, gazonk). diff --git a/lib/dialyzer/test/small_SUITE_data/src/on_load.erl b/lib/dialyzer/test/small_SUITE_data/src/on_load.erl new file mode 100644 index 0000000000..16533a9caa --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/on_load.erl @@ -0,0 +1,11 @@ +%%% This is to ensure that "on_load" functions are never reported as unused. + +-module(on_load). + +-export([foo/0]). + +-on_load(bar/0). + +foo() -> ok. + +bar() -> ok. diff --git a/lib/erl_docgen/src/docgen_edoc_xml_cb.erl b/lib/erl_docgen/src/docgen_edoc_xml_cb.erl index dc9bc565ee..20daae8215 100644 --- a/lib/erl_docgen/src/docgen_edoc_xml_cb.erl +++ b/lib/erl_docgen/src/docgen_edoc_xml_cb.erl @@ -187,6 +187,7 @@ chapter_title(#xmlElement{content=Es}) -> % name = h3 | h4 %% 8) <blockquote> contents may need to be made into paragraphs %% 9) <th> (table header) is not allowed - is replaced by %% <td><em>...</em></td>. +%% 10) <img src=""> is not allowed, replace with <image file=""> otp_xmlify([]) -> []; otp_xmlify(Es0) -> @@ -416,6 +417,9 @@ otp_xmlify_e(#xmlElement{name=tr} = E) -> otp_xmlify_e(#xmlElement{name=td} = E) -> Content = otp_xmlify_e(E#xmlElement.content), [E#xmlElement{content=Content}]; +otp_xmlify_e(#xmlElement{name=img} = E) -> % 10) + Content = otp_xmlify_e(E#xmlElement.content), + [otp_xmlify_img(E#xmlElement{ content = Content })]; otp_xmlify_e([E | Es]) -> otp_xmlify_e(E) ++ otp_xmlify_e(Es); otp_xmlify_e([]) -> @@ -634,6 +638,20 @@ otp_xmlify_table([#xmlElement{name=td, content=Content}|Es]) -> otp_xmlify_table([]) -> []. +%% otp_xmlify_img(E) -> Es. +%% Transforms a <img src=""> into <image file=""> +otp_xmlify_img(E0) -> + Attrs = lists:map( + fun(#xmlAttribute{ name = src, value = Path} = A) -> + V = otp_xmlify_a_fileref(Path,this), + A#xmlAttribute{ name = file, + value = V }; + (A) -> + A + end,E0#xmlElement.attributes), + E0#xmlElement{name = image, expanded_name = image, + attributes = Attrs}. + %%--Misc help functions used by otp_xmlify/1 et al--------------------- %% find_next(Tag, Es) -> {Es1, Es2} @@ -975,6 +993,8 @@ t_type([E=#xmlElement{name = atom}]) -> t_atom(E); t_type([E=#xmlElement{name = integer}]) -> t_integer(E); +t_type([E=#xmlElement{name = range}]) -> + t_range(E); t_type([E=#xmlElement{name = float}]) -> t_float(E); t_type([#xmlElement{name = nil}]) -> @@ -1001,6 +1021,9 @@ t_atom(E) -> t_integer(E) -> [get_attrval(value, E)]. +t_range(E) -> + [get_attrval(value, E)]. + t_float(E) -> [get_attrval(value, E)]. diff --git a/lib/hipe/Makefile b/lib/hipe/Makefile index 6682c9aac0..f2be75f0dd 100644 --- a/lib/hipe/Makefile +++ b/lib/hipe/Makefile @@ -37,8 +37,13 @@ else SUB_DIRECTORIES = $(ALWAYS_SUBDIRS) endif + include native.mk +ifndef EBIN +EBIN = ../ebin +endif + # # Default Subdir Targets # @@ -52,12 +57,20 @@ edocs: fi all-subdirs: - -for dir in $(SUB_DIRECTORIES); do \ - (cd $$dir; $(MAKE) $(MAKETARGET) EBIN=../ebin; cd ..); \ + for dir in $(SUB_DIRECTORIES); do \ + (cd $$dir; $(MAKE) $(MAKETARGET) EBIN=$(EBIN); cd ..); \ + done + +# distclean and realclean should clean the bootstrap files +all-subdirs-x: + for dir in $(SUB_DIRECTORIES); do \ + (cd $$dir; $(MAKE) $(MAKETARGET) EBIN=../boot_ebin; cd ..); \ done +clean: + $(MAKE) MAKETARGET="clean" all-subdirs all-subdirs-x distclean: - $(MAKE) MAKETARGET="distclean" all-subdirs + $(MAKE) MAKETARGET="distclean" all-subdirs all-subdirs-x realclean: - $(MAKE) MAKETARGET="realclean" all-subdirs + $(MAKE) MAKETARGET="realclean" all-subdirs all-subdirs-x diff --git a/lib/hipe/amd64/Makefile b/lib/hipe/amd64/Makefile index 58377e5349..397cc0539e 100644 --- a/lib/hipe/amd64/Makefile +++ b/lib/hipe/amd64/Makefile @@ -89,6 +89,9 @@ clean: rm -f $(TARGET_FILES) rm -f core +distclean: clean +realclean: clean + $(DOCS)/%.html:%.erl erl -noshell -run edoc_run file '"$<"' '[{dir, "$(DOCS)"}]' -s init stop diff --git a/lib/hipe/arm/Makefile b/lib/hipe/arm/Makefile index 3f60cd77cc..6187b7e925 100644 --- a/lib/hipe/arm/Makefile +++ b/lib/hipe/arm/Makefile @@ -90,6 +90,9 @@ clean: rm -f $(TARGET_FILES) rm -f core +distclean: clean +realclean: clean + $(DOCS)/%.html:%.erl erl -noshell -run edoc_run file '"$<"' '[{dir, "$(DOCS)"}]' -s init stop diff --git a/lib/hipe/boot_ebin/.gitignore b/lib/hipe/boot_ebin/.gitignore new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/lib/hipe/boot_ebin/.gitignore diff --git a/lib/hipe/cerl/Makefile b/lib/hipe/cerl/Makefile index 7fcc44d27d..d0a0ea1f59 100644 --- a/lib/hipe/cerl/Makefile +++ b/lib/hipe/cerl/Makefile @@ -82,6 +82,9 @@ clean: rm -f $(TARGET_FILES) rm -f core +distclean: clean +realclean: clean + $(DOCS)/%.html:%.erl erl -noshell -run edoc_run file '"$<"' '[{dir, "$(DOCS)"}]' -s init stop diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl index 620fed365e..65b9a057de 100644 --- a/lib/hipe/cerl/erl_types.erl +++ b/lib/hipe/cerl/erl_types.erl @@ -424,12 +424,7 @@ t_has_opaque_subtype(T) -> -spec t_opaque_structure(erl_type()) -> erl_type(). t_opaque_structure(?opaque(Elements)) -> - case ordsets:size(Elements) of - 1 -> - [#opaque{struct = Struct}] = ordsets:to_list(Elements), - Struct; - _ -> throw({error, "Unexpected multiple opaque types"}) - end. + t_sup([Struct || #opaque{struct = Struct} <- ordsets:to_list(Elements)]). -spec t_opaque_module(erl_type()) -> module(). @@ -688,9 +683,9 @@ t_solve_remote(?opaque(Set), ET, R, C) -> {NewList, RR} = opaques_solve_remote(List, ET, R, C), {?opaque(ordsets:from_list(NewList)), RR}; t_solve_remote(?tuple(?any, _, _) = T, _ET, _R, _C) -> {T, []}; -t_solve_remote(?tuple(Types, Arity, Tag), ET, R, C) -> +t_solve_remote(?tuple(Types, _Arity, _Tag), ET, R, C) -> {RL, RR} = list_solve_remote(Types, ET, R, C), - {?tuple(RL, Arity, Tag), RR}; + {t_tuple(RL), RR}; t_solve_remote(?tuple_set(Set), ET, R, C) -> {NewSet, RR} = tuples_solve_remote(Set, ET, R, C), {?tuple_set(NewSet), RR}; diff --git a/lib/hipe/doc/Makefile b/lib/hipe/doc/Makefile index cdf9c9c798..e28b16c12e 100644 --- a/lib/hipe/doc/Makefile +++ b/lib/hipe/doc/Makefile @@ -24,6 +24,9 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk clean: -rm -f *.html edoc-info stylesheet.css erlang.png +distclean: clean +realclean: clean + # ---------------------------------------------------- # Special Build Targets # ---------------------------------------------------- diff --git a/lib/hipe/doc/src/Makefile b/lib/hipe/doc/src/Makefile index d440178e4c..065854e8a7 100644 --- a/lib/hipe/doc/src/Makefile +++ b/lib/hipe/doc/src/Makefile @@ -97,6 +97,9 @@ clean clean_docs: rm -f $(TOP_PDF_FILE) $(TOP_PDF_FILE:%.pdf=%.fo) rm -f errs core *~ +distclean: clean +realclean: clean + # ---------------------------------------------------- # Release Target # ---------------------------------------------------- diff --git a/lib/hipe/flow/Makefile b/lib/hipe/flow/Makefile index bbe8ef8666..e8d570ac48 100644 --- a/lib/hipe/flow/Makefile +++ b/lib/hipe/flow/Makefile @@ -82,6 +82,9 @@ clean: rm -f $(TARGET_FILES) rm -f core +distclean: clean +realclean: clean + $(DOCS)/%.html:%.erl erl -noshell -run edoc_run file '"$<"' '[{dir, "$(DOCS)"}]' -s init stop diff --git a/lib/hipe/icode/Makefile b/lib/hipe/icode/Makefile index bd6436c8b3..e57daecfbc 100644 --- a/lib/hipe/icode/Makefile +++ b/lib/hipe/icode/Makefile @@ -100,6 +100,9 @@ clean: rm -f $(TARGET_FILES) rm -f core +distclean: clean +realclean: clean + $(DOCS)/%.html:%.erl erl -noshell -run edoc_run file '"$<"' '[{dir, "$(DOCS)"}]' -s init stop diff --git a/lib/hipe/main/Makefile b/lib/hipe/main/Makefile index a14c9c3ca4..d49dd6f424 100644 --- a/lib/hipe/main/Makefile +++ b/lib/hipe/main/Makefile @@ -93,6 +93,9 @@ clean: rm -f $(TARGET_FILES) $(DOC_FILES) $(HRL_FILES) rm -f core +distclean: clean +realclean: clean + $(DOCS)/%.html:%.erl erl -noshell -run edoc_run file '"$<"' '[{dir, "$(DOCS)"}]' -s init stop diff --git a/lib/hipe/native.mk b/lib/hipe/native.mk index 6f4602477b..738e78e556 100644 --- a/lib/hipe/native.mk +++ b/lib/hipe/native.mk @@ -1,5 +1,7 @@ -ifndef SECONDARY_BOOTSTRAP ifeq ($(NATIVE_LIBS_ENABLED),yes) +ifndef SECONDARY_BOOTSTRAP ERL_COMPILE_FLAGS += +native +else +EBIN = ../boot_ebin endif endif diff --git a/lib/hipe/opt/Makefile b/lib/hipe/opt/Makefile index 4596201801..8e244ab360 100644 --- a/lib/hipe/opt/Makefile +++ b/lib/hipe/opt/Makefile @@ -80,6 +80,9 @@ clean: rm -f $(TARGET_FILES) rm -f core +distclean: clean +realclean: clean + $(DOCS)/%.html:%.erl erl -noshell -run edoc_run file '"$<"' '[{dir, "$(DOCS)"}]' -s init stop diff --git a/lib/hipe/ppc/Makefile b/lib/hipe/ppc/Makefile index f24139e34b..83376e8d9d 100644 --- a/lib/hipe/ppc/Makefile +++ b/lib/hipe/ppc/Makefile @@ -92,6 +92,9 @@ clean: rm -f $(TARGET_FILES) rm -f core +distclean: clean +realclean: clean + $(DOCS)/%.html:%.erl erl -noshell -run edoc_run file '"$<"' '[{dir, "$(DOCS)"}]' -s init stop diff --git a/lib/hipe/regalloc/Makefile b/lib/hipe/regalloc/Makefile index 386f3589c6..c327b443b0 100644 --- a/lib/hipe/regalloc/Makefile +++ b/lib/hipe/regalloc/Makefile @@ -94,6 +94,9 @@ clean: rm -f $(TARGET_FILES) rm -f core +distclean: clean +realclean: clean + $(DOCS)/%.html:%.erl erl -noshell -run edoc_run file '"$<"' '[{dir, "$(DOCS)"}]' -s init stop diff --git a/lib/hipe/rtl/Makefile b/lib/hipe/rtl/Makefile index 48086ec79f..30026831b7 100644 --- a/lib/hipe/rtl/Makefile +++ b/lib/hipe/rtl/Makefile @@ -89,6 +89,9 @@ clean: rm -f $(TARGET_FILES) rm -f core erl_crash.dump +distclean: clean +realclean: clean + # ---------------------------------------------------- # Special Build Targets # ---------------------------------------------------- diff --git a/lib/hipe/sparc/Makefile b/lib/hipe/sparc/Makefile index f25212a89b..e3acecdcb8 100644 --- a/lib/hipe/sparc/Makefile +++ b/lib/hipe/sparc/Makefile @@ -92,6 +92,9 @@ clean: rm -f $(TARGET_FILES) rm -f core +distclean: clean +realclean: clean + $(DOCS)/%.html:%.erl erl -noshell -run edoc_run file '"$<"' '[{dir, "$(DOCS)"}]' -s init stop diff --git a/lib/hipe/util/Makefile b/lib/hipe/util/Makefile index 85719ec3d6..7d1a7c01c7 100644 --- a/lib/hipe/util/Makefile +++ b/lib/hipe/util/Makefile @@ -85,6 +85,9 @@ clean: rm -f $(TARGET_FILES) rm -f core +distclean: clean +realclean: clean + $(DOCS)/%.html:%.erl erl -noshell -run edoc_run file '"$<"' '[{dir, "$(DOCS)"}]' -s init stop diff --git a/lib/hipe/x86/Makefile b/lib/hipe/x86/Makefile index d7d0c7bf5a..aed757246f 100644 --- a/lib/hipe/x86/Makefile +++ b/lib/hipe/x86/Makefile @@ -100,6 +100,9 @@ clean: rm -f $(TARGET_FILES) rm -f core +distclean: clean +realclean: clean + $(DOCS)/%.html:%.erl erl -noshell -run edoc_run file '"$<"' '[{dir, "$(DOCS)"}]' -s init stop diff --git a/lib/ic/src/ic_noc.erl b/lib/ic/src/ic_noc.erl index d43d550a52..b3fa3ee96e 100644 --- a/lib/ic/src/ic_noc.erl +++ b/lib/ic/src/ic_noc.erl @@ -289,6 +289,9 @@ emit_serv_std(G, N, X) -> emit(Fd, "terminate(Reason, State) ->\n"), emit(Fd, " ~p:~p(Reason, State).\n", [Impl, terminate]), + nl(Fd), + emit(Fd, "code_change(_OldVsn, State, _Extra) ->\n"), + emit(Fd, " {ok, State}.\n"), nl(Fd), nl(Fd) end, Fd. @@ -304,13 +307,13 @@ gen_end_of_call(G, _N, _X) -> Fd = ic_genobj:stubfiled(G), nl(Fd), nl(Fd), ic_codegen:mcomment_light(Fd, ["Standard gen_server call handle"]), - emit(Fd, "handle_call(stop, From, State) ->\n"), + emit(Fd, "handle_call(stop, _From, State) ->\n"), emit(Fd, " {stop, normal, ok, State}"), case get_opt(G, serv_last_call) of exception -> emit(Fd, ";\n"), nl(Fd), - emit(Fd, "handle_call(Req, From, State) ->\n"), + emit(Fd, "handle_call(_Req, _From, State) ->\n"), emit(Fd, " {reply, ~p, State}.\n",[getCallErr()]); exit -> emit(Fd, ".\n"), @@ -335,7 +338,7 @@ gen_end_of_cast(G, _N, _X) -> exception -> emit(Fd, ";\n"), nl(Fd), - emit(Fd, "handle_cast(Req, State) ->\n"), + emit(Fd, "handle_cast(_Req, State) ->\n"), emit(Fd, " {reply, ~p, State}.\n",[getCastErr()]); exit -> emit(Fd, ".\n"), @@ -353,12 +356,13 @@ emit_skel_footer(G, N, X) -> Fd = ic_genobj:stubfiled(G), nl(Fd), nl(Fd), ic_codegen:mcomment_light(Fd, ["Standard gen_server handles"]), - emit(Fd, "handle_info(X, State) ->\n"), case use_impl_handle_info(G, N, X) of true -> + emit(Fd, "handle_info(X, State) ->\n"), emit(Fd, " ~p:handle_info(X, State).\n\n", [list_to_atom(ic_genobj:impl(G))]); false -> + emit(Fd, "handle_info(_X, State) ->\n"), emit(Fd, " {reply, ~p, State}.\n\n",[getInfoErr()]) end end, @@ -402,9 +406,8 @@ get_if_gen(G, N, X) -> [io_lib:format("Standard Operation: ~p", [Name])]), - emit(Fd, "handle_call({~s, ~p, []}, From, State) ->~n", + emit(Fd, "handle_call({_~s, ~p, []}, _From, State) ->~n", [mk_name(G, "Ref"), Name]), - emit(Fd, " {reply, ~p, State};~n", [IFC_TKS]), nl(Fd), ok; @@ -479,8 +482,8 @@ gen_head_special(G, N, X) when is_record(X, interface) -> nl(Fd), ic_codegen:comment(Fd, "gen server export stuff"), emit(Fd, "-behaviour(gen_server).\n"), - ic_codegen:export(Fd, [{init, 1}, {terminate, 2}, {handle_call, 3}, - {handle_cast, 2}, {handle_info, 2}]), + ic_codegen:export(Fd, [{init, 1}, {terminate, 2}, {code_change, 3}, + {handle_call, 3}, {handle_cast, 2}, {handle_info, 2}]), nl(Fd), nl(Fd), ic_codegen:mcomment(Fd, ["Object interface functions."]), nl(Fd), nl(Fd), nl(Fd) diff --git a/lib/ic/vsn.mk b/lib/ic/vsn.mk index e21fc8fbb2..fc1475974e 100644 --- a/lib/ic/vsn.mk +++ b/lib/ic/vsn.mk @@ -1 +1 @@ -IC_VSN = 4.2.29 +IC_VSN = 4.2.30 diff --git a/lib/kernel/doc/src/error_logger.xml b/lib/kernel/doc/src/error_logger.xml index 2d95f96ac7..95b23e4aef 100644 --- a/lib/kernel/doc/src/error_logger.xml +++ b/lib/kernel/doc/src/error_logger.xml @@ -49,7 +49,7 @@ that events are logged to file instead, or not logged at all, see <seealso marker="kernel_app">kernel(6)</seealso>.</p> <p>Also the SASL application, if started, adds its own event - handler, which by default writes supervisor-, crash- and progress + handler, which by default writes supervisor, crash and progress reports to tty. See <seealso marker="sasl:sasl_app">sasl(6)</seealso>.</p> <p>It is recommended that user defined applications should report diff --git a/lib/kernel/doc/src/gen_tcp.xml b/lib/kernel/doc/src/gen_tcp.xml index 8a5d40bb16..9f362841ce 100644 --- a/lib/kernel/doc/src/gen_tcp.xml +++ b/lib/kernel/doc/src/gen_tcp.xml @@ -235,7 +235,9 @@ do_recv(Sock, Bs) -> <p>Returns <c>{ok, <anno>Socket</anno>}</c> if a connection is established, or <c>{error, closed}</c> if <c><anno>ListenSocket</anno></c> is closed, or <c>{error, timeout}</c> if no connection is established - within the specified time. May also return a POSIX error + within the specified time, + or <c>{error, system_limit}</c> if all available ports in the + Erlang emulator are in use. May also return a POSIX error value if something else goes wrong, see inet(3) for possible error values.</p> <p>Packets can be sent to the returned socket <c><anno>Socket</anno></c> diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml index 1a05b4ba99..86950b3ecc 100644 --- a/lib/kernel/doc/src/inet.xml +++ b/lib/kernel/doc/src/inet.xml @@ -149,7 +149,7 @@ fe80::204:acff:fe17:bf38 <fsummary>Return a descriptive string for an error reason</fsummary> <desc> <p>Returns a diagnostic error string. See the section below - for possible <c><anno>Posix</anno></c> values and the corresponding + for possible Posix values and the corresponding strings.</p> </desc> </func> diff --git a/lib/kernel/doc/src/kernel_app.xml b/lib/kernel/doc/src/kernel_app.xml index 0f71a4f0f2..63fdc223f4 100644 --- a/lib/kernel/doc/src/kernel_app.xml +++ b/lib/kernel/doc/src/kernel_app.xml @@ -104,7 +104,7 @@ that node. <c>Value</c> is one of:</p> <taglist> <tag><c>never</c></tag> - <item>Connections are never automatically connected, they + <item>Connections are never automatically established, they must be explicitly connected. See <c>net_kernel(3)</c>.</item> <tag><c>once</c></tag> <item>Connections will be established automatically, but only diff --git a/lib/kernel/src/auth.erl b/lib/kernel/src/auth.erl index c329a5652a..252c20ac4e 100644 --- a/lib/kernel/src/auth.erl +++ b/lib/kernel/src/auth.erl @@ -381,13 +381,17 @@ create_cookie(Name) -> case {R1, R2} of {ok, ok} -> ok; - {{error,_Reason}, _} -> - {error, "Failed to create cookie file"}; + {{error,Reason}, _} -> + {error, + lists:flatten( + io_lib:format("Failed to write to cookie file '~s': ~p", [Name, Reason]))}; {ok, {error, Reason}} -> {error, "Failed to change mode: " ++ atom_to_list(Reason)} end; - {error,_Reason} -> - {error, "Failed to create cookie file"} + {error,Reason} -> + {error, + lists:flatten( + io_lib:format("Failed to create cookie file '~s': ~p", [Name, Reason]))} end. random_cookie(0, _, Result) -> diff --git a/lib/kernel/src/disk_log.erl b/lib/kernel/src/disk_log.erl index fb9415d440..f5f972c112 100644 --- a/lib/kernel/src/disk_log.erl +++ b/lib/kernel/src/disk_log.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2011. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -1034,10 +1034,9 @@ sync_loop(From, S) -> -define(MAX_LOOK_AHEAD, 64*1024). %% Inlined. -log_loop(S, Pids, _Bins, _Sync, _Sz) when S#state.cache_error =/= ok -> +log_loop(#state{cache_error = CE}=S, Pids, _Bins, _Sync, _Sz) when CE =/= ok -> loop(cache_error(S, Pids)); -log_loop(#state{messages = []}=S, Pids, Bins, Sync, Sz) - when Sz > ?MAX_LOOK_AHEAD -> +log_loop(#state{}=S, Pids, Bins, Sync, Sz) when Sz > ?MAX_LOOK_AHEAD -> loop(log_end(S, Pids, Bins, Sync)); log_loop(#state{messages = []}=S, Pids, Bins, Sync, Sz) -> receive @@ -1046,8 +1045,7 @@ log_loop(#state{messages = []}=S, Pids, Bins, Sync, Sz) -> after 0 -> loop(log_end(S, Pids, Bins, Sync)) end; -log_loop(S, Pids, Bins, Sync, Sz) -> - [M | Ms] = S#state.messages, +log_loop(#state{messages = [M | Ms]}=S, Pids, Bins, Sync, Sz) -> S1 = S#state{messages = Ms}, log_loop(M, Pids, Bins, Sync, Sz, S1, get(log)). diff --git a/lib/kernel/src/erts_debug.erl b/lib/kernel/src/erts_debug.erl index 7d6a5ade94..16a773898d 100644 --- a/lib/kernel/src/erts_debug.erl +++ b/lib/kernel/src/erts_debug.erl @@ -53,6 +53,11 @@ size(Tuple, Seen0, Sum0) when is_tuple(Tuple) -> Sum = Sum0 + 1 + tuple_size(Tuple), tuple_size(1, tuple_size(Tuple), Tuple, Seen, Sum) end; +size(Fun, Seen0, Sum) when is_function(Fun) -> + case remember_term(Fun, Seen0) of + seen -> {Sum,Seen0}; + Seen -> fun_size(Fun, Seen, Sum) + end; size(Term, Seen0, Sum) -> case erts_debug:flat_size(Term) of 0 -> {Sum,Seen0}; @@ -68,6 +73,21 @@ tuple_size(I, Sz, _, Seen, Sum) when I > Sz -> tuple_size(I, Sz, Tuple, Seen0, Sum0) -> {Sum,Seen} = size(element(I, Tuple), Seen0, Sum0), tuple_size(I+1, Sz, Tuple, Seen, Sum). + +fun_size(Fun, Seen, Sum) -> + case erlang:fun_info(Fun, type) of + {type,external} -> + {Sum + erts_debug:flat_size(Fun),Seen}; + {type,local} -> + Sz = erts_debug:flat_size(fun() -> ok end), + {env,Env} = erlang:fun_info(Fun, env), + fun_size_1(Env, Seen, Sum+Sz+length(Env)) + end. + +fun_size_1([H|T], Seen0, Sum0) -> + {Sum,Seen} = size(H, Seen0, Sum0), + fun_size_1(T, Seen, Sum); +fun_size_1([], Seen, Sum) -> {Sum,Seen}. remember_term(Term, Seen) -> case gb_trees:lookup(Term, Seen) of diff --git a/lib/kernel/src/gen_tcp.erl b/lib/kernel/src/gen_tcp.erl index 4d6c7f5f1d..56d0451e44 100644 --- a/lib/kernel/src/gen_tcp.erl +++ b/lib/kernel/src/gen_tcp.erl @@ -175,7 +175,7 @@ try_connect([], _Port, _Opts, _Timer, _Mod, Err) -> Port :: inet:port_number(), Options :: [listen_option()], ListenSocket :: socket(), - Reason :: inet:posix(). + Reason :: system_limit | inet:posix(). listen(Port, Opts) -> Mod = mod(Opts, undefined), @@ -194,7 +194,7 @@ listen(Port, Opts) -> -spec accept(ListenSocket) -> {ok, Socket} | {error, Reason} when ListenSocket :: socket(), Socket :: socket(), - Reason :: closed | timeout | inet:posix(). + Reason :: closed | timeout | system_limit | inet:posix(). accept(S) -> case inet_db:lookup_socket(S) of @@ -208,7 +208,7 @@ accept(S) -> ListenSocket :: socket(), Timeout :: timeout(), Socket :: socket(), - Reason :: closed | timeout | inet:posix(). + Reason :: closed | timeout | system_limit | inet:posix(). accept(S, Time) when is_port(S) -> case inet_db:lookup_socket(S) of diff --git a/lib/kernel/src/global.erl b/lib/kernel/src/global.erl index fa97614eca..7da33859bf 100644 --- a/lib/kernel/src/global.erl +++ b/lib/kernel/src/global.erl @@ -280,13 +280,13 @@ unregister_name(Name) -> gen_server:call(global_name_server, {registrar, Fun}, infinity) end. --spec re_register_name(Name, Pid) -> _ when +-spec re_register_name(Name, Pid) -> 'yes' when Name :: term(), Pid :: pid(). re_register_name(Name, Pid) when is_pid(Pid) -> re_register_name(Name, Pid, fun random_exit_name/3). --spec re_register_name(Name, Pid, Resolve) -> _ when +-spec re_register_name(Name, Pid, Resolve) -> 'yes' when Name :: term(), Pid :: pid(), Resolve :: method(). @@ -1965,7 +1965,7 @@ resolve_it(Method, Name, Pid1, Pid2) -> minmax(P1,P2) -> if node(P1) < node(P2) -> {P1, P2}; true -> {P2, P1} end. --spec random_exit_name(Name, Pid1, Pid2) -> 'none' when +-spec random_exit_name(Name, Pid1, Pid2) -> pid() when Name :: term(), Pid1 :: pid(), Pid2 :: pid(). @@ -1976,7 +1976,7 @@ random_exit_name(Name, Pid, Pid2) -> exit(Max, kill), Min. --spec random_notify_name(Name, Pid1, Pid2) -> 'none' when +-spec random_notify_name(Name, Pid1, Pid2) -> pid() when Name :: term(), Pid1 :: pid(), Pid2 :: pid(). @@ -2175,7 +2175,7 @@ get_own_nodes() -> start_the_registrar() -> spawn_link(fun() -> loop_the_registrar() end). - + loop_the_registrar() -> receive {trans_all_known, Fun, From} -> diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl index 49f64a9236..4de3c1c6b1 100644 --- a/lib/kernel/src/inet.erl +++ b/lib/kernel/src/inet.erl @@ -1218,11 +1218,13 @@ port_list(Name) -> %% utils %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec format_error(Posix) -> string() when - Posix :: posix(). +-spec format_error(Reason) -> string() when + Reason :: posix() | system_limit. format_error(exbadport) -> "invalid port state"; format_error(exbadseq) -> "bad command sequence"; +format_error(system_limit) -> + "a system limit was hit, probably not enough ports"; format_error(Tag) -> erl_posix_msg:message(Tag). diff --git a/lib/kernel/test/gen_tcp_misc_SUITE.erl b/lib/kernel/test/gen_tcp_misc_SUITE.erl index 3da4b07c05..d9bba0dbb0 100644 --- a/lib/kernel/test/gen_tcp_misc_SUITE.erl +++ b/lib/kernel/test/gen_tcp_misc_SUITE.erl @@ -39,7 +39,8 @@ accept_timeouts_in_order/1,accept_timeouts_in_order2/1, accept_timeouts_in_order3/1,accept_timeouts_mixed/1, killing_acceptor/1,killing_multi_acceptors/1,killing_multi_acceptors2/1, - several_accepts_in_one_go/1,active_once_closed/1, send_timeout/1, send_timeout_active/1, + several_accepts_in_one_go/1, accept_system_limit/1, + active_once_closed/1, send_timeout/1, send_timeout_active/1, otp_7731/1, zombie_sockets/1, otp_7816/1, otp_8102/1, otp_9389/1]). @@ -71,7 +72,7 @@ all() -> accept_timeouts_in_order, accept_timeouts_in_order2, accept_timeouts_in_order3, accept_timeouts_mixed, killing_acceptor, killing_multi_acceptors, - killing_multi_acceptors2, several_accepts_in_one_go, + killing_multi_acceptors2, several_accepts_in_one_go, accept_system_limit, active_once_closed, send_timeout, send_timeout_active, otp_7731, zombie_sockets, otp_7816, otp_8102, otp_9389]. @@ -1837,6 +1838,54 @@ wait_until_accepting(Proc,N) -> end. +accept_system_limit(suite) -> + []; +accept_system_limit(doc) -> + ["Check that accept returns {error, system_limit} " + "(and not {error, enfile}) when running out of ports"]; +accept_system_limit(Config) when is_list(Config) -> + ?line {ok, LS} = gen_tcp:listen(0, []), + ?line {ok, TcpPort} = inet:port(LS), + ?line Connector = spawn_link(fun () -> connector(TcpPort) end), + ?line ok = acceptor(LS, false, []), + ?line Connector ! stop, + ok. + +acceptor(LS, GotSL, A) -> + case gen_tcp:accept(LS, 1000) of + {ok, S} -> + acceptor(LS, GotSL, [S|A]); + {error, system_limit} -> + acceptor(LS, true, A); + {error, timeout} when GotSL -> + ok; + {error, timeout} -> + error + end. + +connector(TcpPort) -> + ManyPorts = open_ports([]), + ConnF = fun (Port) -> + case catch gen_tcp:connect({127,0,0,1}, TcpPort, []) of + {ok, Sock} -> + Sock; + _Error -> + port_close(Port) + end + end, + R = [ConnF(Port) || Port <- lists:sublist(ManyPorts, 10)], + receive stop -> R end. + +open_ports(L) -> + case catch open_port({spawn_driver, "ram_file_drv"}, []) of + Port when is_port(Port) -> + open_ports([Port|L]); + {'EXIT', {system_limit, _}} -> + {L1, L2} = lists:split(5, L), + [port_close(Port) || Port <- L1], + L2 + end. + active_once_closed(suite) -> []; diff --git a/lib/kernel/test/sendfile_SUITE.erl b/lib/kernel/test/sendfile_SUITE.erl index 6d0848ee05..03704b0c04 100644 --- a/lib/kernel/test/sendfile_SUITE.erl +++ b/lib/kernel/test/sendfile_SUITE.erl @@ -26,7 +26,9 @@ all() -> [t_sendfile_small - ,t_sendfile_big + ,t_sendfile_big_all + ,t_sendfile_big_size + ,t_sendfile_many_small ,t_sendfile_partial ,t_sendfile_offset ,t_sendfile_sendafter @@ -38,20 +40,25 @@ all() -> ]. init_per_suite(Config) -> - Priv = ?config(priv_dir, Config), - SFilename = filename:join(Priv, "sendfile_small.html"), - {ok, DS} = file:open(SFilename,[write,raw]), - file:write(DS,"yo baby yo"), - file:sync(DS), - file:close(DS), - BFilename = filename:join(Priv, "sendfile_big.html"), - {ok, DB} = file:open(BFilename,[write,raw]), - [file:write(DB,[<<0:(10*8*1024*1024)>>]) || _I <- lists:seq(1,51)], - file:sync(DB), - file:close(DB), - [{small_file, SFilename}, - {file_opts,[raw,binary]}, - {big_file, BFilename}|Config]. + case {os:type(),os:version()} of + {{unix,sunos}, {5,8,_}} -> + {skip, "Solaris 8 not supported for now"}; + _ -> + Priv = ?config(priv_dir, Config), + SFilename = filename:join(Priv, "sendfile_small.html"), + {ok, DS} = file:open(SFilename,[write,raw]), + file:write(DS,"yo baby yo"), + file:sync(DS), + file:close(DS), + BFilename = filename:join(Priv, "sendfile_big.html"), + {ok, DB} = file:open(BFilename,[write,raw]), + [file:write(DB,[<<0:(10*8*1024*1024)>>]) || _I <- lists:seq(1,51)], + file:sync(DB), + file:close(DB), + [{small_file, SFilename}, + {file_opts,[raw,binary]}, + {big_file, BFilename}|Config] + end. end_per_suite(Config) -> file:delete(proplists:get_value(big_file, Config)). @@ -91,7 +98,34 @@ t_sendfile_small(Config) when is_list(Config) -> ok = sendfile_send(Send). -t_sendfile_big(Config) when is_list(Config) -> +t_sendfile_many_small(Config) when is_list(Config) -> + Filename = proplists:get_value(small_file, Config), + FileOpts = proplists:get_value(file_opts, Config, []), + + error_logger:add_report_handler(?MODULE,[self()]), + + Send = fun(Sock) -> + {Size,_} = sendfile_file_info(Filename), + N = 10000, + {ok,D} = file:open(Filename,[read|FileOpts]), + [begin + {ok,Size} = file:sendfile(D,Sock,0,0,[]) + end || _I <- lists:seq(1,N)], + file:close(D), + Size*N + end, + + ok = sendfile_send({127,0,0,1}, Send, 0), + + receive + {stolen,Reason} -> + exit(Reason) + after 200 -> + ok + end. + + +t_sendfile_big_all(Config) when is_list(Config) -> Filename = proplists:get_value(big_file, Config), Send = fun(Sock) -> @@ -103,6 +137,20 @@ t_sendfile_big(Config) when is_list(Config) -> ok = sendfile_send({127,0,0,1}, Send, 0). +t_sendfile_big_size(Config) -> + Filename = proplists:get_value(big_file, Config), + FileOpts = proplists:get_value(file_opts, Config, []), + + SendAll = fun(Sock) -> + {ok, #file_info{size = Size}} = + file:read_file_info(Filename), + {ok,D} = file:open(Filename,[read|FileOpts]), + {ok, Size} = file:sendfile(D, Sock,0,Size,[]), + Size + end, + + ok = sendfile_send({127,0,0,1}, SendAll, 0). + t_sendfile_partial(Config) -> Filename = proplists:get_value(small_file, Config), FileOpts = proplists:get_value(file_opts, Config, []), @@ -310,6 +358,10 @@ sendfile_server(ClientPid, Orig) -> -define(SENDFILE_TIMEOUT, 10000). sendfile_do_recv(Sock, Bs) -> + TimeoutMul = case os:type() of + {win32, _} -> 6; + _ -> 1 + end, receive stop when Bs /= 0,is_integer(Bs) -> gen_tcp:close(Sock), @@ -333,7 +385,7 @@ sendfile_do_recv(Sock, Bs) -> {tcp_closed, Sock} when is_integer(Bs) -> ct:log("Stopped due to close"), {ok, Bs} - after ?SENDFILE_TIMEOUT -> + after ?SENDFILE_TIMEOUT * TimeoutMul -> ct:log("Sendfile timeout"), timeout end. diff --git a/lib/kernel/test/zlib_SUITE.erl b/lib/kernel/test/zlib_SUITE.erl index 74bafe8935..e0fd0f5d19 100644 --- a/lib/kernel/test/zlib_SUITE.erl +++ b/lib/kernel/test/zlib_SUITE.erl @@ -73,6 +73,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. all() -> [{group, api}, {group, examples}, {group, func}, smp, + otp_9981, otp_7359]. groups() -> @@ -964,6 +965,24 @@ otp_7359_def_inf(Data,{DefSize,InfSize}) -> ?line ok = zlib:close(ZInf), ok. +otp_9981(Config) when is_list(Config) -> + Ports = lists:sort(erlang:ports()), + Invalid = <<"My invalid data">>, + catch zlib:compress(invalid), + Ports = lists:sort(erlang:ports()), + catch zlib:uncompress(Invalid), + Ports = lists:sort(erlang:ports()), + catch zlib:zip(invalid), + Ports = lists:sort(erlang:ports()), + catch zlib:unzip(Invalid), + Ports = lists:sort(erlang:ports()), + catch zlib:gzip(invalid), + Ports = lists:sort(erlang:ports()), + catch zlib:gunzip(Invalid), + Ports = lists:sort(erlang:ports()), + ok. + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% Helps with testing directly %%%%%%%%%%%%% diff --git a/lib/megaco/doc/src/notes.xml b/lib/megaco/doc/src/notes.xml index d9c575885f..393064fbb5 100644 --- a/lib/megaco/doc/src/notes.xml +++ b/lib/megaco/doc/src/notes.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2000</year><year>2011</year> + <year>2000</year><year>2012</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -36,6 +36,75 @@ section is the version number of Megaco.</p> + <section><title>Megaco 3.16.0.1</title> + + <p>Version 3.16.0.1 supports code replacement in runtime from/to + version 3.16, 3.15.1.1, 3.15.1 and 3.15.</p> + + <section> + <title>Improvements and new features</title> + +<!-- + <p>-</p> +--> + + <list type="bulleted"> + <item> + <p>Fixed some faulty test cases. </p> +<!-- + <p>Own Id: OTP-9795</p> +--> + </item> + + <item> + <p>Removed use of deprecated system flag, + <c>scheduler_bind_type</c>, in the measurement tool + <c>mstone1</c>. </p> + <p>Own Id: OTP-9949</p> + </item> + + </list> + + </section> + + <section> + <title>Fixed bugs and malfunctions</title> + + <p>-</p> + + <!-- + <list type="bulleted"> + <item> + <p>Fixing miscellaneous things detected by dialyzer. </p> + <p>Own Id: OTP-9075</p> + </item> + + </list> + --> + + </section> + + <section> + <title>Incompatibilities</title> + <p>-</p> + +<!-- + <list type="bulleted"> + <item> + <p>Due to the change in the flex driver API, + we may no longer be able to build and/or use + the flex driver without reentrant support. </p> + <p>Own Id: OTP-9795</p> + </item> + + </list> +--> + + </section> + + </section> <!-- 3.16.0.1 --> + + <section><title>Megaco 3.16</title> <p>Version 3.16 supports code replacement in runtime from/to @@ -50,7 +119,7 @@ <list type="bulleted"> <item> - <p>Minor improvemnts to the emasurement tool mstone1. </p> + <p>Minor improvements to the measurement tool <c>mstone1</c>. </p> <p>Own Id: OTP-9604</p> </item> diff --git a/lib/megaco/examples/meas/meas.sh.skel.src b/lib/megaco/examples/meas/meas.sh.skel.src index c7bd6cdd2a..ecf463b9c6 100644 --- a/lib/megaco/examples/meas/meas.sh.skel.src +++ b/lib/megaco/examples/meas/meas.sh.skel.src @@ -2,7 +2,7 @@ # %CopyrightBegin% # -# Copyright Ericsson AB 2007-2011. All Rights Reserved. +# Copyright Ericsson AB 2007-2012. All Rights Reserved. # # The contents of this file are subject to the Erlang Public License, # Version 1.1, (the "License"); you may not use this file except in @@ -32,6 +32,7 @@ STOP="-s init stop" ERL="erl \ -noshell \ + +sbt tnnps \ -pa $MEAS_HOME \ $MEAS_DEFAULT \ $STOP" diff --git a/lib/megaco/examples/meas/megaco_codec_mstone1.erl b/lib/megaco/examples/meas/megaco_codec_mstone1.erl index 9ab7822df8..2133cd633c 100644 --- a/lib/megaco/examples/meas/megaco_codec_mstone1.erl +++ b/lib/megaco/examples/meas/megaco_codec_mstone1.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2009. All Rights Reserved. +%% Copyright Ericsson AB 2005-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -191,7 +191,6 @@ mstone_init(MessagePackage, Factor, Codecs, DrvInclude) -> do_mstone(MessagePackage, Factor, Codecs, DrvInclude) -> io:format("~n", []), - ?LIB:set_default_sched_bind(), ?LIB:display_os_info(), ?LIB:display_system_info(), ?LIB:display_app_info(), diff --git a/lib/megaco/examples/meas/megaco_codec_mstone2.erl b/lib/megaco/examples/meas/megaco_codec_mstone2.erl index f3588f2e3d..54b889345f 100644 --- a/lib/megaco/examples/meas/megaco_codec_mstone2.erl +++ b/lib/megaco/examples/meas/megaco_codec_mstone2.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2009. All Rights Reserved. +%% Copyright Ericsson AB 2006-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -40,7 +40,7 @@ %% When the finished timer expires, it will stop respawing %% the worker processes, and instead just wait for them all %% to finish. -%% The test is finished by printing the statistics. +%% The test is finishes by printing the statistics. %% - A worker process for each codec combination. %% This process is spawned by the loader process. It receives %% at start a list of messages. It shall decode and then @@ -162,7 +162,6 @@ parse_message_package(BadMessagePackage) -> mstone_init(MessagePackage, DrvInclude) -> io:format("~n", []), - ?LIB:set_default_sched_bind(), ?LIB:display_os_info(), ?LIB:display_system_info(), ?LIB:display_app_info(), diff --git a/lib/megaco/examples/meas/megaco_codec_mstone_lib.erl b/lib/megaco/examples/meas/megaco_codec_mstone_lib.erl index 040af9826b..ca8016d65f 100644 --- a/lib/megaco/examples/meas/megaco_codec_mstone_lib.erl +++ b/lib/megaco/examples/meas/megaco_codec_mstone_lib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2010. All Rights Reserved. +%% Copyright Ericsson AB 2006-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -30,7 +30,6 @@ -compile({no_auto_import,[error/1]}). -export([start_flex_scanner/0, stop_flex_scanner/1, expanded_messages/2, expanded_messages/3, - set_default_sched_bind/0, display_os_info/0, display_system_info/0, display_alloc_info/0, @@ -70,16 +69,6 @@ detect_version(Codec, Conf, Bin) -> %%---------------------------------------------------------------------- %% -%% S c h e d u l e r b i n d t y p e -%% -%%---------------------------------------------------------------------- - -set_default_sched_bind() -> - (catch erlang:system_flag(scheduler_bind_type, default_bind)). - - -%%---------------------------------------------------------------------- -%% %% D i s p l a y O s I n f o %% %%---------------------------------------------------------------------- diff --git a/lib/megaco/examples/meas/mstone1.sh.skel.src b/lib/megaco/examples/meas/mstone1.sh.skel.src index 54a6c61a58..b1935acef6 100644 --- a/lib/megaco/examples/meas/mstone1.sh.skel.src +++ b/lib/megaco/examples/meas/mstone1.sh.skel.src @@ -3,7 +3,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2007-2011. All Rights Reserved. +# Copyright Ericsson AB 2007-2012. All Rights Reserved. # # The contents of this file are subject to the Erlang Public License, # Version 1.1, (the "License"); you may not use this file except in @@ -55,6 +55,15 @@ Options: flex scanner will be used nd - only codec config(s) without drivers will be used od - only codec config(s) with drivers will be used + -sbt <bind-type> Set scheduler bind type. See erl man page for more info. + tnnps - Thread no node processor spread (default) + u - Unbound + ns - No spread + ts - Thread spread + ps - Processor spread + s - Spread + nnts - No node thread spread + nnps - No node processor spread -- everything after this is just passed on to erl. " @@ -67,6 +76,7 @@ MODULE=megaco_codec_mstone1 STARTF="start" FACTOR="" MSG_PACK=time_test +SBT="+sbt tnnps" while test $# != 0; do # echo "DBG: Value = $1" @@ -107,6 +117,17 @@ while test $# != 0; do exit 0 esac;; + -sbt) + case $2 in + tnnps|u|ns|ts|ps|s|nnts|nnps) + SBT="+sbt $2"; + shift ; shift ;; + *) + echo "unknown scheduler bind type: $2"; + echo "$usage" ; + exit 0 + esac;; + -f) if [ "x$SCHED" != "x" ]; then echo "option(s) -s and -f cannot both be given" ; @@ -177,6 +198,7 @@ if [ $TYPE = factor ]; then ERL="erl \ -noshell \ + $SBT \ $PHS \ $ATP \ $SMP_OPTS \ @@ -218,6 +240,7 @@ elif [ $TYPE = sched ]; then ERL="erl \ -noshell \ + $SBT \ $PHS \ $ATP \ $SMP_OPTS \ diff --git a/lib/megaco/src/app/megaco.appup.src b/lib/megaco/src/app/megaco.appup.src index 3c9740818a..7f89fa8bc2 100644 --- a/lib/megaco/src/app/megaco.appup.src +++ b/lib/megaco/src/app/megaco.appup.src @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2011. All Rights Reserved. +%% Copyright Ericsson AB 2001-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -142,10 +142,17 @@ %% | %% v %% 3.16 +%% | +%% v +%% 3.16.0.1 %% %% {"%VSN%", [ + {"3.16", + [ + ] + }, {"3.15.1.1", [ {restart_application, megaco} @@ -163,6 +170,10 @@ } ], [ + {"3.16", + [ + ] + }, {"3.15.1.1", [ {restart_application, megaco} diff --git a/lib/megaco/test/megaco_mess_test.erl b/lib/megaco/test/megaco_mess_test.erl index 8bafab1aba..663ac8c329 100644 --- a/lib/megaco/test/megaco_mess_test.erl +++ b/lib/megaco/test/megaco_mess_test.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2011. All Rights Reserved. +%% Copyright Ericsson AB 1999-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -324,9 +324,6 @@ min(M) -> timer:minutes(M). %% Test server callbacks -% init_per_testcase(pending_ack = Case, Config) -> -% put(dbg,true), -% megaco_test_lib:init_per_testcase(Case, Config); init_per_testcase(otp_7189 = Case, Config) -> C = lists:keydelete(tc_timeout, 1, Config), megaco_test_lib:init_per_testcase(Case, [{tc_timeout, min(2)} |C]); @@ -337,9 +334,6 @@ init_per_testcase(Case, Config) -> C = lists:keydelete(tc_timeout, 1, Config), megaco_test_lib:init_per_testcase(Case, [{tc_timeout, min(1)} |C]). -% end_per_testcase(pending_ack = Case, Config) -> -% erase(dbg), -% megaco_test_lib:end_per_testcase(Case, Config); end_per_testcase(Case, Config) -> megaco_test_lib:end_per_testcase(Case, Config). @@ -434,6 +428,7 @@ connect(suite) -> connect(doc) -> []; connect(Config) when is_list(Config) -> + %% ?SKIP("Needs a re-write..."), ?ACQUIRE_NODES(1, Config), PrelMid = preliminary_mid, MgMid = ipv4_mid(4711), @@ -457,16 +452,25 @@ connect(Config) when is_list(Config) -> ?VERIFY(bad_send_mod, megaco:conn_info(PrelCH, send_mod)), SC = service_change_request(), case megaco:call(PrelCH, [SC], []) of - {error, - {send_message_failed, - {'EXIT', {undef, [{bad_send_mod, send_message, [sh, _]} | _]}}}} -> + {_Version, + {error, + {send_message_failed, + {'EXIT', {undef, [{bad_send_mod, send_message, [sh, _]} | _]}}}} + } -> + %% R14B and previous + ?LOG("expected send failure (1)", []), ok; %% As of R15, we also get some extra info (e.g. line numbers) - {error, - {send_message_failed, - {'EXIT', {undef, [{bad_send_mod, send_message, [sh, _], _} | _]}}}} -> + {_Version, + {error, + {send_message_failed, + {'EXIT', {undef, [{bad_send_mod, send_message, [sh, _], _} | _]}}}} + } -> + %% R15B and later + ?LOG("expected send failure (2)", []), ok; + Unexpected -> ?ERROR(Unexpected) end, diff --git a/lib/megaco/vsn.mk b/lib/megaco/vsn.mk index bb6f5f554a..11a951a23e 100644 --- a/lib/megaco/vsn.mk +++ b/lib/megaco/vsn.mk @@ -2,7 +2,7 @@ # %CopyrightBegin% # -# Copyright Ericsson AB 1997-2011. All Rights Reserved. +# Copyright Ericsson AB 1997-2012. All Rights Reserved. # # The contents of this file are subject to the Erlang Public License, # Version 1.1, (the "License"); you may not use this file except in @@ -18,6 +18,6 @@ # %CopyrightEnd% APPLICATION = megaco -MEGACO_VSN = 3.16 +MEGACO_VSN = 3.16.0.1 PRE_VSN = APP_VSN = "$(APPLICATION)-$(MEGACO_VSN)$(PRE_VSN)" diff --git a/lib/observer/doc/src/etop.xml b/lib/observer/doc/src/etop.xml index 78047caab3..4eb5603549 100644 --- a/lib/observer/doc/src/etop.xml +++ b/lib/observer/doc/src/etop.xml @@ -114,6 +114,37 @@ Default: <c>on</c></item> </description> <funcs> <func> + <name>start() -> ok</name> + <fsummary>Start etop</fsummary> + <desc> + <p>This function starts <c>etop</c>. + Note that etop is preferably started with the etop and getop scripts</p> + </desc> + </func> + <func> + <name>start(Options) -> ok</name> + <fsummary>Start etop</fsummary> + <type> + <v>Options = [Option]</v> + <v>Option = {Key, Value}</v> + <v>Key = atom()</v> + <v>Value = term()</v> + </type> + <desc> + <p>This function starts <c>etop</c>. Use + <seealso marker="#help/0">help/0</seealso> to see a + description of the possible options.</p> + </desc> + </func> + <func> + <name>help() -> ok</name> + <fsummary>Print etop's help</fsummary> + <desc> + <p>This function prints the help of <c>etop</c> and + its options.</p> + </desc> + </func> + <func> <name>config(Key,Value) -> Result</name> <fsummary>Change tool's configuration</fsummary> <type> diff --git a/lib/observer/src/etop.erl b/lib/observer/src/etop.erl index 0bf1d68534..7ec0fedbb2 100644 --- a/lib/observer/src/etop.erl +++ b/lib/observer/src/etop.erl @@ -31,9 +31,9 @@ help() -> io:format( - "Usage of the erlang top program~n" - "Options are set as command line parameters as in -node a@host -..~n" - "or as parameter to etop:start([{node, a@host}, {...}])~n" + "Usage of the Erlang top program~n~n" + "Options are set as command line parameters as in -node my@host~n" + "or as parameters to etop:start([{node, my@host}, {...}]).~n~n" "Options are:~n" " node atom Required The erlang node to measure ~n" " port integer The used port, NOTE: due to a bug this program~n" diff --git a/lib/snmp/doc/src/notes.xml b/lib/snmp/doc/src/notes.xml index 704ff0a20f..2d045faa0f 100644 --- a/lib/snmp/doc/src/notes.xml +++ b/lib/snmp/doc/src/notes.xml @@ -34,6 +34,88 @@ <section> + <title>SNMP Development Toolkit 4.22</title> + <p>Version 4.22 supports code replacement in runtime from/to + version 4.21.7 4.21.6 4.21.5, 4.21.4, 4.21.3, 4.21.2, 4.21.1 and 4.21. </p> + + <section> + <title>Improvements and new features</title> +<!-- + <p>-</p> +--> + + <list type="bulleted"> + <item> + <p>[compiler] The table information the MIB compiler provides with + augmented tables has been extended with <c>nbr_of_cols</c>, + <c>first_accessible</c> and <c>not_accessible</c>. </p> + <p>Own Id: OTP-9969</p> + </item> + + <item> + <p>Added the <c>log_to_io</c> audit-trail-log converter function + to the api modules of both the + <seealso marker="snmpm#log_to_io">manager</seealso> + and + <seealso marker="snmpa#log_to_io">agent</seealso>. </p> + <p>Own Id: OTP-9940</p> + </item> + + <item> + <p>[manager] Introduced a new transport module, + <c>snmpm_net_if_mt</c>, + which handles all incomming and outgoing + traffic in newly created processes. The message/request is + processed and then the process exits. </p> + <p>Own Id: OTP-9876</p> + </item> + + <item> + <p>[agent] Documenting previously existing but undocumented function, + <seealso marker="snmp_generic#get_table_info">snmp_generic:get_table_info/2</seealso>. </p> + <p>Own Id: OTP-9942</p> + </item> + + <item> + <p>[agent] Improve error handling while reading agent config files. + Some files contain mandatory information and is therefor themself + mandatory. </p> + <p>Own Id: OTP-9943</p> + </item> + </list> + + </section> + + <section> + <title>Fixed Bugs and Malfunctions</title> + <p>-</p> + + <!-- + <list type="bulleted"> + <item> + <p>[agent] Simultaneous + <seealso marker="snmpa#backup">snmpa:backup/1,2</seealso> + calls can interfere. + The master agent did not check if a backup was already in + progress when a backup request was accepted. </p> + <p>Own Id: OTP-9884</p> + <p>Aux Id: Seq 11995</p> + </item> + + </list> + --> + + </section> + + <section> + <title>Incompatibilities</title> + <p>-</p> + </section> + + </section> <!-- 4.22 --> + + + <section> <title>SNMP Development Toolkit 4.21.7</title> <p>Version 4.21.7 supports code replacement in runtime from/to version 4.21.6, 4.21.5, 4.21.4, 4.21.3, 4.21.2, 4.21.1, 4.21, 4.20.1 and @@ -47,14 +129,14 @@ <list type="bulleted"> <item> <p>[agent] DoS attack using GET-BULK with large value of - MaxRepetitions. - A preventive method has been implementing by simply - limit the number of varbinds that can be included in - a Get-BULK response message. This is specified by the - new config option, - <seealso marker="snmp_app#agent_gb_max_vbs">gb_max_vbs</seealso>. - </p> - <p>Own Id: OTP-9700</p> + MaxRepetitions. + A preventive method has been implementing by simply + limit the number of varbinds that can be included in + a Get-BULK response message. This is specified by the + new config option, + <seealso marker="snmp_app#agent_gb_max_vbs">gb_max_vbs</seealso>. + </p> + <p>Own Id: OTP-9700</p> </item> </list> @@ -63,7 +145,7 @@ </section> <section> - <title>Reported Fixed Bugs and Malfunctions</title> + <title>Fixed Bugs and Malfunctions</title> <!-- <p>-</p> --> @@ -71,10 +153,10 @@ <list type="bulleted"> <item> <p>[agent] Simultaneous - <seealso marker="snmpa#backup">snmpa:backup/1,2</seealso> - calls can interfere. - The master agent did not check if a backup was already in - progress when a backup request was accepted. </p> + <seealso marker="snmpa#backup">snmpa:backup/1,2</seealso> + calls can interfere. + The master agent did not check if a backup was already in + progress when a backup request was accepted. </p> <p>Own Id: OTP-9884</p> <p>Aux Id: Seq 11995</p> </item> @@ -106,14 +188,14 @@ <list type="bulleted"> <item> <p>[agent] DoS attack using GET-BULK with large value of - MaxRepetitions. - A preventive method has been implementing by simply - limit the number of varbinds that can be included in - a Get-BULK response message. This is specified by the - new config option, - <seealso marker="snmp_app#agent_gb_max_vbs">gb_max_vbs</seealso>. - </p> - <p>Own Id: OTP-9700</p> + MaxRepetitions. + A preventive method has been implementing by simply + limit the number of varbinds that can be included in + a Get-BULK response message. This is specified by the + new config option, + <seealso marker="snmp_app#agent_gb_max_vbs">gb_max_vbs</seealso>. + </p> + <p>Own Id: OTP-9700</p> </item> </list> @@ -121,7 +203,7 @@ </section> <section> - <title>Reported Fixed Bugs and Malfunctions</title> + <title>Fixed Bugs and Malfunctions</title> <!-- <p>-</p> --> @@ -129,12 +211,12 @@ <list type="bulleted"> <item> <p>[agent] Mib server cache gclimit update function incorrectly calls - age update function. - The gclimit update function, - <seealso marker="snmpa#update_mibs_cache_gclimit">update_mibs_cache_gclimit/1</seealso>, - <em>incorrectly</em> called the age update function, - <seealso marker="snmpa#update_mibs_cache_age">update_mibs_cache_age/2</seealso>. </p> - <p>Johan Claesson</p> + age update function. + The gclimit update function, + <seealso marker="snmpa#update_mibs_cache_gclimit">update_mibs_cache_gclimit/1</seealso>, + <em>incorrectly</em> called the age update function, + <seealso marker="snmpa#update_mibs_cache_age">update_mibs_cache_age/2</seealso>. </p> + <p>Johan Claesson</p> <p>Own Id: OTP-9868</p> </item> diff --git a/lib/snmp/doc/src/snmp.xml b/lib/snmp/doc/src/snmp.xml index af0833f005..3e6610891f 100644 --- a/lib/snmp/doc/src/snmp.xml +++ b/lib/snmp/doc/src/snmp.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="iso-8859-1" ?> <!DOCTYPE erlref SYSTEM "erlref.dtd"> <erlref> <header> <copyright> - <year>1996</year><year>2009</year> + <year>1996</year><year>2012</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -391,6 +391,30 @@ version of the protocol data unit. There is a new line between <c>Vsn</c> and <c>PDU</c>.</p> + <marker id="log_to_io"></marker> + </desc> + </func> + + <func> + <name>log_to_io(LogDir, Mibs, LogName, LogFile) -> ok | {error, Reason}</name> + <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start) -> ok | {error, Reason}</name> + <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop) -> ok | {error, Reason}</name> + <fsummary>Convert an Audit Trail Log to text format</fsummary> + <type> + <v>LogDir = string()</v> + <v>Mibs = [MibName]</v> + <v>MibName = string()</v> + <v>LogName = string()</v> + <v>LogFile = string()</v> + <v>Start = Stop = null | datetime() | {local_time,datetime()} | {universal_time,datetime()} </v> + <v>Reason = term()</v> + </type> + <desc> + <p>Converts an Audit Trail Log to a readable format and + prints it on stdio. See + <seealso marker="snmp#log_to_txt">log_to_txt</seealso> + above for more info.</p> + <marker id="change_log_size"></marker> </desc> </func> diff --git a/lib/snmp/doc/src/snmp_app.xml b/lib/snmp/doc/src/snmp_app.xml index f6abe783b3..d11eaa2771 100644 --- a/lib/snmp/doc/src/snmp_app.xml +++ b/lib/snmp/doc/src/snmp_app.xml @@ -35,8 +35,8 @@ <appsummary>The SNMP Application</appsummary> <description> <p>This chapter describes the <c>snmp</c> - application in OTP. The SNMP application provides the following - services:</p> + application in OTP. The SNMP application provides the following + services:</p> <list type="bulleted"> <item> <p>a multilingual extensible SNMP agent</p> @@ -589,16 +589,16 @@ {no_reuse, no_reuse()} | {filter, manager_net_if_filter_options()} </c></p> <p>These options are actually specific to the used module. - The ones shown here are applicable to the default - <c>manager_net_if_module()</c>.</p> + The ones shown here are applicable to the default + <c>manager_net_if_module()</c>.</p> <p>For defaults see the options in <c>manager_net_if_option()</c>.</p> </item> <marker id="manager_ni_module"></marker> <tag><c><![CDATA[manager_net_if_module() = atom() <optional>]]></c></tag> <item> - <p>Module which handles the network interface part for the - SNMP manager. Must implement the + <p>The module which handles the network interface part for the + SNMP manager. It must implement the <seealso marker="snmpm_network_interface">snmpm_network_interface</seealso> behaviour.</p> <p>Default is <c>snmpm_net_if</c>.</p> </item> diff --git a/lib/snmp/doc/src/snmp_config.xml b/lib/snmp/doc/src/snmp_config.xml index 0a49b7a62e..b756f3da7d 100644 --- a/lib/snmp/doc/src/snmp_config.xml +++ b/lib/snmp/doc/src/snmp_config.xml @@ -586,18 +586,18 @@ {no_reuse, no_reuse()} | {filter, manager_net_if_filter_options()}</c></p> <p>These options are actually specific to the used module. - The ones shown here are applicable to the default - <c>manager_net_if_module()</c>.</p> + The ones shown here are applicable to the default + <c>manager_net_if_module()</c>. </p> <p>For defaults see the options in <c>manager_net_if_option()</c>.</p> </item> <marker id="manager_ni_module"></marker> <tag><c><![CDATA[manager_net_if_module() = atom() <optional>]]></c></tag> <item> - <p>Module which handles the network interface part for the - SNMP manager. Must implement the - <seealso marker="snmpm_network_interface">snmpm_network_interface</seealso> behaviour.</p> - <p>Default is <c>snmpm_net_if</c>.</p> + <p>The module which handles the network interface part for the + SNMP manager. It must implement the + <seealso marker="snmpm_network_interface">snmpm_network_interface</seealso> behaviour. </p> + <p>Default is <c>snmpm_net_if</c>. </p> </item> <marker id="manager_ni_filter_opts"></marker> diff --git a/lib/snmp/doc/src/snmp_generic.xml b/lib/snmp/doc/src/snmp_generic.xml index 77f3cefaa2..79a22323d9 100644 --- a/lib/snmp/doc/src/snmp_generic.xml +++ b/lib/snmp/doc/src/snmp_generic.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="iso-8859-1" ?> <!DOCTYPE erlref SYSTEM "erlref.dtd"> <erlref> <header> <copyright> - <year>1996</year><year>2009</year> + <year>1996</year><year>2012</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -34,15 +34,16 @@ <module>snmp_generic</module> <modulesummary>Generic Functions for Implementing SNMP Objects in a Database</modulesummary> <description> - <p>The module <c>snmp_generic</c> contains generic functions for implementing tables - (and variables) using the SNMP built-in database or Mnesia. These - default functions are used if no instrumentation function is - provided for a managed object in a MIB. Sometimes, it might be - necessary to customize the behaviour of the default functions. For - example, in some situations a trap should be sent if a row is - deleted or modified, or some hardware is to be informed, when - information is changed. - </p> + <marker id="description"></marker> + <p>The module <c>snmp_generic</c> contains generic functions for + implementing tables (and variables) using the SNMP built-in database + or Mnesia. These default functions are used if no instrumentation + function is provided for a managed object in a MIB. Sometimes, + it might be necessary to customize the behaviour of the default + functions. For example, in some situations a trap should be sent + if a row is deleted or modified, or some hardware is to be informed, + when information is changed. </p> + <p>The overall structure is shown in the following figure:</p> <pre> +---------------+ @@ -93,6 +94,7 @@ </description> <section> + <marker id="data_types"></marker> <title>DATA TYPES</title> <p>In the functions defined below, the following types are used:</p> <code type="none"> @@ -118,7 +120,10 @@ value() = term() case of a <c>set</c> operation. </p> </item> </taglist> + + <marker id="get_status_col2"></marker> </section> + <funcs> <func> <name>get_status_col(Name, Cols)</name> @@ -136,8 +141,11 @@ value() = term() <p>This function can be used in instrumentation functions for <c>is_set_ok</c>, <c>undo</c> or <c>set</c> to check if the status column of a table is modified.</p> + + <marker id="get_index_types"></marker> </desc> </func> + <func> <name>get_index_types(Name)</name> <fsummary>Get the index types of <c>Name</c></fsummary> @@ -147,9 +155,36 @@ value() = term() <desc> <p>Gets the index types of <c>Name</c></p> <p>This function can be used in instrumentation functions to - retrieve the index types part of the table info.</p> + retrieve the index types part of the table info.</p> + + <marker id="get_table_info"></marker> </desc> </func> + + <func> + <name>get_table_info(Name, Item) -> table_info_result()</name> + <fsummary>Get table info item of MIB table <c>Name</c></fsummary> + <type> + <v>Name = name()</v> + <v>Item = table_item() | all</v> + <v>table_item() = nbr_of_cols | defvals | status_col | not_accessible | + index_types | first_accessible | first_own_index</v> + <v>table_info_result() = Value | [{table_item(), Value}]</v> + <v>Value = term()</v> + </type> + <desc> + <p>Get a specific table info item or, if <c>Item</c> has the + value <c>all</c>, a two tuple list (property list) is instead + returned with all the items and their respctive values of the + given table. </p> + + <p>This function can be used in instrumentation functions to + retrieve a given part of the table info.</p> + + <marker id="table_func"></marker> + </desc> + </func> + <func> <name>table_func(Op1, NameDb)</name> <name>table_func(Op2, RowIndex, Cols, NameDb) -> Ret</name> @@ -190,8 +225,11 @@ value() = term() <p>The function returns according to the specification of an instrumentation function. </p> + + <marker id="table_get_elements"></marker> </desc> </func> + <func> <name>table_get_elements(NameDb, RowIndex, Cols) -> Values</name> <fsummary>Get elements in a table row</fsummary> @@ -204,8 +242,11 @@ value() = term() <desc> <p>Returns a list with values for all columns in <c>Cols</c>. If a column is undefined, its value is <c>noinit</c>.</p> + + <marker id="table_next"></marker> </desc> </func> + <func> <name>table_next(NameDb, RestOid) -> RowIndex | endOfTable</name> <fsummary>Find the next row in the table</fsummary> @@ -217,8 +258,11 @@ value() = term() <desc> <p>Finds the indices of the next row in the table. <c>RestOid</c> does not have to specify an existing row.</p> + + <marker id="table_row_exists"></marker> </desc> </func> + <func> <name>table_row_exists(NameDb, RowIndex) -> bool()</name> <fsummary>Check if a row in a table exists</fsummary> @@ -228,8 +272,11 @@ value() = term() </type> <desc> <p>Checks if a row in a table exists.</p> + + <marker id="table_set_elements"></marker> </desc> </func> + <func> <name>table_set_elements(NameDb, RowIndex, Cols) -> bool()</name> <fsummary>Set elements in a table row</fsummary> @@ -246,8 +293,11 @@ value() = term() <c>mnesia:write</c> to store the values. This means that this function must be called from within a transaction (<c>mnesia:transaction/1</c> or <c>mnesia:dirty/1</c>).</p> + + <marker id="variable_func"></marker> </desc> </func> + <func> <name>variable_func(Op1, NameDb)</name> <name>variable_func(Op2, Val, NameDb) -> Ret</name> @@ -268,8 +318,11 @@ value() = term() the database. </p> <p>The function returns according to the specification of an instrumentation function. </p> + + <marker id="variable_get"></marker> </desc> </func> + <func> <name>variable_get(NameDb) -> {value, Value} | undefined</name> <fsummary>Get the value of a variable</fsummary> @@ -279,8 +332,11 @@ value() = term() </type> <desc> <p>Gets the value of a variable.</p> + + <marker id="variable_set"></marker> </desc> </func> + <func> <name>variable_set(NameDb, NewVal) -> true | false</name> <fsummary>Set a value for a variable</fsummary> @@ -299,6 +355,7 @@ value() = term() </funcs> <section> + <marker id="example"></marker> <title>Example</title> <p>The following example shows an implementation of a table which is stored in Mnesia, but with some checks performed at set-request diff --git a/lib/snmp/doc/src/snmp_manager_netif.xml b/lib/snmp/doc/src/snmp_manager_netif.xml index 2738ca76c1..169e20d10b 100644 --- a/lib/snmp/doc/src/snmp_manager_netif.xml +++ b/lib/snmp/doc/src/snmp_manager_netif.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="iso-8859-1" ?> <!DOCTYPE chapter SYSTEM "chapter.dtd"> <chapter> <header> <copyright> - <year>2004</year><year>2009</year> + <year>2004</year><year>2012</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -35,31 +35,34 @@ <image file="snmp_manager_netif_1.gif"> <icaption>The Purpose of Manager Net if</icaption> </image> + <p>The Network Interface (Net if) process delivers SNMP PDUs to the - manager server, and receives SNMP PDUs from the manager server. - The most common behaviour of a Net if process is that is receives - request PDU from the manager server, encodes the PDU into bytes - and transmits the bytes onto the network to an agent. When the - reply from the agent is received by the Net if process, which it - decodes into an SNMP PDU, which it sends to the manager server. - </p> + manager server, and receives SNMP PDUs from the manager server. + The most common behaviour of a Net if process is that is receives + request PDU from the manager server, encodes the PDU into bytes + and transmits the bytes onto the network to an agent. When the + reply from the agent is received by the Net if process, which it + decodes into an SNMP PDU, which it sends to the manager server. </p> + <p>However, that simple behaviour can be modified in numerous - ways. For example, the Net if process can apply some kind of - encrypting/decrypting scheme on the bytes. - </p> - <p>It is also possible to write your own Net if process. The default - Net if process is implemented in the module <c>snmpm_net_if</c> and - it uses UDP as the transport protocol. - </p> - <p>This section describes how to write a Net if process. - </p> + ways. For example, the Net if process can apply some kind of + encrypting/decrypting scheme on the bytes. </p> + + <p>The snmp application provides two different modules, + <c>snmpm_net_if</c> (the default) and <c>snmpm_net_if_mt</c>, + both uses the UDP as the transport protocol. The difference + between the two modules is that the latter is "multi-threaded", + i.e. for each message/request a new process is created that + process the message/request and then exits. </p> + + <p>It is also possible to write your own Net if process, + this section describes how to write a Net if processdo that.</p> <section> <marker id="mandatory_functions"></marker> <title>Mandatory Functions</title> <p>A Net if process must implement the SNMP manager - <seealso marker="snmpm_network_interface">network interface behaviour</seealso>. - </p> + <seealso marker="snmpm_network_interface">network interface behaviour</seealso>. </p> </section> <section> diff --git a/lib/snmp/doc/src/snmpa.xml b/lib/snmp/doc/src/snmpa.xml index 2322af28cc..86fde03205 100644 --- a/lib/snmp/doc/src/snmpa.xml +++ b/lib/snmp/doc/src/snmpa.xml @@ -501,6 +501,7 @@ notification_delivery_info() = #snmpa_notification_delivery_info{} </func> <func> + <name>log_to_txt(LogDir)</name> <name>log_to_txt(LogDir, Mibs)</name> <name>log_to_txt(LogDir, Mibs, OutFile) -> ok | {error, Reason}</name> <name>log_to_txt(LogDir, Mibs, OutFile, LogName) -> ok | {error, Reason}</name> @@ -528,6 +529,37 @@ notification_delivery_info() = #snmpa_notification_delivery_info{} See <seealso marker="snmp#log_to_txt">snmp:log_to_txt</seealso> for more info.</p> + <marker id="log_to_io"></marker> + </desc> + </func> + + <func> + <name>log_to_io(LogDir) -> ok | {error, Reason}</name> + <name>log_to_io(LogDir, Mibs) -> ok | {error, Reason}</name> + <name>log_to_io(LogDir, Mibs, LogName) -> ok | {error, Reason}</name> + <name>log_to_io(LogDir, Mibs, LogName, LogFile) -> ok | {error, Reason}</name> + <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start) -> ok | {error, Reason}</name> + <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop) -> ok | {error, Reason}</name> + <fsummary>Convert an Audit Trail Log to text format</fsummary> + <type> + <v>LogDir = string()</v> + <v>Mibs = [MibName]</v> + <v>MibName = string()</v> + <v>LogName = string()</v> + <v>LogFile = string()</v> + <v>Start = Stop = null | datetime() | {local_time,datetime()} | {universal_time,datetime()} </v> + <v>Reason = disk_log_open_error() | file_open_error() | term()</v> + <v>disk_log_open_error() = {LogName, term()}</v> + <v>file_open_error() = {OutFile, term()}</v> + </type> + <desc> + <p>Converts an Audit Trail Log to a readable format and + prints it on stdio. + <c>LogName</c> defaults to "snmpa_log". + <c>LogFile</c> defaults to "snmpa.log". + See <seealso marker="snmp#log_to_io">snmp:log_to_io</seealso> + for more info.</p> + <marker id="change_log_size"></marker> </desc> </func> diff --git a/lib/snmp/doc/src/snmpm.xml b/lib/snmp/doc/src/snmpm.xml index c36a1b2a24..9bbb6cdbdb 100644 --- a/lib/snmp/doc/src/snmpm.xml +++ b/lib/snmp/doc/src/snmpm.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2004</year><year>2011</year> + <year>2004</year><year>2012</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -1237,6 +1237,38 @@ priv_key = [integer()] (length is 16 if priv = usmDESPrivProtocol | usmAesCfb1 See <seealso marker="snmp#log_to_txt">snmp:log_to_txt</seealso> for more info.</p> + <marker id="log_to_io"></marker> + </desc> + </func> + + <func> + <name>log_to_io(LogDir) -> ok | {error, Reason}</name> + <name>log_to_io(LogDir, Mibs) -> ok | {error, Reason}</name> + <name>log_to_io(LogDir, Mibs) -> ok | {error, Reason}</name> + <name>log_to_io(LogDir, Mibs, LogName) -> ok | {error, Reason}</name> + <name>log_to_io(LogDir, Mibs, LogName, LogFile) -> ok | {error, Reason}</name> + <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start) -> ok | {error, Reason}</name> + <name>log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop) -> ok | {error, Reason}</name> + <fsummary>Convert an Audit Trail Log to text format</fsummary> + <type> + <v>LogDir = string()</v> + <v>Mibs = [MibName]</v> + <v>MibName = string()</v> + <v>LogName = string()</v> + <v>LogFile = string()</v> + <v>Start = Stop = null | datetime() | {local_time,datetime()} | {universal_time,datetime()} </v> + <v>Reason = disk_log_open_error() | file_open_error() | term()</v> + <v>disk_log_open_error() = {LogName, term()}</v> + <v>file_open_error() = {OutFile, term()}</v> + </type> + <desc> + <p>Converts an Audit Trail Log to a readable format and + prints it on stdio. + <c>LogName</c> defaults to "snmpm_log". + <c>LogFile</c> defaults to "snmpm.log". + See <seealso marker="snmp#log_to_io">snmp:log_to_io</seealso> + for more info.</p> + <marker id="change_log_size"></marker> </desc> </func> diff --git a/lib/snmp/doc/src/snmpm_network_interface_filter.xml b/lib/snmp/doc/src/snmpm_network_interface_filter.xml index ea1e183848..5f80cec94e 100644 --- a/lib/snmp/doc/src/snmpm_network_interface_filter.xml +++ b/lib/snmp/doc/src/snmpm_network_interface_filter.xml @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="latin1" ?> +<?xml version="1.0" encoding="iso-8859-1" ?> <!DOCTYPE erlref SYSTEM "erlref.dtd"> <erlref> <header> <copyright> - <year>2007</year><year>2009</year> + <year>2007</year><year>2012</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -72,9 +72,10 @@ </list> <p>Note that the network interface filter is something which is used by the network interface implementation provided by the application - (<c>snmpm_net_if</c>). The default filter accepts all messages.</p> + (<c>snmpm_net_if</c> and <c>snmpm_net_if_mt</c>). + The default filter accepts all messages.</p> <p>A network interface filter can e.g. be used during testing or for load - regulation. </p> + regulation. </p> </description> <section> diff --git a/lib/snmp/examples/ex2/snmp_ex2_manager.erl b/lib/snmp/examples/ex2/snmp_ex2_manager.erl index ff873327bc..1b247d713d 100644 --- a/lib/snmp/examples/ex2/snmp_ex2_manager.erl +++ b/lib/snmp/examples/ex2/snmp_ex2_manager.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2006-2010. All Rights Reserved. +%% Copyright Ericsson AB 2006-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -39,7 +39,7 @@ %% Manager callback API: -export([handle_error/3, - handle_agent/4, + handle_agent/5, handle_pdu/4, handle_trap/3, handle_inform/3, @@ -265,16 +265,17 @@ handle_snmp_callback(handle_error, {ReqId, Reason}) -> "~n Reason: ~p" "~n", [ReqId, Reason]), ok; -handle_snmp_callback(handle_agent, {Addr, Port, SnmpInfo}) -> +handle_snmp_callback(handle_agent, {Addr, Port, Type, SnmpInfo}) -> {ES, EI, VBs} = SnmpInfo, io:format("*** UNKNOWN AGENT ***" "~n Address: ~p" "~n Port: ~p" + "~n Type: ~p" "~n SNMP Info: " "~n Error Status: ~w" "~n Error Index: ~w" "~n Varbinds: ~p" - "~n", [Addr, Port, ES, EI, VBs]), + "~n", [Addr, Port, Type, ES, EI, VBs]), ok; handle_snmp_callback(handle_pdu, {TargetName, ReqId, SnmpResponse}) -> {ES, EI, VBs} = SnmpResponse, @@ -382,8 +383,8 @@ handle_error(ReqId, Reason, Server) when is_pid(Server) -> ignore. -handle_agent(Addr, Port, SnmpInfo, Server) when is_pid(Server) -> - report_callback(Server, handle_agent, {Addr, Port, SnmpInfo}), +handle_agent(Addr, Port, Type, SnmpInfo, Server) when is_pid(Server) -> + report_callback(Server, handle_agent, {Addr, Port, Type, SnmpInfo}), ignore. diff --git a/lib/snmp/include/snmp_types.hrl b/lib/snmp/include/snmp_types.hrl index 4adb24361c..fce087347f 100644 --- a/lib/snmp/include/snmp_types.hrl +++ b/lib/snmp/include/snmp_types.hrl @@ -78,23 +78,36 @@ %%----------------------------------------------------------------- %% TableInfo - stored in snmp_symbolic_store for use by the -%% generic table functions. +%% generic table functions. For an ordinary table, the +%% types will be the following: %% nbr_of_cols is an integer +%% pos_integer() %% defvals is a list of {Col, Defval}, ordered by column %% number +%% [{Col :: integer(), Defval :: term()}] %% status_col is an integer +%% pos_integer() %% not_accessible a sorted list of columns (> first_accessible) %% that are 'not-accessible' -%% indextypes is a list of #asn1_type for the index-columns, -%% ordered by column number -%% first_accessible is an integer, the first non-accessible -%% column +%% [pos_integer()] +%% index_types is a list of #asn1_type for the index-columns, +%% ordered by column number or an "augment"-tuple +%% [asn1_type()] +%% first_accessible is an integer, the first accessible column +%% pos_integer() %% first_own_index is an integer. 0 if there is no such index for %% this table. %% This is not the same as the last integer in the oid! %% Example: If a table has one own index (oid.1), one %% column (oid.2) and one imported index then %% first_own_index will be 2. +%% non_neg_integer() +%% For a augmented table, it will instead look like this: +%% index_types {augments, {atom(), asn1_type()}} +%% nbr_of_cols pos_integer() +%% not_accessible [pos_integer()] +%% first_accessible pos_integer() +%% %%----------------------------------------------------------------- -record(table_info, @@ -192,7 +205,7 @@ %%---------------------------------------------------------------------- -record(mib, {misc = [], - mib_format_version = "3.2", + mib_format_version = "3.3", name = "", module_identity, %% Not in SMIv1, and only with +module_identity mes = [], diff --git a/lib/snmp/src/agent/snmp_community_mib.erl b/lib/snmp/src/agent/snmp_community_mib.erl index 77307aa7ad..d7d41aca31 100644 --- a/lib/snmp/src/agent/snmp_community_mib.erl +++ b/lib/snmp/src/agent/snmp_community_mib.erl @@ -28,6 +28,7 @@ -export([add_community/5, add_community/6, delete_community/1]). -export([check_community/1]). +-include("snmpa_internal.hrl"). -include("SNMP-COMMUNITY-MIB.hrl"). -include("SNMP-TARGET-MIB.hrl"). -include("SNMPv2-TC.hrl"). @@ -120,10 +121,17 @@ init_tabs(Comms) -> read_community_config_files(Dir) -> ?vdebug("read community config file",[]), - Gen = fun(_) -> ok end, - Filter = fun(Comms) -> Comms end, - Check = fun(Entry) -> check_community(Entry) end, - [Comms] = + FileName = "community.conf", + Gen = fun(D, Reason) -> + warning_msg("failed reading config file ~s" + "~n Config Dir: ~s" + "~n Reason: ~p", + [FileName, D, Reason]), + ok + end, + Filter = fun(Comms) -> Comms end, + Check = fun(Entry) -> check_community(Entry) end, + [Comms] = snmp_conf:read_files(Dir, [{Gen, Filter, Check, "community.conf"}]), Comms. @@ -601,5 +609,8 @@ set_sname(_) -> %% Keep it, if already set. error(Reason) -> throw({error, Reason}). +warning_msg(F, A) -> + ?snmpa_warning("[COMMUNITY-MIB]: " ++ F, A). + config_err(F, A) -> snmpa_error:config_err("[COMMUNITY-MIB]: " ++ F, A). diff --git a/lib/snmp/src/agent/snmp_framework_mib.erl b/lib/snmp/src/agent/snmp_framework_mib.erl index 0d7866d94d..cc191bd956 100644 --- a/lib/snmp/src/agent/snmp_framework_mib.erl +++ b/lib/snmp/src/agent/snmp_framework_mib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2010. All Rights Reserved. +%% Copyright Ericsson AB 1999-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -115,7 +115,9 @@ do_configure(Dir) -> read_internal_config_files(Dir) -> ?vdebug("read context config file",[]), - Gen = fun(D) -> convert_context(D) end, + Gen = fun(D, Reason) -> + convert_context(D, Reason) + end, Filter = fun(Contexts) -> Contexts end, Check = fun(Entry) -> check_context(Entry) end, [Ctxs] = snmp_conf:read_files(Dir, [{Gen, Filter, Check, "context.conf"}]), @@ -123,10 +125,17 @@ read_internal_config_files(Dir) -> read_agent(Dir) -> - ?vdebug("read agent config file",[]), - Check = fun(Entry) -> check_agent(Entry) end, - File = filename:join(Dir, "agent.conf"), - Agent = snmp_conf:read(File, Check), + ?vdebug("read agent config file", []), + FileName = "agent.conf", + Check = fun(Entry) -> check_agent(Entry) end, + File = filename:join(Dir, FileName), + Agent = + try + snmp_conf:read(File, Check) + catch + throw:{error, Reason} -> + error({failed_reading_config_file, Dir, FileName, Reason}) + end, sort_agent(Agent). @@ -146,9 +155,9 @@ sort_agent(L) -> %%----------------------------------------------------------------- %% Generate a context.conf file. %%----------------------------------------------------------------- -convert_context(Dir) -> +convert_context(Dir, _Reason) -> config_err("missing context.conf file => generating a default file", []), - File = filename:join(Dir,"context.conf"), + File = filename:join(Dir, "context.conf"), case file:open(File, [write]) of {ok, Fid} -> ok = io:format(Fid, "~s\n", [context_header()]), @@ -165,7 +174,7 @@ context_header() -> io_lib:format("%% This file was automatically generated by " "snmp_config v~s ~w-~2.2.0w-~2.2.0w " "~2.2.0w:~2.2.0w:~2.2.0w\n", - [?version,Y,Mo,D,H,Mi,S]). + [?version, Y, Mo, D, H, Mi, S]). %%----------------------------------------------------------------- diff --git a/lib/snmp/src/agent/snmp_notification_mib.erl b/lib/snmp/src/agent/snmp_notification_mib.erl index 720ac749b8..37e09f5d3e 100644 --- a/lib/snmp/src/agent/snmp_notification_mib.erl +++ b/lib/snmp/src/agent/snmp_notification_mib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2011. All Rights Reserved. +%% Copyright Ericsson AB 1998-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -27,6 +27,7 @@ -export([add_notify/3, delete_notify/1]). -export([check_notify/1]). +-include("snmpa_internal.hrl"). -include("SNMP-NOTIFICATION-MIB.hrl"). -include("SNMPv2-TC.hrl"). -include("snmp_tables.hrl"). @@ -104,7 +105,14 @@ do_reconfigure(Dir) -> read_notify_config_files(Dir) -> ?vdebug("read notify config file",[]), - Gen = fun(_) -> ok end, + FileName = "notify.conf", + Gen = fun(D, Reason) -> + info_msg("failed reading config file ~s" + "~n Config Dir: ~s" + "~n Reason: ~p", + [FileName, D, Reason]), + ok + end, Filter = fun(Notifs) -> Notifs end, Check = fun(Entry) -> check_notify(Entry) end, [Notifs] = @@ -112,7 +120,7 @@ read_notify_config_files(Dir) -> Notifs. check_notify({Name, Tag, Type}) -> - snmp_conf:check_string(Name,{gt,0}), + snmp_conf:check_string(Name, {gt, 0}), snmp_conf:check_string(Tag), {ok, Val} = snmp_conf:check_atom(Type, [{trap, 1}, {inform, 2}]), Notify = {Name, Tag, Val, @@ -451,12 +459,15 @@ set_sname() -> set_sname(get(sname)). set_sname(undefined) -> - put(sname,conf); + put(sname, conf); set_sname(_) -> %% Keep it, if already set. ok. error(Reason) -> throw({error, Reason}). +info_msg(F, A) -> + ?snmpa_info("[NOTIFICATION-MIB]: " ++ F, A). + config_err(F, A) -> snmpa_error:config_err("[NOTIFICATION-MIB]: " ++ F, A). diff --git a/lib/snmp/src/agent/snmp_standard_mib.erl b/lib/snmp/src/agent/snmp_standard_mib.erl index b6834d278c..ca93546923 100644 --- a/lib/snmp/src/agent/snmp_standard_mib.erl +++ b/lib/snmp/src/agent/snmp_standard_mib.erl @@ -143,20 +143,35 @@ do_reconfigure(Dir) -> %% Func: read_standard/1 %% Args: Dir is the directory with trailing dir_separator where %% the configuration files can be found. -%% Purpose: Reads th standard configuration file. +%% Purpose: Reads the standard configuration file. %% Returns: A list of standard variables %% Fails: If an error occurs, the process will die with Reason %% configuration_error. +%% This file is mandatory, as it contains mandatory +%% config options for which there are no default values. %%----------------------------------------------------------------- read_standard(Dir) -> ?vdebug("check standard config file",[]), - Gen = fun(_) -> ok end, - Filter = fun(Standard) -> sort_standard(Standard) end, - Check = fun(Entry) -> check_standard(Entry) end, + FileName = "standard.conf", + Gen = fun(D, Reason) -> + throw({error, {failed_reading_config_file, + D, FileName, + list_dir(Dir), Reason}}) + end, + Filter = fun(Standard) -> sort_standard(Standard) end, + Check = fun(Entry) -> check_standard(Entry) end, [Standard] = - snmp_conf:read_files(Dir, [{Gen, Filter, Check, "standard.conf"}]), + snmp_conf:read_files(Dir, [{Gen, Filter, Check, FileName}]), Standard. +list_dir(Dir) -> + case file:list_dir(Dir) of + {ok, Files} -> + Files; + Error -> + Error + end. + %%----------------------------------------------------------------- %% Make sure that each mandatory standard attribute is present, and @@ -548,6 +563,7 @@ snmp_set_serial_no(set, NewVal) -> snmp_generic:variable_func(set, (NewVal + 1) rem 2147483648, {snmpSetSerialNo, volatile}). + %%----------------------------------------------------------------- %% This is the instrumentation function for sysOrTable %%----------------------------------------------------------------- @@ -588,4 +604,4 @@ error(Reason) -> throw({error, Reason}). config_err(F, A) -> - snmpa_error:config_err("[STANDARD-MIB]: " ++ F, A). + snmpa_error:config_err("[STANDARD-MIB] " ++ F, A). diff --git a/lib/snmp/src/agent/snmp_target_mib.erl b/lib/snmp/src/agent/snmp_target_mib.erl index a45db89c09..b01d536caa 100644 --- a/lib/snmp/src/agent/snmp_target_mib.erl +++ b/lib/snmp/src/agent/snmp_target_mib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2011. All Rights Reserved. +%% Copyright Ericsson AB 1998-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -132,12 +132,12 @@ do_reconfigure(Dir) -> read_target_config_files(Dir) -> - ?vdebug("check target address config file",[]), - TAGen = fun(_D) -> ok end, + ?vdebug("check target address and parameter config file(s)",[]), + TAGen = fun(_D, _Reason) -> ok end, TAFilter = fun(Addr) -> Addr end, TACheck = fun(Entry) -> check_target_addr(Entry) end, - TPGen = fun(_D) -> ok end, + TPGen = fun(_D, _Reason) -> ok end, TPFilter = fun(Params) -> Params end, TPCheck = fun(Entry) -> check_target_params(Entry) end, diff --git a/lib/snmp/src/agent/snmp_user_based_sm_mib.erl b/lib/snmp/src/agent/snmp_user_based_sm_mib.erl index 69cebc858b..2e801622e7 100644 --- a/lib/snmp/src/agent/snmp_user_based_sm_mib.erl +++ b/lib/snmp/src/agent/snmp_user_based_sm_mib.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2010. All Rights Reserved. +%% Copyright Ericsson AB 1999-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -136,7 +136,7 @@ do_reconfigure(Dir) -> read_usm_config_files(Dir) -> ?vdebug("read usm config file",[]), - Gen = fun(D) -> generate_usm(D) end, + Gen = fun(D, Reason) -> generate_usm(D, Reason) end, Filter = fun(Usms) -> Usms end, Check = fun(Entry) -> check_usm(Entry) end, [Usms] = @@ -144,7 +144,7 @@ read_usm_config_files(Dir) -> Usms. -generate_usm(Dir) -> +generate_usm(Dir, _Reason) -> info_msg("Incomplete configuration. Generating empty usm.conf.", []), USMFile = filename:join(Dir, "usm.conf"), ok = file:write_file(USMFile, list_to_binary([])). diff --git a/lib/snmp/src/agent/snmp_view_based_acm_mib.erl b/lib/snmp/src/agent/snmp_view_based_acm_mib.erl index 2cee91b081..479a44795f 100644 --- a/lib/snmp/src/agent/snmp_view_based_acm_mib.erl +++ b/lib/snmp/src/agent/snmp_view_based_acm_mib.erl @@ -115,7 +115,7 @@ do_reconfigure(Dir) -> read_vacm_config_files(Dir) -> ?vdebug("read vacm config file",[]), - Gen = fun(_) -> ok end, + Gen = fun(_D, _Reason) -> ok end, Filter = fun(Vacms) -> Sec2Group = [X || {vacmSecurityToGroup, X} <- Vacms], Access = [X || {vacmAccess, X} <- Vacms], diff --git a/lib/snmp/src/agent/snmpa.erl b/lib/snmp/src/agent/snmpa.erl index c400aaddf7..b45a47ec6b 100644 --- a/lib/snmp/src/agent/snmpa.erl +++ b/lib/snmp/src/agent/snmpa.erl @@ -83,8 +83,11 @@ -export([add_agent_caps/2, del_agent_caps/1, get_agent_caps/0]). %% Audit Trail Log functions --export([log_to_txt/2, log_to_txt/3, log_to_txt/4, +-export([log_to_txt/1, + log_to_txt/2, log_to_txt/3, log_to_txt/4, log_to_txt/5, log_to_txt/6, log_to_txt/7, + log_to_io/1, log_to_io/2, log_to_io/3, + log_to_io/4, log_to_io/5, log_to_io/6, log_info/0, change_log_size/1, get_log_type/0, get_log_type/1, @@ -780,6 +783,8 @@ get_agent_caps() -> %%% Audit Trail Log functions %%%----------------------------------------------------------------- +log_to_txt(LogDir) -> + log_to_txt(LogDir, []). log_to_txt(LogDir, Mibs) -> OutFile = "snmpa_log.txt", LogName = ?audit_trail_log_name, @@ -800,6 +805,23 @@ log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop) -> snmp:log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop). +log_to_io(LogDir) -> + log_to_io(LogDir, []). +log_to_io(LogDir, Mibs) -> + LogName = ?audit_trail_log_name, + LogFile = ?audit_trail_log_file, + snmp:log_to_io(LogDir, Mibs, LogName, LogFile). +log_to_io(LogDir, Mibs, LogName) -> + LogFile = ?audit_trail_log_file, + snmp:log_to_io(LogDir, Mibs, LogName, LogFile). +log_to_io(LogDir, Mibs, LogName, LogFile) -> + snmp:log_to_io(LogDir, Mibs, LogName, LogFile). +log_to_io(LogDir, Mibs, LogName, LogFile, Start) -> + snmp:log_to_io(LogDir, Mibs, LogName, LogFile, Start). +log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop) -> + snmp:log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop). + + log_info() -> LogName = ?audit_trail_log_name, snmp_log:info(LogName). diff --git a/lib/snmp/src/agent/snmpa_agent.erl b/lib/snmp/src/agent/snmpa_agent.erl index 9cc986cf47..9d30e332f1 100644 --- a/lib/snmp/src/agent/snmpa_agent.erl +++ b/lib/snmp/src/agent/snmpa_agent.erl @@ -1281,7 +1281,7 @@ handle_call({backup, BackupDir}, From, #state{backup = undefined} = S) -> ?vtrace("backup server: ~p", [BackupServer]), {noreply, S#state{backup = {BackupServer, From}}}; -handle_call({backup, _BackupDir}, From, #state{backup = Backup} = S) -> +handle_call({backup, _BackupDir}, _From, #state{backup = Backup} = S) -> ?vinfo("backup already in progress: ~p", [Backup]), {reply, {error, backup_in_progress}, S}; diff --git a/lib/snmp/src/agent/snmpa_local_db.erl b/lib/snmp/src/agent/snmpa_local_db.erl index 1ec8dd3874..2c0cad807a 100644 --- a/lib/snmp/src/agent/snmpa_local_db.erl +++ b/lib/snmp/src/agent/snmpa_local_db.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2011. All Rights Reserved. +%% Copyright Ericsson AB 1996-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -515,7 +515,7 @@ handle_call({backup, BackupDir}, From, {reply, Error, State} end; -handle_call({backup, _BackupDir}, From, #state{backup = Backup} = S) -> +handle_call({backup, _BackupDir}, _From, #state{backup = Backup} = S) -> ?vinfo("backup already in progress: ~p", [Backup]), {reply, {error, backup_in_progress}, S}; diff --git a/lib/snmp/src/agent/snmpa_mib.erl b/lib/snmp/src/agent/snmpa_mib.erl index 574467d38f..575a018c0c 100644 --- a/lib/snmp/src/agent/snmpa_mib.erl +++ b/lib/snmp/src/agent/snmpa_mib.erl @@ -580,7 +580,7 @@ handle_call({backup, BackupDir}, From, {reply, Error, State} end; -handle_call({backup, _BackupDir}, From, #state{backup = Backup} = S) -> +handle_call({backup, _BackupDir}, _From, #state{backup = Backup} = S) -> ?vinfo("backup already in progress: ~p", [Backup]), {reply, {error, backup_in_progress}, S}; diff --git a/lib/snmp/src/app/snmp.app.src b/lib/snmp/src/app/snmp.app.src index a880a14696..b11c1ef934 100644 --- a/lib/snmp/src/app/snmp.app.src +++ b/lib/snmp/src/app/snmp.app.src @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2009. All Rights Reserved. +%% Copyright Ericsson AB 1996-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -91,6 +91,7 @@ snmpm_mpd, snmpm_net_if, snmpm_net_if_filter, + snmpm_net_if_mt, snmpm_network_interface, snmpm_network_interface_filter, snmpm_server, diff --git a/lib/snmp/src/app/snmp.appup.src b/lib/snmp/src/app/snmp.appup.src index c8e5eec6db..8360d88c94 100644 --- a/lib/snmp/src/app/snmp.appup.src +++ b/lib/snmp/src/app/snmp.appup.src @@ -22,66 +22,181 @@ %% ----- U p g r a d e ------------------------------------------------------- [ + {"4.21.7", + [ + {load_module, snmp_config, soft_purge, soft_purge, []}, + {load_module, snmp_conf, soft_purge, soft_purge, []}, + {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_target_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, [snmp_conf]}, + + {load_module, snmp, soft_purge, soft_purge, [snmp_log]}, + {load_module, snmpa, soft_purge, soft_purge, [snmp]}, + {load_module, snmpm, soft_purge, soft_purge, [snmp]}, + {load_module, snmp_log, soft_purge, soft_purge, []}, + {load_module, snmp_verbosity, soft_purge, soft_purge, []}, + {load_module, snmpm_mpd, soft_purge, soft_purge, []}, + + {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, + {update, snmpa_mib, soft, soft_purge, soft_purge, []}, + {update, snmpa_agent, soft, soft_purge, soft_purge, []}, + + {add_module, snmpm_net_if_mt} + ] + }, {"4.21.6", [ + {load_module, snmp_config, soft_purge, soft_purge, []}, + {load_module, snmp_conf, soft_purge, soft_purge, []}, + {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_target_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, [snmp_conf]}, + + {load_module, snmp, soft_purge, soft_purge, [snmp_log]}, + {load_module, snmpa, soft_purge, soft_purge, [snmp]}, + {load_module, snmpm, soft_purge, soft_purge, [snmp]}, + {load_module, snmp_log, soft_purge, soft_purge, []}, + {load_module, snmp_verbosity, soft_purge, soft_purge, []}, + {load_module, snmpm_mpd, soft_purge, soft_purge, []}, + {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, {update, snmpa_mib, soft, soft_purge, soft_purge, []}, - {update, snmpa_agent, soft, soft_purge, soft_purge, []} + {update, snmpa_agent, soft, soft_purge, soft_purge, []}, + + {add_module, snmpm_net_if_mt} ] }, {"4.21.5", [ - {load_module, snmpa, soft_purge, soft_purge, []}, - {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, + {load_module, snmp_config, soft_purge, soft_purge, []}, + {load_module, snmp_conf, soft_purge, soft_purge, []}, + {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, [snmp_conf]}, + + {load_module, snmp, soft_purge, soft_purge, [snmp_log]}, + {load_module, snmpm, soft_purge, soft_purge, [snmp]}, + {load_module, snmp_log, soft_purge, soft_purge, []}, + {load_module, snmp_verbosity, soft_purge, soft_purge, []}, + {load_module, snmpm_mpd, soft_purge, soft_purge, []}, + + {load_module, snmpa, soft_purge, soft_purge, [snmp]}, + {load_module, snmp_target_mib, soft_purge, soft_purge, + [snmp_conf, snmpa_mib_lib]}, {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, {load_module, snmpa_trap, soft_purge, soft_purge, []}, {load_module, snmpa_vacm, soft_purge, soft_purge, []}, {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, {update, snmpa_mib, soft, soft_purge, soft_purge, []}, {update, snmpa_supervisor, soft, soft_purge, soft_purge, []}, - {update, snmpa_agent, soft, soft_purge, soft_purge, []} + {update, snmpa_agent, soft, soft_purge, soft_purge, []}, + + {add_module, snmpm_net_if_mt} ] }, {"4.21.4", [ - {load_module, snmpa, soft_purge, soft_purge, []}, - {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, + {load_module, snmp_config, soft_purge, soft_purge, []}, + {load_module, snmp_conf, soft_purge, soft_purge, []}, + {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]}, + + {load_module, snmp, soft_purge, soft_purge, [snmp_log]}, + {load_module, snmpm, soft_purge, soft_purge, [snmp]}, + {load_module, snmp_log, soft_purge, soft_purge, []}, + {load_module, snmp_verbosity, soft_purge, soft_purge, []}, + {load_module, snmpm_mpd, soft_purge, soft_purge, []}, + + {load_module, snmpa, soft_purge, soft_purge, [snmp]}, + {load_module, snmp_target_mib, soft_purge, soft_purge, + [snmp_conf, snmpa_mib_lib]}, {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, {load_module, snmpa_trap, soft_purge, soft_purge, []}, {update, snmpa_supervisor, soft, soft_purge, soft_purge, []}, {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []}, - {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}, + {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, + [snmp_conf]}, {load_module, snmpa_vacm, soft_purge, soft_purge, []}, {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, {update, snmpa_mib, soft, soft_purge, soft_purge, []}, - {update, snmpa_agent, soft, soft_purge, soft_purge, []} + {update, snmpa_agent, soft, soft_purge, soft_purge, []}, + + {add_module, snmpm_net_if_mt} ] }, {"4.21.3", [ - {load_module, snmpa, soft_purge, soft_purge, []}, - {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, + {load_module, snmp_config, soft_purge, soft_purge, []}, + {load_module, snmp_conf, soft_purge, soft_purge, []}, + {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]}, + + {load_module, snmp, soft_purge, soft_purge, [snmp_log]}, + {load_module, snmpm, soft_purge, soft_purge, [snmp]}, + {load_module, snmp_log, soft_purge, soft_purge, []}, + {load_module, snmp_verbosity, soft_purge, soft_purge, []}, + {load_module, snmpm_mpd, soft_purge, soft_purge, []}, + + {load_module, snmpa, soft_purge, soft_purge, [snmp]}, + {load_module, snmp_target_mib, soft_purge, soft_purge, + [snmp_conf, snmpa_mib_lib]}, {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, {load_module, snmpa_trap, soft_purge, soft_purge, []}, {update, snmpa_supervisor, soft, soft_purge, soft_purge, []}, {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []}, - {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}, + {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, + [snmp_conf]}, {load_module, snmpa_vacm, soft_purge, soft_purge, []}, {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, {update, snmpa_mib, soft, soft_purge, soft_purge, []}, - {update, snmpa_agent, soft, soft_purge, soft_purge, []} + {update, snmpa_agent, soft, soft_purge, soft_purge, []}, + + {add_module, snmpm_net_if_mt} ] }, {"4.21.2", [ - {load_module, snmpa, soft_purge, soft_purge, []}, - {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, + {load_module, snmp_config, soft_purge, soft_purge, []}, + {load_module, snmp_conf, soft_purge, soft_purge, []}, + {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]}, + + {load_module, snmp, soft_purge, soft_purge, [snmp_log]}, + {load_module, snmpm, soft_purge, soft_purge, [snmp]}, + {load_module, snmp_log, soft_purge, soft_purge, []}, + {load_module, snmp_verbosity, soft_purge, soft_purge, []}, + {load_module, snmpm_mpd, soft_purge, soft_purge, []}, + + {load_module, snmpa, soft_purge, soft_purge, [snmp]}, + {load_module, snmp_target_mib, soft_purge, soft_purge, + [snmp_conf, snmpa_mib_lib]}, {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, {update, snmpa_supervisor, soft, soft_purge, soft_purge, []}, - {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}, + {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, + [snmp_conf]}, {load_module, snmpa_vacm, soft_purge, soft_purge, []}, {load_module, snmpa_mpd, soft_purge, soft_purge, []}, {load_module, snmpa_set_lib, soft_purge, soft_purge, []}, @@ -89,17 +204,35 @@ {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []}, {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, {update, snmpa_mib, soft, soft_purge, soft_purge, []}, - {update, snmpa_agent, soft, soft_purge, soft_purge, []} + {update, snmpa_agent, soft, soft_purge, soft_purge, []}, + + {add_module, snmpm_net_if_mt} ] }, {"4.21.1", [ - {load_module, snmpa, soft_purge, soft_purge, []}, - {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, + {load_module, snmp_config, soft_purge, soft_purge, []}, + {load_module, snmp_conf, soft_purge, soft_purge, []}, + {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]}, + + {load_module, snmp, soft_purge, soft_purge, [snmp_log]}, + {load_module, snmpm, soft_purge, soft_purge, [snmp]}, + {load_module, snmp_log, soft_purge, soft_purge, []}, + {load_module, snmp_verbosity, soft_purge, soft_purge, []}, + {load_module, snmpm_mpd, soft_purge, soft_purge, []}, + + {load_module, snmpa, soft_purge, soft_purge, [snmp]}, + {load_module, snmp_target_mib, soft_purge, soft_purge, + [snmp_conf, snmpa_mib_lib]}, {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, {update, snmpa_supervisor, soft, soft_purge, soft_purge, []}, - {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}, + {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, + [snmp_conf]}, {load_module, snmpa_vacm, soft_purge, soft_purge, []}, {load_module, snmpa_mpd, soft_purge, soft_purge, []}, {load_module, snmpa_set_lib, soft_purge, soft_purge, []}, @@ -108,91 +241,46 @@ {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, {update, snmpa_mib, soft, soft_purge, soft_purge, []}, {update, snmpa_agent, soft, soft_purge, soft_purge, []}, - {update, snmp_note_store, soft, soft_purge, soft_purge, []} + {update, snmp_note_store, soft, soft_purge, soft_purge, []}, + + {add_module, snmpm_net_if_mt} ] }, {"4.21", [ - {load_module, snmpa, soft_purge, soft_purge, []}, + {load_module, snmp_config, soft_purge, soft_purge, []}, + {load_module, snmp_conf, soft_purge, soft_purge, []}, + {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]}, + + {load_module, snmp, soft_purge, soft_purge, [snmp_log]}, + {load_module, snmpm, soft_purge, soft_purge, [snmp]}, + {load_module, snmp_log, soft_purge, soft_purge, []}, + {load_module, snmp_verbosity, soft_purge, soft_purge, []}, + {load_module, snmpm_mpd, soft_purge, soft_purge, []}, + + {load_module, snmpa, soft_purge, soft_purge, [snmp]}, {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, {update, snmpa_supervisor, soft, soft_purge, soft_purge, []}, - {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}, + {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, + [snmp_conf]}, {load_module, snmpa_vacm, soft_purge, soft_purge, []}, {load_module, snmpa_mpd, soft_purge, soft_purge, []}, {load_module, snmpa_set_lib, soft_purge, soft_purge, []}, {load_module, snmpa_trap, soft_purge, soft_purge, []}, - {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, + {load_module, snmp_target_mib, soft_purge, soft_purge, + [snmp_conf, snmpa_mib_lib]}, {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []}, {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, {update, snmpa_mib, soft, soft_purge, soft_purge, []}, {update, snmpa_agent, soft, soft_purge, soft_purge, []}, - {update, snmp_note_store, soft, soft_purge, soft_purge, []} - ] - }, - {"4.20.1", - [ - {load_module, snmpa, soft_purge, soft_purge, []}, - {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, - {update, snmpa_supervisor, soft, soft_purge, soft_purge, []}, - - {load_module, snmpa_vacm, soft_purge, soft_purge, []}, - {load_module, snmpa_set_lib, soft_purge, soft_purge, []}, - {load_module, snmpa_trap, soft_purge, soft_purge, []}, - {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, - {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}, - {load_module, snmpm, soft_purge, soft_purge, - [snmpm_server, snmpm_config, snmp_config]}, - {load_module, snmp_conf, soft_purge, soft_purge, []}, - {load_module, snmp_config, soft_purge, soft_purge, []}, - {load_module, snmpm_mpd, soft_purge, soft_purge, - [snmp_conf, snmp_config, snmpm_config]}, - {load_module, snmpa_mpd, soft_purge, soft_purge, - [snmp_conf, snmp_config]}, - {load_module, snmpa_conf, soft_purge, soft_purge, [snmp_config]}, - {update, snmp_note_store, soft, soft_purge, soft_purge, []}, - {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []}, - {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, - {update, snmpa_mib, soft, soft_purge, soft_purge, []}, - {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mpd]}, - {update, snmpm_config, soft, soft_purge, soft_purge, [snmp_conf]}, - {update, snmpm_server, soft, soft_purge, soft_purge, - [snmpm_net_if, snmpm_mpd, snmpm_config]}, - {update, snmpm_net_if, soft, soft_purge, soft_purge, - [snmp_conf, snmpm_mpd, snmpm_config]} - ] - }, - {"4.20", - [ - {load_module, snmpa, soft_purge, soft_purge, []}, - {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, - {update, snmpa_supervisor, soft, soft_purge, soft_purge, []}, + {update, snmp_note_store, soft, soft_purge, soft_purge, []}, - {load_module, snmpa_vacm, soft_purge, soft_purge, []}, - {load_module, snmpa_set_lib, soft_purge, soft_purge, []}, - {load_module, snmpa_trap, soft_purge, soft_purge, []}, - {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}, - {load_module, snmp_target_mib, soft_purge, soft_purge, - [snmpa_mib_lib, snmp_conf]}, - {load_module, snmpm, soft_purge, soft_purge, - [snmpm_server, snmpm_config, snmp_config]}, - {load_module, snmp_conf, soft_purge, soft_purge, []}, - {load_module, snmp_config, soft_purge, soft_purge, []}, - {load_module, snmpm_mpd, soft_purge, soft_purge, - [snmp_conf, snmp_config, snmpm_config]}, - {load_module, snmpa_mpd, soft_purge, soft_purge, - [snmp_conf, snmp_config]}, - {load_module, snmpa_conf, soft_purge, soft_purge, [snmp_config]}, - {update, snmp_note_store, soft, soft_purge, soft_purge, []}, - {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []}, - {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, - {update, snmpa_mib, soft, soft_purge, soft_purge, []}, - {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mpd]}, - {update, snmpm_config, soft, soft_purge, soft_purge, [snmp_conf]}, - {update, snmpm_server, soft, soft_purge, soft_purge, - [snmpm_net_if, snmpm_mpd, snmpm_config]}, - {update, snmpm_net_if, soft, soft_purge, soft_purge, - [snmp_conf, snmpm_mpd, snmpm_config]} + {add_module, snmpm_net_if_mt} ] } ], @@ -200,66 +288,181 @@ %% ------D o w n g r a d e --------------------------------------------------- [ + {"4.21.7", + [ + {load_module, snmp_config, soft_purge, soft_purge, []}, + {load_module, snmp_conf, soft_purge, soft_purge, []}, + {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_target_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, [snmp_conf]}, + + {load_module, snmp, soft_purge, soft_purge, [snmp_log]}, + {load_module, snmpa, soft_purge, soft_purge, [snmp]}, + {load_module, snmpm, soft_purge, soft_purge, [snmp]}, + {load_module, snmp_log, soft_purge, soft_purge, []}, + {load_module, snmp_verbosity, soft_purge, soft_purge, []}, + {load_module, snmpm_mpd, soft_purge, soft_purge, []}, + + {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, + {update, snmpa_mib, soft, soft_purge, soft_purge, []}, + {update, snmpa_agent, soft, soft_purge, soft_purge, []}, + + {remove, {snmpm_net_if_mt, soft_purge, soft_purge}} + ] + }, {"4.21.6", [ + {load_module, snmp_config, soft_purge, soft_purge, []}, + {load_module, snmp_conf, soft_purge, soft_purge, []}, + {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_target_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, [snmp_conf]}, + + {load_module, snmp, soft_purge, soft_purge, [snmp_log]}, + {load_module, snmpa, soft_purge, soft_purge, [snmp]}, + {load_module, snmpm, soft_purge, soft_purge, [snmp]}, + {load_module, snmp_log, soft_purge, soft_purge, []}, + {load_module, snmp_verbosity, soft_purge, soft_purge, []}, + {load_module, snmpm_mpd, soft_purge, soft_purge, []}, + {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, {update, snmpa_mib, soft, soft_purge, soft_purge, []}, - {update, snmpa_agent, soft, soft_purge, soft_purge, []} + {update, snmpa_agent, soft, soft_purge, soft_purge, []}, + + {remove, {snmpm_net_if_mt, soft_purge, soft_purge}} ] }, {"4.21.5", [ - {load_module, snmpa, soft_purge, soft_purge, []}, - {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, + {load_module, snmp_config, soft_purge, soft_purge, []}, + {load_module, snmp_conf, soft_purge, soft_purge, []}, + {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, [snmp_conf]}, + + {load_module, snmp, soft_purge, soft_purge, [snmp_log]}, + {load_module, snmpm, soft_purge, soft_purge, [snmp]}, + {load_module, snmp_log, soft_purge, soft_purge, []}, + {load_module, snmp_verbosity, soft_purge, soft_purge, []}, + {load_module, snmpm_mpd, soft_purge, soft_purge, []}, + + {load_module, snmpa, soft_purge, soft_purge, [snmp]}, + {load_module, snmp_target_mib, soft_purge, soft_purge, + [snmp_conf, snmpa_mib_lib]}, {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, {load_module, snmpa_trap, soft_purge, soft_purge, []}, {load_module, snmpa_vacm, soft_purge, soft_purge, []}, {update, snmpa_supervisor, soft, soft_purge, soft_purge, []}, {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, {update, snmpa_mib, soft, soft_purge, soft_purge, []}, - {update, snmpa_agent, soft, soft_purge, soft_purge, []} + {update, snmpa_agent, soft, soft_purge, soft_purge, []}, + + {remove, {snmpm_net_if_mt, soft_purge, soft_purge}} ] }, {"4.21.4", [ - {load_module, snmpa, soft_purge, soft_purge, []}, - {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, + {load_module, snmp_config, soft_purge, soft_purge, []}, + {load_module, snmp_conf, soft_purge, soft_purge, []}, + {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]}, + + {load_module, snmp, soft_purge, soft_purge, [snmp_log]}, + {load_module, snmpm, soft_purge, soft_purge, [snmp]}, + {load_module, snmp_log, soft_purge, soft_purge, []}, + {load_module, snmp_verbosity, soft_purge, soft_purge, []}, + {load_module, snmpm_mpd, soft_purge, soft_purge, []}, + + {load_module, snmpa, soft_purge, soft_purge, [snmp]}, + {load_module, snmp_target_mib, soft_purge, soft_purge, + [snmp_conf, snmpa_mib_lib]}, {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, {load_module, snmpa_trap, soft_purge, soft_purge, []}, {update, snmpa_supervisor, soft, soft_purge, soft_purge, []}, {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []}, - {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}, + {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, + [snmp_conf]}, {load_module, snmpa_vacm, soft_purge, soft_purge, []}, {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, {update, snmpa_mib, soft, soft_purge, soft_purge, []}, - {update, snmpa_agent, soft, soft_purge, soft_purge, []} + {update, snmpa_agent, soft, soft_purge, soft_purge, []}, + + {remove, {snmpm_net_if_mt, soft_purge, soft_purge}} ] }, {"4.21.3", [ - {load_module, snmpa, soft_purge, soft_purge, []}, - {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, + {load_module, snmp_config, soft_purge, soft_purge, []}, + {load_module, snmp_conf, soft_purge, soft_purge, []}, + {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]}, + + {load_module, snmp, soft_purge, soft_purge, [snmp_log]}, + {load_module, snmpm, soft_purge, soft_purge, [snmp]}, + {load_module, snmp_log, soft_purge, soft_purge, []}, + {load_module, snmp_verbosity, soft_purge, soft_purge, []}, + {load_module, snmpm_mpd, soft_purge, soft_purge, []}, + + {load_module, snmpa, soft_purge, soft_purge, [snmp]}, + {load_module, snmp_target_mib, soft_purge, soft_purge, + [snmp_conf, snmpa_mib_lib]}, {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, {load_module, snmpa_trap, soft_purge, soft_purge, []}, {update, snmpa_supervisor, soft, soft_purge, soft_purge, []}, {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []}, - {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}, + {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, + [snmp_conf]}, {load_module, snmpa_vacm, soft_purge, soft_purge, []}, {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, {update, snmpa_mib, soft, soft_purge, soft_purge, []}, - {update, snmpa_agent, soft, soft_purge, soft_purge, []} + {update, snmpa_agent, soft, soft_purge, soft_purge, []}, + + {remove, {snmpm_net_if_mt, soft_purge, soft_purge}} ] }, {"4.21.2", [ - {load_module, snmpa, soft_purge, soft_purge, []}, - {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, + {load_module, snmp_config, soft_purge, soft_purge, []}, + {load_module, snmp_conf, soft_purge, soft_purge, []}, + {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]}, + + {load_module, snmp, soft_purge, soft_purge, [snmp_log]}, + {load_module, snmpm, soft_purge, soft_purge, [snmp]}, + {load_module, snmp_log, soft_purge, soft_purge, []}, + {load_module, snmp_verbosity, soft_purge, soft_purge, []}, + {load_module, snmpm_mpd, soft_purge, soft_purge, []}, + + {load_module, snmpa, soft_purge, soft_purge, [snmp]}, + {load_module, snmp_target_mib, soft_purge, soft_purge, + [snmp_conf, snmpa_mib_lib]}, {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, {update, snmpa_supervisor, soft, soft_purge, soft_purge, []}, - {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}, + {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, + [snmp_conf]}, {load_module, snmpa_vacm, soft_purge, soft_purge, []}, {load_module, snmpa_mpd, soft_purge, soft_purge, []}, {load_module, snmpa_set_lib, soft_purge, soft_purge, []}, @@ -267,17 +470,35 @@ {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []}, {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, {update, snmpa_mib, soft, soft_purge, soft_purge, []}, - {update, snmpa_agent, soft, soft_purge, soft_purge, []} + {update, snmpa_agent, soft, soft_purge, soft_purge, []}, + + {remove, {snmpm_net_if_mt, soft_purge, soft_purge}} ] }, {"4.21.1", [ - {load_module, snmpa, soft_purge, soft_purge, []}, - {load_module, snmp_target_mib, soft_purge, soft_purge, [snmpa_mib_lib]}, + {load_module, snmp_config, soft_purge, soft_purge, []}, + {load_module, snmp_conf, soft_purge, soft_purge, []}, + {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]}, + + {load_module, snmp, soft_purge, soft_purge, [snmp_log]}, + {load_module, snmpm, soft_purge, soft_purge, [snmp]}, + {load_module, snmp_log, soft_purge, soft_purge, []}, + {load_module, snmp_verbosity, soft_purge, soft_purge, []}, + {load_module, snmpm_mpd, soft_purge, soft_purge, []}, + + {load_module, snmpa, soft_purge, soft_purge, [snmp]}, + {load_module, snmp_target_mib, soft_purge, soft_purge, + [snmp_conf, snmpa_mib_lib]}, {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, {update, snmpa_supervisor, soft, soft_purge, soft_purge, []}, - {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}, + {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, + [snmp_conf]}, {load_module, snmpa_vacm, soft_purge, soft_purge, []}, {load_module, snmpa_mpd, soft_purge, soft_purge, []}, {load_module, snmpa_set_lib, soft_purge, soft_purge, []}, @@ -286,90 +507,46 @@ {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, {update, snmpa_mib, soft, soft_purge, soft_purge, []}, {update, snmpa_agent, soft, soft_purge, soft_purge, []}, - {update, snmp_note_store, soft, soft_purge, soft_purge, []} + {update, snmp_note_store, soft, soft_purge, soft_purge, []}, + + {remove, {snmpm_net_if_mt, soft_purge, soft_purge}} ] }, {"4.21", [ - {load_module, snmpa, soft_purge, soft_purge, []}, + {load_module, snmp_config, soft_purge, soft_purge, []}, + {load_module, snmp_conf, soft_purge, soft_purge, []}, + {load_module, snmp_community_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_framework_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_notification_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_standard_mib, soft_purge, soft_purge, [snmp_conf]}, + {load_module, snmp_user_based_sm_mib, soft_purge, soft_purge, [snmp_conf]}, + + {load_module, snmp, soft_purge, soft_purge, [snmp_log]}, + {load_module, snmpm, soft_purge, soft_purge, [snmp]}, + {load_module, snmp_log, soft_purge, soft_purge, []}, + {load_module, snmp_verbosity, soft_purge, soft_purge, []}, + {load_module, snmpm_mpd, soft_purge, soft_purge, []}, + + {load_module, snmpa, soft_purge, soft_purge, [snmp]}, {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, {update, snmpa_supervisor, soft, soft_purge, soft_purge, []}, - {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}, + {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, + [snmp_conf]}, {load_module, snmpa_vacm, soft_purge, soft_purge, []}, {load_module, snmpa_mpd, soft_purge, soft_purge, []}, {load_module, snmpa_set_lib, soft_purge, soft_purge, []}, {load_module, snmpa_trap, soft_purge, soft_purge, []}, - {load_module, snmp_target_mib, soft_purge, soft_purge, []}, + {load_module, snmp_target_mib, soft_purge, soft_purge, + [snmp_conf, snmpa_mib_lib]}, {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []}, {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, {update, snmpa_mib, soft, soft_purge, soft_purge, []}, {update, snmpa_agent, soft, soft_purge, soft_purge, []}, - {update, snmp_note_store, soft, soft_purge, soft_purge, []} - ] - }, - {"4.20.1", - [ - {load_module, snmpa, soft_purge, soft_purge, []}, - {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, - {update, snmpa_supervisor, soft, soft_purge, soft_purge, []}, - - {load_module, snmpa_vacm, soft_purge, soft_purge, []}, - {load_module, snmpa_set_lib, soft_purge, soft_purge, []}, - {load_module, snmpa_trap, soft_purge, soft_purge, []}, - {load_module, snmp_target_mib, soft_purge, soft_purge, []}, - {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}, - {load_module, snmpm, soft_purge, soft_purge, - [snmpm_server, snmpm_config, snmp_config]}, - {load_module, snmp_conf, soft_purge, soft_purge, []}, - {load_module, snmp_config, soft_purge, soft_purge, []}, - {load_module, snmpm_mpd, soft_purge, soft_purge, - [snmp_conf, snmp_config, snmpm_config]}, - {load_module, snmpa_mpd, soft_purge, soft_purge, - [snmp_conf, snmp_config]}, - {load_module, snmpa_conf, soft_purge, soft_purge, [snmp_config]}, {update, snmp_note_store, soft, soft_purge, soft_purge, []}, - {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []}, - {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, - {update, snmpa_mib, soft, soft_purge, soft_purge, []}, - {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mpd]}, - {update, snmpm_config, soft, soft_purge, soft_purge, [snmp_conf]}, - {update, snmpm_server, soft, soft_purge, soft_purge, - [snmpm_net_if, snmpm_mpd, snmpm_config]}, - {update, snmpm_net_if, soft, soft_purge, soft_purge, - [snmp_conf, snmpm_mpd, snmpm_config]} - ] - }, - {"4.20", - [ - {load_module, snmpa, soft_purge, soft_purge, []}, - {load_module, snmpa_mib_lib, soft_purge, soft_purge, []}, - {update, snmpa_supervisor, soft, soft_purge, soft_purge, []}, - {load_module, snmpa_vacm, soft_purge, soft_purge, []}, - {load_module, snmpa_set_lib, soft_purge, soft_purge, []}, - {load_module, snmpa_trap, soft_purge, soft_purge, []}, - {load_module, snmp_view_based_acm_mib, soft_purge, soft_purge, []}, - {load_module, snmp_target_mib, soft_purge, soft_purge, [snmp_conf]}, - {load_module, snmpm, soft_purge, soft_purge, - [snmpm_server, snmpm_config, snmp_config]}, - {load_module, snmp_conf, soft_purge, soft_purge, []}, - {load_module, snmp_config, soft_purge, soft_purge, []}, - {load_module, snmpm_mpd, soft_purge, soft_purge, - [snmp_conf, snmp_config, snmpm_config]}, - {load_module, snmpa_mpd, soft_purge, soft_purge, - [snmp_conf, snmp_config]}, - {load_module, snmpa_conf, soft_purge, soft_purge, [snmp_config]}, - {update, snmp_note_store, soft, soft_purge, soft_purge, []}, - {load_module, snmp_generic_mnesia, soft_purge, soft_purge, []}, - {update, snmpa_local_db, soft, soft_purge, soft_purge, []}, - {update, snmpa_mib, soft, soft_purge, soft_purge, []}, - {update, snmpa_agent, soft, soft_purge, soft_purge, [snmpa_mpd]}, - {update, snmpm_config, soft, soft_purge, soft_purge, [snmp_conf]}, - {update, snmpm_server, soft, soft_purge, soft_purge, - [snmpm_net_if, snmpm_mpd, snmpm_config]}, - {update, snmpm_net_if, soft, soft_purge, soft_purge, - [snmp_conf, snmpm_mpd, snmpm_config]} + {remove, {snmpm_net_if_mt, soft_purge, soft_purge}} ] } ] diff --git a/lib/snmp/src/app/snmp.erl b/lib/snmp/src/app/snmp.erl index 3e0f05e604..fc03757e3f 100644 --- a/lib/snmp/src/app/snmp.erl +++ b/lib/snmp/src/app/snmp.erl @@ -50,6 +50,7 @@ read_mib/1, log_to_txt/5, log_to_txt/6, log_to_txt/7, + log_to_io/4, log_to_io/5, log_to_io/6, change_log_size/2, octet_string_to_bits/1, bits_to_octet_string/1, @@ -843,6 +844,12 @@ log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start) -> log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop) -> snmp_log:log_to_txt(LogName, LogFile, LogDir, Mibs, OutFile, Start, Stop). +log_to_io(LogDir, Mibs, LogName, LogFile) -> + snmp_log:log_to_io(LogName, LogFile, LogDir, Mibs). +log_to_io(LogDir, Mibs, LogName, LogFile, Start) -> + snmp_log:log_to_io(LogName, LogFile, LogDir, Mibs, Start). +log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop) -> + snmp_log:log_to_io(LogName, LogFile, LogDir, Mibs, Start, Stop). change_log_size(LogName, NewSize) -> snmp_log:change_size(LogName, NewSize). diff --git a/lib/snmp/src/compile/snmpc_lib.erl b/lib/snmp/src/compile/snmpc_lib.erl index 38bb8f3ac6..6e833b6c44 100644 --- a/lib/snmp/src/compile/snmpc_lib.erl +++ b/lib/snmp/src/compile/snmpc_lib.erl @@ -704,23 +704,29 @@ check_trap_name(EnterpriseName, Line, MEs) -> %% This information is needed to be able to create default instrumentation %% functions for tables. %%---------------------------------------------------------------------- -make_table_info(Line, _TableName, {augments,SrcTableEntry}, ColumnMEs) -> +make_table_info(Line, TableName, {augments, SrcTableEntry}, ColumnMEs) -> ColMEs = lists:keysort(#me.oid, ColumnMEs), - %% Nbr_of_Cols = length(ColMEs), + Nbr_of_Cols = length(ColMEs), MEs = ColMEs ++ (get(cdata))#cdata.mes, - Aug = case lookup(SrcTableEntry,MEs) of + Aug = case lookup(SrcTableEntry, MEs) of false -> print_error("Cannot AUGMENT the non-existing table entry ~p", - [SrcTableEntry],Line), + [SrcTableEntry], Line), {augments, error}; - {value,ME} -> - {augments, {SrcTableEntry,translate_type(ME#me.asn1_type)}} + {value, ME} -> + {augments, {SrcTableEntry, translate_type(ME#me.asn1_type)}} end, - #table_info{index_types = Aug}; -make_table_info(Line, TableName, {indexes,[]}, _ColumnMEs) -> + FirstNonIdxCol = augments_first_non_index_column(ColMEs), + NoAccs = list_not_accessible(FirstNonIdxCol, ColMEs), + FirstAcc = first_accessible(TableName, ColMEs), + #table_info{nbr_of_cols = Nbr_of_Cols, + first_accessible = FirstAcc, + not_accessible = NoAccs, + index_types = Aug}; +make_table_info(Line, TableName, {indexes, []}, _ColumnMEs) -> print_error("Table ~w lacks indexes.", [TableName],Line), #table_info{}; -make_table_info(Line, TableName, {indexes,Indexes}, ColumnMEs) -> +make_table_info(Line, TableName, {indexes, Indexes}, ColumnMEs) -> ColMEs = lists:keysort(#me.oid, ColumnMEs), NonImpliedIndexes = lists:map(fun non_implied_name/1, Indexes), test_read_create_access(ColMEs, Line, dummy), @@ -860,11 +866,17 @@ get_asn1_type(ColumnName, MEs, Line) -> end. test_index_positions(Line, Indexes, ColMEs) -> - TLI = lists:filter(fun (IndexName) -> - is_table_local_index(IndexName,ColMEs) end, - Indexes), + IsTLI = fun(IndexName) -> is_table_local_index(IndexName, ColMEs) end, + TLI = lists:filter(IsTLI, Indexes), test_index_positions_impl(Line, TLI, ColMEs). +%% An table that augments another cannot conatin any index, +%% so the first non-index column is always the first column. +augments_first_non_index_column([]) -> + none; +augments_first_non_index_column([#me{oid=Col}|_ColMEs]) -> + Col. + %% Returns the first non-index column | none test_index_positions_impl(_Line, [], []) -> none; test_index_positions_impl(_Line, [], [#me{oid=Col}|_ColMEs]) -> diff --git a/lib/snmp/src/manager/depend.mk b/lib/snmp/src/manager/depend.mk index 0e7e9e3df7..2e7783c8ed 100644 --- a/lib/snmp/src/manager/depend.mk +++ b/lib/snmp/src/manager/depend.mk @@ -2,7 +2,7 @@ # %CopyrightBegin% # -# Copyright Ericsson AB 2004-2009. All Rights Reserved. +# Copyright Ericsson AB 2004-2012. All Rights Reserved. # # The contents of this file are subject to the Erlang Public License, # Version 1.1, (the "License"); you may not use this file except in @@ -49,6 +49,13 @@ $(EBIN)/snmpm_net_if.$(EMULATOR): \ snmpm_net_if.erl \ snmpm_network_interface.erl +$(EBIN)/snmpm_net_if_mt.$(EMULATOR): \ + ../../include/snmp_types.hrl \ + ../misc/snmp_debug.hrl \ + ../misc/snmp_verbosity.hrl \ + snmpm_net_if_mt.erl \ + snmpm_network_interface.erl + $(EBIN)/snmpm_server.$(EMULATOR): \ ../../include/snmp_types.hrl \ ../../include/STANDARD-MIB.hrl \ diff --git a/lib/snmp/src/manager/modules.mk b/lib/snmp/src/manager/modules.mk index 79f3dd65d9..d46545ea3f 100644 --- a/lib/snmp/src/manager/modules.mk +++ b/lib/snmp/src/manager/modules.mk @@ -2,7 +2,7 @@ # %CopyrightBegin% # -# Copyright Ericsson AB 2004-2009. All Rights Reserved. +# Copyright Ericsson AB 2004-2012. All Rights Reserved. # # The contents of this file are subject to the Erlang Public License, # Version 1.1, (the "License"); you may not use this file except in @@ -31,6 +31,7 @@ MODULES = \ snmpm_mpd \ snmpm_misc_sup \ snmpm_net_if \ + snmpm_net_if_mt \ snmpm_net_if_filter \ snmpm_server \ snmpm_server_sup \ diff --git a/lib/snmp/src/manager/snmpm.erl b/lib/snmp/src/manager/snmpm.erl index 6d2ac8d747..89eaee9f80 100644 --- a/lib/snmp/src/manager/snmpm.erl +++ b/lib/snmp/src/manager/snmpm.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2011. All Rights Reserved. +%% Copyright Ericsson AB 2004-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -75,8 +75,11 @@ %% %% Logging + log_to_txt/1, log_to_txt/2, log_to_txt/3, log_to_txt/4, log_to_txt/5, log_to_txt/6, log_to_txt/7, + log_to_io/1, log_to_io/2, log_to_io/3, + log_to_io/4, log_to_io/5, log_to_io/6, change_log_size/1, get_log_type/0, set_log_type/1, @@ -1371,6 +1374,9 @@ cancel_async_request(UserId, ReqId) -> %%%----------------------------------------------------------------- %%% Audit Trail Log functions (for backward compatibility) %%%----------------------------------------------------------------- + +log_to_txt(LogDir) -> + log_to_txt(LogDir, []). log_to_txt(LogDir, Mibs) -> OutFile = "snmpm_log.txt", LogName = ?audit_trail_log_name, @@ -1391,6 +1397,23 @@ log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop) -> snmp:log_to_txt(LogDir, Mibs, OutFile, LogName, LogFile, Start, Stop). +log_to_io(LogDir) -> + log_to_io(LogDir, []). +log_to_io(LogDir, Mibs) -> + LogName = ?audit_trail_log_name, + LogFile = ?audit_trail_log_file, + snmp:log_to_io(LogDir, Mibs, LogName, LogFile). +log_to_io(LogDir, Mibs, LogName) -> + LogFile = ?audit_trail_log_file, + snmp:log_to_io(LogDir, Mibs, LogName, LogFile). +log_to_io(LogDir, Mibs, LogName, LogFile) -> + snmp:log_to_io(LogDir, Mibs, LogName, LogFile). +log_to_io(LogDir, Mibs, LogName, LogFile, Start) -> + snmp:log_to_io(LogDir, Mibs, LogName, LogFile, Start). +log_to_io(LogDir, Mibs, LogName, LogFile, Start, Stop) -> + snmp:log_to_io(LogDir, Mibs, LogFile, Start, Stop). + + change_log_size(NewSize) -> LogName = ?audit_trail_log_name, snmp:change_log_size(LogName, NewSize). diff --git a/lib/snmp/src/manager/snmpm_config.erl b/lib/snmp/src/manager/snmpm_config.erl index c2e57abddb..5bbf9e5542 100644 --- a/lib/snmp/src/manager/snmpm_config.erl +++ b/lib/snmp/src/manager/snmpm_config.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2011. All Rights Reserved. +%% Copyright Ericsson AB 2004-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in diff --git a/lib/snmp/src/manager/snmpm_mpd.erl b/lib/snmp/src/manager/snmpm_mpd.erl index 103c87d32b..883224143e 100644 --- a/lib/snmp/src/manager/snmpm_mpd.erl +++ b/lib/snmp/src/manager/snmpm_mpd.erl @@ -110,9 +110,9 @@ process_msg(Msg, Domain, Addr, Port, State, NoteStore, Logger) -> #message{version = 'version-2', vsn_hdr = Community, data = Data} when State#state.v2c =:= true -> HS = ?empty_msg_size + length(Community), - (catch process_v1_v2c_msg('version-2', NoteStore, Msg, - Domain, Addr, Port, - Community, Data, HS, Logger)); + process_v1_v2c_msg('version-2', NoteStore, Msg, + Domain, Addr, Port, + Community, Data, HS, Logger); %% Version 3 #message{version = 'version-3', vsn_hdr = H, data = Data} diff --git a/lib/snmp/src/manager/snmpm_net_if_mt.erl b/lib/snmp/src/manager/snmpm_net_if_mt.erl new file mode 100644 index 0000000000..3e87f6a7fb --- /dev/null +++ b/lib/snmp/src/manager/snmpm_net_if_mt.erl @@ -0,0 +1,1259 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-2012. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +-module(snmpm_net_if_mt). + +-behaviour(gen_server). +-behaviour(snmpm_network_interface). + + +%% Network Interface callback functions +-export([ + start_link/2, + stop/1, + send_pdu/6, % Backward compatibillity + send_pdu/7, % Backward compatibillity + send_pdu/8, + + inform_response/4, + + note_store/2, + + info/1, + verbosity/2, + %% system_info_updated/2, + get_log_type/1, set_log_type/2, + filter_reset/1 + ]). + +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, + code_change/3, terminate/2]). + +-define(SNMP_USE_V3, true). +-include("snmp_types.hrl"). +-include("snmpm_internal.hrl"). +-include("snmpm_atl.hrl"). +-include("snmp_debug.hrl"). + +%% -define(VMODULE,"NET_IF"). +-include("snmp_verbosity.hrl"). + +-record(state, + { + server, + note_store, + sock, + mpd_state, + log, + irb = auto, % auto | {user, integer()} + irgc, + filter + }). + + +-define(DEFAULT_FILTER_MODULE, snmpm_net_if_filter). +-define(DEFAULT_FILTER_OPTS, [{module, ?DEFAULT_FILTER_MODULE}]). + +-ifdef(snmp_debug). +-define(GS_START_LINK(Args), + gen_server:start_link(?MODULE, Args, [{debug,[trace]}])). +-else. +-define(GS_START_LINK(Args), + gen_server:start_link(?MODULE, Args, [])). +-endif. + + +-define(IRGC_TIMEOUT, timer:minutes(5)). + +-define(ATL_SEQNO_INITIAL, 1). +-define(ATL_SEQNO_MAX, 2147483647). + + +%%%------------------------------------------------------------------- +%%% API +%%%------------------------------------------------------------------- +start_link(Server, NoteStore) -> + ?d("start_link -> entry with" + "~n Server: ~p" + "~n NoteStore: ~p", [Server, NoteStore]), + Args = [Server, NoteStore], + ?GS_START_LINK(Args). + +stop(Pid) -> + call(Pid, stop). + +send_pdu(Pid, Pdu, Vsn, MsgData, Addr, Port) -> + send_pdu(Pid, Pdu, Vsn, MsgData, Addr, Port, ?DEFAULT_EXTRA_INFO). + +send_pdu(Pid, Pdu, Vsn, MsgData, Addr, Port, ExtraInfo) -> + Domain = snmpm_config:default_transport_domain(), + send_pdu(Pid, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo). + +send_pdu(Pid, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo) + when is_record(Pdu, pdu) -> + ?d("send_pdu -> entry with" + "~n Pid: ~p" + "~n Pdu: ~p" + "~n Vsn: ~p" + "~n MsgData: ~p" + "~n Domain: ~p" + "~n Addr: ~p" + "~n Port: ~p", [Pid, Pdu, Vsn, MsgData, Domain, Addr, Port]), + cast(Pid, {send_pdu, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo}). + +note_store(Pid, NoteStore) -> + call(Pid, {note_store, NoteStore}). + +inform_response(Pid, Ref, Addr, Port) -> + cast(Pid, {inform_response, Ref, Addr, Port}). + +info(Pid) -> + call(Pid, info). + +verbosity(Pid, V) -> + call(Pid, {verbosity, V}). + +%% system_info_updated(Pid, What) -> +%% call(Pid, {system_info_updated, What}). + +get_log_type(Pid) -> + call(Pid, get_log_type). + +set_log_type(Pid, NewType) -> + call(Pid, {set_log_type, NewType}). + +filter_reset(Pid) -> + cast(Pid, filter_reset). + + +%%%------------------------------------------------------------------- +%%% Callback functions from gen_server +%%%------------------------------------------------------------------- + +%%-------------------------------------------------------------------- +%% Func: init/1 +%% Returns: {ok, State} | +%% {ok, State, Timeout} | +%% ignore | +%% {stop, Reason} +%%-------------------------------------------------------------------- +init([Server, NoteStore]) -> + ?d("init -> entry with" + "~n Server: ~p" + "~n NoteStore: ~p", [Server, NoteStore]), + case (catch do_init(Server, NoteStore)) of + {error, Reason} -> + {stop, Reason}; + {ok, State} -> + {ok, State} + end. + +do_init(Server, NoteStore) -> + process_flag(trap_exit, true), + + %% -- Prio -- + {ok, Prio} = snmpm_config:system_info(prio), + process_flag(priority, Prio), + + %% -- Create inform request table -- + %% This should really be protected, but it also needs to + %% be writable for the worker processes, so... + ets:new(snmpm_inform_request_table, + [set, public, named_table, {keypos, 1}]), + + %% -- Verbosity -- + {ok, Verbosity} = snmpm_config:system_info(net_if_verbosity), + put(sname, mnif), + put(verbosity, Verbosity), + ?vlog("starting", []), + + %% -- MPD -- + {ok, Vsns} = snmpm_config:system_info(versions), + MpdState = snmpm_mpd:init(Vsns), + ?vdebug("MpdState: ~w", [MpdState]), + + %% -- Module dependent options -- + {ok, Opts} = snmpm_config:system_info(net_if_options), + + %% -- Inform response behaviour -- + {ok, IRB} = snmpm_config:system_info(net_if_irb), + IrGcRef = irgc_start(IRB), + + %% -- Socket -- + SndBuf = get_opt(Opts, sndbuf, default), + RecBuf = get_opt(Opts, recbuf, default), + BindTo = get_opt(Opts, bind_to, false), + NoReuse = get_opt(Opts, no_reuse, false), + {ok, Port} = snmpm_config:system_info(port), + {ok, Sock} = do_open_port(Port, SndBuf, RecBuf, BindTo, NoReuse), + + %% Flow control -- + FilterOpts = get_opt(Opts, filter, []), + FilterMod = create_filter(FilterOpts), + ?vdebug("FilterMod: ~w", [FilterMod]), + + %% -- Audit trail log --- + {ok, ATL} = snmpm_config:system_info(audit_trail_log), + Log = do_init_log(ATL), + ?vdebug("Log: ~w", [Log]), + + %% -- Initiate counters --- + init_counters(), + + %% -- We are done --- + State = #state{server = Server, + note_store = NoteStore, + mpd_state = MpdState, + sock = Sock, + log = Log, + irb = IRB, + irgc = IrGcRef, + filter = FilterMod}, + ?vdebug("started", []), + {ok, State}. + + +%% Open port +do_open_port(Port, SendSz, RecvSz, BindTo, NoReuse) -> + ?vtrace("do_open_port -> entry with" + "~n Port: ~p" + "~n SendSz: ~p" + "~n RecvSz: ~p" + "~n BindTo: ~p" + "~n NoReuse: ~p", [Port, SendSz, RecvSz, BindTo, NoReuse]), + IpOpts1 = bind_to(BindTo), + IpOpts2 = no_reuse(NoReuse), + IpOpts3 = recbuf(RecvSz), + IpOpts4 = sndbuf(SendSz), + IpOpts = [binary | IpOpts1 ++ IpOpts2 ++ IpOpts3 ++ IpOpts4], + OpenRes = + case init:get_argument(snmpm_fd) of + {ok, [[FdStr]]} -> + Fd = list_to_integer(FdStr), + gen_udp:open(0, [{fd, Fd}|IpOpts]); + error -> + gen_udp:open(Port, IpOpts) + end, + case OpenRes of + {error, _} = Error -> + throw(Error); + OK -> + OK + end. + +bind_to(true) -> + case snmpm_config:system_info(address) of + {ok, Addr} when is_list(Addr) -> + [{ip, list_to_tuple(Addr)}]; + {ok, Addr} -> + [{ip, Addr}]; + _ -> + [] + end; +bind_to(_) -> + []. + +no_reuse(false) -> + [{reuseaddr, true}]; +no_reuse(_) -> + []. + +recbuf(default) -> + []; +recbuf(Sz) -> + [{recbuf, Sz}]. + +sndbuf(default) -> + []; +sndbuf(Sz) -> + [{sndbuf, Sz}]. + + +create_filter(Opts) when is_list(Opts) -> + case get_opt(Opts, module, ?DEFAULT_FILTER_MODULE) of + ?DEFAULT_FILTER_MODULE = Mod -> + Mod; + Module -> + snmpm_network_interface_filter:verify(Module), + Module + end; +create_filter(BadOpts) -> + throw({error, {bad_filter_opts, BadOpts}}). + + +%% ---------------------------------------------------------------------- +%% Audit Trail Logger +%% ---------------------------------------------------------------------- + +%% Open log +do_init_log(false) -> + ?vtrace("do_init_log(false) -> entry", []), + undefined; +do_init_log(true) -> + ?vtrace("do_init_log(true) -> entry", []), + {ok, Type} = snmpm_config:system_info(audit_trail_log_type), + {ok, Dir} = snmpm_config:system_info(audit_trail_log_dir), + {ok, Size} = snmpm_config:system_info(audit_trail_log_size), + {ok, Repair} = snmpm_config:system_info(audit_trail_log_repair), + Name = ?audit_trail_log_name, + File = filename:absname(?audit_trail_log_file, Dir), + case snmpm_config:system_info(audit_trail_log_seqno) of + {ok, true} -> + Initial = ?ATL_SEQNO_INITIAL, + Max = ?ATL_SEQNO_MAX, + Module = snmpm_config, + Function = increment_counter, + Args = [atl_seqno, Initial, Max], + SeqNoGen = {Module, Function, Args}, + case snmp_log:create(Name, File, SeqNoGen, Size, Repair, true) of + {ok, Log} -> + ?vdebug("log created: ~w", [Log]), + {Name, Log, Type}; + {error, Reason} -> + throw({error, {failed_create_audit_log, Reason}}) + end; + _ -> + case snmp_log:create(Name, File, Size, Repair, true) of + {ok, Log} -> + ?vdebug("log created: ~w", [Log]), + {Name, Log, Type}; + {error, Reason} -> + throw({error, {failed_create_audit_log, Reason}}) + end + end. + + +%% ---------------------------------------------------------------------- + +%%-------------------------------------------------------------------- +%% Func: handle_call/3 +%% Returns: {reply, Reply, State} | +%% {reply, Reply, State, Timeout} | +%% {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, Reply, State} | (terminate/2 is called) +%% {stop, Reason, State} (terminate/2 is called) +%%-------------------------------------------------------------------- +handle_call({verbosity, Verbosity}, _From, State) -> + ?vlog("received verbosity request", []), + put(verbosity, Verbosity), + {reply, ok, State}; + +%% handle_call({system_info_updated, What}, _From, State) -> +%% ?vlog("received system_info_updated request with What = ~p", [What]), +%% {NewState, Reply} = handle_system_info_updated(State, What), +%% {reply, Reply, NewState}; + +handle_call(get_log_type, _From, State) -> + ?vlog("received get-log-type request", []), + Reply = (catch handle_get_log_type(State)), + {reply, Reply, State}; + +handle_call({set_log_type, NewType}, _From, State) -> + ?vlog("received set-log-type request with NewType = ~p", [NewType]), + {NewState, Reply} = (catch handle_set_log_type(State, NewType)), + {reply, Reply, NewState}; + +handle_call({note_store, Pid}, _From, State) -> + ?vlog("received new note_store: ~w", [Pid]), + {reply, ok, State#state{note_store = Pid}}; + +handle_call(stop, _From, State) -> + ?vlog("received stop request", []), + Reply = ok, + {stop, normal, Reply, State}; + +handle_call(info, _From, State) -> + ?vlog("received info request", []), + Reply = get_info(State), + {reply, Reply, State}; + +handle_call(Req, From, State) -> + warning_msg("received unknown request (from ~p): ~n~p", [Req, From]), + {reply, {error, {invalid_request, Req}}, State}. + + +%%-------------------------------------------------------------------- +%% Func: handle_cast/2 +%% Returns: {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, State} (terminate/2 is called) +%%-------------------------------------------------------------------- +handle_cast({send_pdu, Pdu, Vsn, MsgData, Domain, Addr, Port, ExtraInfo}, + State) -> + ?vlog("received send_pdu message with" + "~n Pdu: ~p" + "~n Vsn: ~p" + "~n MsgData: ~p" + "~n Domain: ~p" + "~n Addr: ~p" + "~n Port: ~p", [Pdu, Vsn, MsgData, Domain, Addr, Port]), + maybe_process_extra_info(ExtraInfo), + handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, Port, State), + {noreply, State}; + +handle_cast({inform_response, Ref, Addr, Port}, State) -> + ?vlog("received inform_response message with" + "~n Ref: ~p" + "~n Addr: ~p" + "~n Port: ~p", [Ref, Addr, Port]), + handle_inform_response(Ref, Addr, Port, State), + {noreply, State}; + +handle_cast(filter_reset, State) -> + ?vlog("received filter_reset message", []), + reset_counters(), + {noreply, State}; + +handle_cast(Msg, State) -> + warning_msg("received unknown message: ~n~p", [Msg]), + {noreply, State}. + + +%%-------------------------------------------------------------------- +%% Func: handle_info/2 +%% Returns: {noreply, State} | +%% {noreply, State, Timeout} | +%% {stop, Reason, State} (terminate/2 is called) +%%-------------------------------------------------------------------- +handle_info({udp, Sock, Ip, Port, Bytes}, #state{sock = Sock} = State) -> + ?vlog("received ~w bytes from ~p:~p", [size(Bytes), Ip, Port]), + handle_udp(Ip, Port, Bytes, State), + {noreply, State}; + +handle_info(inform_response_gc, State) -> + ?vlog("received inform_response_gc message", []), + State2 = handle_inform_response_gc(State), + {noreply, State2}; + +handle_info({disk_log, _Node, Log, Info}, State) -> + ?vlog("received disk_log message: " + "~n Info: ~p", [Info]), + State2 = handle_disk_log(Log, Info, State), + {noreply, State2}; + +handle_info({'DOWN', _MRef, process, Pid, {net_if_worker, ExitStatus}}, + State) -> + ?vdebug("received DOWN message from net_if-worker: " + "~n ExitStatus: ~p", [ExitStatus]), + handle_worker_exit(Pid, ExitStatus), + {noreply, State}; + +handle_info(Info, State) -> + warning_msg("received unknown info: ~n~p", [Info]), + {noreply, State}. + + +%%-------------------------------------------------------------------- +%% Func: terminate/2 +%% Purpose: Shutdown the server +%% Returns: any (ignored by gen_server) +%%-------------------------------------------------------------------- +terminate(Reason, #state{log = Log, irgc = IrGcRef}) -> + ?vdebug("terminate: ~p", [Reason]), + irgc_stop(IrGcRef), + %% Close logs + do_close_log(Log), + ok. + + +do_close_log({Log, _Type}) -> + (catch snmp_log:sync(Log)), + (catch snmp_log:close(Log)), + ok; +do_close_log(_) -> + ok. + + +%%---------------------------------------------------------------------- +%% Func: code_change/3 +%% Purpose: Convert process state when code is changed +%% Returns: {ok, NewState} +%%---------------------------------------------------------------------- + +code_change(_Vsn, State, _Extra) -> + ?d("code_change -> entry with" + "~n Vsn: ~p" + "~n State: ~p" + "~n Extra: ~p", [_Vsn, State, _Extra]), + {ok, State}. + + +%%%------------------------------------------------------------------- +%%% Internal functions +%%%------------------------------------------------------------------- + +handle_udp(Addr, Port, Bytes, State) -> + Verbosity = get(verbosity), + spawn_opt(fun() -> + Log = worker_init(State, Verbosity), + Res = (catch maybe_handle_recv_msg( + Addr, Port, Bytes, + State#state{log = Log})), + worker_exit(udp, {Addr, Port}, Res) + end, + [monitor]). + + +maybe_handle_recv_msg(Addr, Port, Bytes, #state{filter = FilterMod} = State) -> + case (catch FilterMod:accept_recv(Addr, Port)) of + false -> + %% Drop the received packet + inc(netIfMsgInDrops), + ok; + _ -> + handle_recv_msg(Addr, Port, Bytes, State) + end. + + +handle_recv_msg(Addr, Port, Bytes, #state{server = Pid}) + when is_binary(Bytes) andalso (size(Bytes) =:= 0) -> + Pid ! {snmp_error, {empty_message, Addr, Port}, Addr, Port}, + ok; + +handle_recv_msg(Addr, Port, Bytes, + #state{server = Pid, + note_store = NoteStore, + mpd_state = MpdState, + sock = Sock, + log = Log} = State) -> + Domain = snmp_conf:which_domain(Addr), % What the ****... + Logger = logger(Log, read, Addr, Port), + case (catch snmpm_mpd:process_msg(Bytes, Domain, Addr, Port, + MpdState, NoteStore, Logger)) of + + {ok, Vsn, Pdu, MS, ACM} -> + maybe_handle_recv_pdu(Addr, Port, Vsn, Pdu, MS, ACM, + Logger, State); + + {discarded, Reason, Report} -> + ?vdebug("discarded: ~p", [Reason]), + ErrorInfo = {failed_processing_message, Reason}, + Pid ! {snmp_error, ErrorInfo, Addr, Port}, + maybe_udp_send(State#state.filter, Sock, Addr, Port, Report), + ok; + + {discarded, Reason} -> + ?vdebug("discarded: ~p", [Reason]), + ErrorInfo = {failed_processing_message, Reason}, + Pid ! {snmp_error, ErrorInfo, Addr, Port}, + ok; + + Error -> + error_msg("processing of received message failed: " + "~n ~p", [Error]), + ok + end. + + +maybe_handle_recv_pdu(Addr, Port, + Vsn, #pdu{type = Type} = Pdu, PduMS, ACM, + Logger, + #state{filter = FilterMod} = State) -> + case (catch FilterMod:accept_recv_pdu(Addr, Port, Type)) of + false -> + inc(netIfPduInDrops), + ok; + _ -> + handle_recv_pdu(Addr, Port, Vsn, Pdu, PduMS, ACM, Logger, State) + end; +maybe_handle_recv_pdu(Addr, Port, Vsn, Trap, PduMS, ACM, Logger, + #state{filter = FilterMod} = State) + when is_record(Trap, trappdu) -> + case (catch FilterMod:accept_recv_pdu(Addr, Port, trappdu)) of + false -> + inc(netIfPduInDrops), + ok; + _ -> + handle_recv_pdu(Addr, Port, Vsn, Trap, PduMS, ACM, Logger, State) + end; +maybe_handle_recv_pdu(Addr, Port, Vsn, Pdu, PduMS, ACM, Logger, State) -> + handle_recv_pdu(Addr, Port, Vsn, Pdu, PduMS, ACM, Logger, State). + + +handle_recv_pdu(Addr, Port, + Vsn, #pdu{type = 'inform-request'} = Pdu, _PduMS, ACM, + Logger, #state{server = Pid, irb = IRB} = State) -> + handle_inform_request(IRB, Pid, Vsn, Pdu, ACM, + Addr, Port, Logger, State); +handle_recv_pdu(Addr, Port, + _Vsn, #pdu{type = report} = Pdu, _PduMS, ok, + _Logger, + #state{server = Pid} = _State) -> + ?vtrace("received report - ok", []), + Pid ! {snmp_report, {ok, Pdu}, Addr, Port}, + ok; +handle_recv_pdu(Addr, Port, + _Vsn, #pdu{type = report} = Pdu, _PduMS, + {error, ReqId, Reason}, + _Logger, + #state{server = Pid} = _State) -> + ?vtrace("received report - error", []), + Pid ! {snmp_report, {error, ReqId, Reason, Pdu}, Addr, Port}, + ok; +handle_recv_pdu(Addr, Port, + _Vsn, #pdu{type = 'snmpv2-trap'} = Pdu, _PduMS, _ACM, + _Logger, + #state{server = Pid} = _State) -> + ?vtrace("received snmpv2-trap", []), + Pid ! {snmp_trap, Pdu, Addr, Port}, + ok; +handle_recv_pdu(Addr, Port, + _Vsn, Trap, _PduMS, _ACM, + _Logger, + #state{server = Pid} = _State) when is_record(Trap, trappdu) -> + ?vtrace("received trappdu", []), + Pid ! {snmp_trap, Trap, Addr, Port}, + ok; +handle_recv_pdu(Addr, Port, + _Vsn, Pdu, _PduMS, _ACM, + _Logger, + #state{server = Pid} = _State) when is_record(Pdu, pdu) -> + ?vtrace("received pdu", []), + Pid ! {snmp_pdu, Pdu, Addr, Port}, + ok; +handle_recv_pdu(_Addr, _Port, _Vsn, Pdu, _PduMS, ACM, _Logger, _State) -> + ?vlog("received unexpected pdu: " + "~n Pdu: ~p" + "~n ACM: ~p", [Pdu, ACM]), + ok. + + +handle_inform_request(auto, Pid, Vsn, Pdu, ACM, Addr, Port, Logger, State) -> + ?vtrace("received inform-request (true)", []), + Pid ! {snmp_inform, ignore, Pdu, Addr, Port}, + RePdu = make_response_pdu(Pdu), + maybe_send_inform_response(RePdu, Vsn, ACM, Addr, Port, Logger, State); +handle_inform_request({user, To}, Pid, Vsn, #pdu{request_id = ReqId} = Pdu, + ACM, Addr, Port, _Logger, _State) -> + ?vtrace("received inform-request (false)", []), + + Pid ! {snmp_inform, ReqId, Pdu, Addr, Port}, + + %% Before we go any further, we need to check that we have not + %% already received this message (possible resend). + + Key = {ReqId, Addr, Port}, + case ets:lookup(snmpm_inform_request_table, Key) of + [_] -> + %% OK, we already know about this. We assume this + %% is a resend. Either the agent is really eager or + %% the user has not answered yet. Bad user! + ok; + [] -> + RePdu = make_response_pdu(Pdu), + Expire = t() + To, + Rec = {Key, Expire, {Vsn, ACM, RePdu}}, + ets:insert(snmpm_inform_request_table, Rec) + end, + ok. + +handle_inform_response(Ref, Addr, Port, State) -> + Verbosity = get(verbosity), + spawn_opt(fun() -> + Log = worker_init(State, Verbosity), + Res = (catch do_handle_inform_response( + Ref, + Addr, Port, + State#state{log = Log})), + worker_exit(inform_reponse, {Addr, Port}, Res) + end, + [monitor]). + + + +do_handle_inform_response(Ref, Addr, Port, State) -> + Key = {Ref, Addr, Port}, + case ets:lookup(snmpm_inform_request_table, Key) of + [{Key, _, {Vsn, ACM, RePdu}}] -> + Logger = logger(State#state.log, read, Addr, Port), + ets:delete(snmpm_inform_request_table, Key), + maybe_send_inform_response(RePdu, Vsn, ACM, Addr, Port, + Logger, State); + [] -> + %% Already acknowledged, or the user was to slow to reply... + ok + end, + ok. + +maybe_send_inform_response(RePdu, Vsn, ACM, Addr, Port, Logger, + #state{server = Pid, + sock = Sock, + filter = FilterMod}) -> + case (catch FilterMod:accept_send_pdu(Addr, Port, pdu_type_of(RePdu))) of + false -> + inc(netIfPduOutDrops), + ok; + _ -> + case snmpm_mpd:generate_response_msg(Vsn, RePdu, ACM, Logger) of + {ok, Msg} -> + maybe_udp_send(FilterMod, Sock, Addr, Port, Msg); + {discarded, Reason} -> + ?vlog("failed generating response message:" + "~n Reason: ~p", [Reason]), + ReqId = RePdu#pdu.request_id, + ErrorInfo = {failed_generating_response, {RePdu, Reason}}, + Pid ! {snmp_error, ReqId, ErrorInfo, Addr, Port}, + ok + end + end. + +handle_inform_response_gc(#state{irb = IRB} = State) -> + ets:safe_fixtable(snmpm_inform_request_table, true), + do_irgc(ets:first(snmpm_inform_request_table), t()), + ets:safe_fixtable(snmpm_inform_request_table, false), + State#state{irgc = irgc_start(IRB)}. + +%% We are deleting at the same time as we are traversing the table!!! +do_irgc('$end_of_table', _) -> + ok; +do_irgc(Key, Now) -> + Next = ets:next(snmpm_inform_request_table, Key), + case ets:lookup(snmpm_inform_request_table, Key) of + [{Key, BestBefore, _}] when BestBefore < Now -> + ets:delete(snmpm_inform_request_table, Key); + _ -> + ok + end, + do_irgc(Next, Now). + +irgc_start(auto) -> + undefined; +irgc_start(_) -> + erlang:send_after(?IRGC_TIMEOUT, self(), inform_response_gc). + +irgc_stop(undefined) -> + ok; +irgc_stop(Ref) -> + (catch erlang:cancel_timer(Ref)). + + +handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, Port, State) -> + Verbosity = get(verbosity), + spawn_opt(fun() -> + Log = worker_init(State, Verbosity), + Res = (catch maybe_handle_send_pdu( + Pdu, Vsn, MsgData, + Domain, Addr, Port, + State#state{log = Log})), + worker_exit(send_pdu, {Domain, Addr, Port}, Res) + end, + [monitor]). + +maybe_handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, Port, + #state{filter = FilterMod} = State) -> + case (catch FilterMod:accept_send_pdu(Addr, Port, pdu_type_of(Pdu))) of + false -> + inc(netIfPduOutDrops), + ok; + _ -> + do_handle_send_pdu(Pdu, Vsn, MsgData, Domain, Addr, Port, State) + end. + +do_handle_send_pdu(Pdu, Vsn, MsgData, _Domain, Addr, Port, + #state{server = Pid, + note_store = NoteStore, + sock = Sock, + log = Log, + filter = FilterMod}) -> + Logger = logger(Log, write, Addr, Port), + case (catch snmpm_mpd:generate_msg(Vsn, NoteStore, + Pdu, MsgData, Logger)) of + {ok, Msg} -> + ?vtrace("do_handle_send_pdu -> message generated", []), + maybe_udp_send(FilterMod, Sock, Addr, Port, Msg); + {discarded, Reason} -> + ?vlog("PDU not sent: " + "~n PDU: ~p" + "~n Reason: ~p", [Pdu, Reason]), + Pid ! {snmp_error, Pdu, Reason}, + ok + end. + + +maybe_udp_send(FilterMod, Sock, Addr, Port, Msg) -> + case (catch FilterMod:accept_send(Addr, Port)) of + false -> + inc(netIfMsgOutDrops), + ok; + _ -> + udp_send(Sock, Addr, Port, Msg) + end. + + +udp_send(Sock, Addr, Port, Msg) -> + case (catch gen_udp:send(Sock, Addr, Port, Msg)) of + ok -> + ?vdebug("sent ~w bytes to ~w:~w [~w]", + [sz(Msg), Addr, Port, Sock]), + ok; + {error, Reason} -> + error_msg("failed sending message to ~p:~p: " + "~n ~p",[Addr, Port, Reason]), + ok; + Error -> + error_msg("failed sending message to ~p:~p: " + "~n ~p",[Addr, Port, Error]), + ok + end. + +sz(B) when is_binary(B) -> + size(B); +sz(L) when is_list(L) -> + length(L); +sz(_) -> + undefined. + + +handle_disk_log(_Log, {wrap, NoLostItems}, State) -> + ?vlog("Audit Trail Log - wrapped: ~w previously logged items where lost", + [NoLostItems]), + State; +handle_disk_log(_Log, {truncated, NoLostItems}, State) -> + ?vlog("Audit Trail Log - truncated: ~w items where lost when truncating", + [NoLostItems]), + State; +handle_disk_log(_Log, full, State) -> + error_msg("Failed to write to Audit Trail Log (full)", []), + State; +handle_disk_log(_Log, {error_status, ok}, State) -> + State; +handle_disk_log(_Log, {error_status, {error, Reason}}, State) -> + error_msg("Error status received from Audit Trail Log: " + "~n~p", [Reason]), + State; +handle_disk_log(_Log, _Info, State) -> + State. + + +%% mk_discovery_msg('version-3', Pdu, _VsnHdr, UserName) -> +%% ScopedPDU = #scopedPdu{contextEngineID = "", +%% contextName = "", +%% data = Pdu}, +%% Bytes = snmp_pdus:enc_scoped_pdu(ScopedPDU), +%% MsgID = get(msg_id), +%% put(msg_id,MsgID+1), +%% UsmSecParams = +%% #usmSecurityParameters{msgAuthoritativeEngineID = "", +%% msgAuthoritativeEngineBoots = 0, +%% msgAuthoritativeEngineTime = 0, +%% msgUserName = UserName, +%% msgPrivacyParameters = "", +%% msgAuthenticationParameters = ""}, +%% SecBytes = snmp_pdus:enc_usm_security_parameters(UsmSecParams), +%% PduType = Pdu#pdu.type, +%% Hdr = #v3_hdr{msgID = MsgID, +%% msgMaxSize = 1000, +%% msgFlags = snmp_misc:mk_msg_flags(PduType, 0), +%% msgSecurityModel = ?SEC_USM, +%% msgSecurityParameters = SecBytes}, +%% Msg = #message{version = 'version-3', vsn_hdr = Hdr, data = Bytes}, +%% case (catch snmp_pdus:enc_message_only(Msg)) of +%% {'EXIT', Reason} -> +%% error("Encoding error. Pdu: ~w. Reason: ~w",[Pdu, Reason]), +%% error; +%% L when list(L) -> +%% {Msg, L} +%% end; +%% mk_discovery_msg(Version, Pdu, {Com, _, _, _, _}, UserName) -> +%% Msg = #message{version = Version, vsn_hdr = Com, data = Pdu}, +%% case catch snmp_pdus:enc_message(Msg) of +%% {'EXIT', Reason} -> +%% error("Encoding error. Pdu: ~w. Reason: ~w",[Pdu, Reason]), +%% error; +%% L when list(L) -> +%% {Msg, L} +%% end. + + +%% mk_msg('version-3', Pdu, {Context, User, EngineID, CtxEngineId, SecLevel}, +%% MsgData) -> +%% %% Code copied from snmp_mpd.erl +%% {MsgId, SecName, SecData} = +%% if +%% tuple(MsgData), Pdu#pdu.type == 'get-response' -> +%% MsgData; +%% true -> +%% Md = get(msg_id), +%% put(msg_id, Md + 1), +%% {Md, User, []} +%% end, +%% ScopedPDU = #scopedPdu{contextEngineID = CtxEngineId, +%% contextName = Context, +%% data = Pdu}, +%% ScopedPDUBytes = snmp_pdus:enc_scoped_pdu(ScopedPDU), + +%% PduType = Pdu#pdu.type, +%% V3Hdr = #v3_hdr{msgID = MsgId, +%% msgMaxSize = 1000, +%% msgFlags = snmp_misc:mk_msg_flags(PduType, SecLevel), +%% msgSecurityModel = ?SEC_USM}, +%% Message = #message{version = 'version-3', vsn_hdr = V3Hdr, +%% data = ScopedPDUBytes}, +%% SecEngineID = case PduType of +%% 'get-response' -> snmp_framework_mib:get_engine_id(); +%% _ -> EngineID +%% end, +%% case catch snmp_usm:generate_outgoing_msg(Message, SecEngineID, +%% SecName, SecData, SecLevel) of +%% {'EXIT', Reason} -> +%% error("Encoding error. Pdu: ~w. Reason: ~w",[Pdu, Reason]), +%% error; +%% {error, Reason} -> +%% error("Encoding error. Pdu: ~w. Reason: ~w",[Pdu, Reason]), +%% error; +%% Packet -> +%% Packet +%% end; +%% mk_msg(Version, Pdu, {Com, _User, _EngineID, _Ctx, _SecLevel}, _SecData) -> +%% Msg = #message{version = Version, vsn_hdr = Com, data = Pdu}, +%% case catch snmp_pdus:enc_message(Msg) of +%% {'EXIT', Reason} -> +%% error("Encoding error. Pdu: ~w. Reason: ~w",[Pdu, Reason]), +%% error; +%% B when list(B) -> +%% B +%% end. + + +%% handle_system_info_updated(#state{log = {Log, _OldType}} = State, +%% audit_trail_log_type = _What) -> +%% %% Just to make sure, check that ATL is actually enabled +%% case snmpm_config:system_info(audit_trail_log) of +%% {ok, true} -> +%% {ok, Type} = snmpm_config:system_info(audit_trail_log_type), +%% NewState = State#state{log = {Log, Type}}, +%% {NewState, ok}; +%% _ -> +%% {State, {error, {adt_not_enabled}}} +%% end; +%% handle_system_info_updated(_State, _What) -> +%% ok. + +handle_get_log_type(#state{log = {_Log, Value}} = State) -> + %% Just to make sure, check that ATL is actually enabled + case snmpm_config:system_info(audit_trail_log) of + {ok, true} -> + Type = + case {lists:member(read, Value), lists:member(write, Value)} of + {true, true} -> + read_write; + {true, false} -> + read; + {false, true} -> + write; + {false, false} -> + throw({State, {error, {bad_atl_type, Value}}}) + end, + {ok, Type}; + _ -> + {error, not_enabled} + end; +handle_get_log_type(_State) -> + {error, not_enabled}. + +handle_set_log_type(#state{log = {Log, OldValue}} = State, NewType) -> + %% Just to make sure, check that ATL is actually enabled + case snmpm_config:system_info(audit_trail_log) of + {ok, true} -> + NewValue = + case NewType of + read -> + [read]; + write -> + [write]; + read_write -> + [read,write]; + _ -> + throw({State, {error, {bad_atl_type, NewType}}}) + end, + NewState = State#state{log = {Log, NewValue}}, + OldType = + case {lists:member(read, OldValue), + lists:member(write, OldValue)} of + {true, true} -> + read_write; + {true, false} -> + read; + {false, true} -> + write; + {false, false} -> + throw({State, {error, {bad_atl_type, OldValue}}}) + end, + {NewState, {ok, OldType}}; + _ -> + {State, {error, not_enabled}} + end; +handle_set_log_type(State, _NewType) -> + {State, {error, not_enabled}}. + + +%% ------------------------------------------------------------------- + +worker_init(#state{log = undefined = Log}, Verbosity) -> + worker_init2(Log, Verbosity); +worker_init(#state{log = {Name, Log, Type}}, Verbosity) -> + case snmp_log:open(Name, Log) of + {ok, NewLog} -> + worker_init2({Name, NewLog, Type}, Verbosity); + {error, Reason} -> + warning_msg("NetIf worker ~p failed opening ATL: " + "~n ~p", [self(), Reason]), + NewLog = undefined, + worker_init2({Name, NewLog, Type}, Verbosity) + end; +worker_init(State, Verbosity) -> + ?vinfo("worker_init -> entry with invalid data: " + "~n State: ~p" + "~n Verbosity: ~p", [State, Verbosity]), + exit({worker_init, State, Verbosity}). + +worker_init2(Log, Verbosity) -> + put(sname, mnifw), + put(verbosity, Verbosity), + Log. + + +worker_exit(Tag, Info, Result) -> + exit({net_if_worker, {Tag, Info, Result}}). + +handle_worker_exit(_, {_, _, ok}) -> + ok; +handle_worker_exit(Pid, {udp, {Addr, Port}, ExitStatus}) -> + warning_msg("Worker process (~p) terminated " + "while processing (incomming) message from ~w:~w: " + "~n~p", [Pid, Addr, Port, ExitStatus]), + ok; +handle_worker_exit(Pid, {send_pdu, {Domain, Addr, Port}, ExitStatus}) -> + warning_msg("Worker process (~p) terminated " + "while processing (outgoing) pdu for [~w] ~w:~w: " + "~n~p", [Pid, Domain, Addr, Port, ExitStatus]), + ok; +handle_worker_exit(Pid, {inform_response, {Addr, Port}, ExitStatus}) -> + warning_msg("Worker process (~p) terminated " + "while processing (outgoing) inform response for ~w:~w: " + "~n~p", [Pid, Addr, Port, ExitStatus]), + ok; +handle_worker_exit(_, _) -> + ok. + + +%% ------------------------------------------------------------------- + +make_response_pdu(#pdu{request_id = ReqId, varbinds = Vbs}) -> + #pdu{type = 'get-response', + request_id = ReqId, + error_status = noError, + error_index = 0, + varbinds = Vbs}. + + +%% ---------------------------------------------------------------- + +pdu_type_of(#pdu{type = Type}) -> + Type; +pdu_type_of(TrapPdu) when is_record(TrapPdu, trappdu) -> + trap. + + +%% ------------------------------------------------------------------- + +%% At this point this function is used during testing +maybe_process_extra_info(?DEFAULT_EXTRA_INFO) -> + ok; +maybe_process_extra_info({?SNMPM_EXTRA_INFO_TAG, Fun}) + when is_function(Fun, 0) -> + (catch Fun()), + ok; +maybe_process_extra_info(_ExtraInfo) -> + ok. + + +%% ------------------------------------------------------------------- + +t() -> + {A,B,C} = erlang:now(), + A*1000000000+B*1000+(C div 1000). + + +%% ------------------------------------------------------------------- + +logger(undefined, _Type, _Addr, _Port) -> + fun(_) -> + ok + end; +logger({_Name, Log, Types}, Type, Addr, Port) -> + case lists:member(Type, Types) of + true -> + fun(Msg) -> + snmp_log:log(Log, Msg, Addr, Port) + end; + false -> + fun(_) -> + ok + end + end. + + +%% ------------------------------------------------------------------- + +%% info_msg(F, A) -> +%% ?snmpm_info("NET-IF server: " ++ F, A). + +warning_msg(F, A) -> + ?snmpm_warning("NET-IF server: " ++ F, A). + +error_msg(F, A) -> + ?snmpm_error("NET-IF server: " ++ F, A). + + + +%%%------------------------------------------------------------------- + +% get_opt(Key, Opts) -> +% ?vtrace("get option ~w", [Key]), +% snmp_misc:get_option(Key, Opts). + +get_opt(Opts, Key, Def) -> + ?vtrace("get option ~w with default ~p", [Key, Def]), + snmp_misc:get_option(Key, Opts, Def). + + +%% ------------------------------------------------------------------- + +get_info(#state{sock = Id}) -> + ProcSize = proc_mem(self()), + PortInfo = get_port_info(Id), + [{process_memory, ProcSize}, {port_info, PortInfo}]. + +proc_mem(P) when is_pid(P) -> + case (catch erlang:process_info(P, memory)) of + {memory, Sz} when is_integer(Sz) -> + Sz; + _ -> + undefined + end. +%% proc_mem(_) -> +%% undefined. + + +get_port_info(Id) -> + PortInfo = + case (catch erlang:port_info(Id)) of + PI when is_list(PI) -> + [{port_info, PI}]; + _ -> + [] + end, + PortStatus = + case (catch prim_inet:getstatus(Id)) of + {ok, PS} -> + [{port_status, PS}]; + _ -> + [] + end, + PortAct = + case (catch inet:getopts(Id, [active])) of + {ok, PA} -> + [{port_act, PA}]; + _ -> + [] + end, + PortStats = + case (catch inet:getstat(Id)) of + {ok, Stat} -> + [{port_stats, Stat}]; + _ -> + [] + end, + IfList = + case (catch inet:getif(Id)) of + {ok, IFs} -> + [{interfaces, IFs}]; + _ -> + [] + end, + BufSz = + case (catch inet:getopts(Id, [recbuf, sndbuf, buffer])) of + {ok, Sz} -> + [{buffer_size, Sz}]; + _ -> + [] + end, + [{socket, Id}] ++ + IfList ++ + PortStats ++ + PortInfo ++ + PortStatus ++ + PortAct ++ + BufSz. + + +%%----------------------------------------------------------------- +%% Counter functions +%%----------------------------------------------------------------- +init_counters() -> + F = fun(Counter) -> maybe_create_counter(Counter) end, + lists:map(F, counters()). + +reset_counters() -> + F = fun(Counter) -> snmpm_config:reset_stats_counter(Counter) end, + lists:map(F, counters()). + +maybe_create_counter(Counter) -> + snmpm_config:maybe_cre_stats_counter(Counter, 0). + +counters() -> + [ + netIfMsgOutDrops, + netIfMsgInDrops, + netIfPduOutDrops, + netIfPduInDrops + ]. + +inc(Name) -> inc(Name, 1). +inc(Name, N) -> snmpm_config:incr_stats_counter(Name, N). + +%% get_counters() -> +%% Counters = counters(), +%% get_counters(Counters, []). + +%% get_counters([], Acc) -> +%% lists:reverse(Acc); +%% get_counters([Counter|Counters], Acc) -> +%% case snmpm_config:get_stats_counter(Counter) of +%% {ok, CounterVal} -> +%% get_counters(Counters, [{Counter, CounterVal}|Acc]); +%% _ -> +%% get_counters(Counters, Acc) +%% end. + + +%% ---------------------------------------------------------------- + +call(Pid, Req) -> + call(Pid, Req, infinity). + +call(Pid, Req, Timeout) -> + gen_server:call(Pid, Req, Timeout). + +cast(Pid, Msg) -> + gen_server:cast(Pid, Msg). + diff --git a/lib/snmp/src/misc/snmp_conf.erl b/lib/snmp/src/misc/snmp_conf.erl index 7249def24e..e1e7fab57b 100644 --- a/lib/snmp/src/misc/snmp_conf.erl +++ b/lib/snmp/src/misc/snmp_conf.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2011. All Rights Reserved. +%% Copyright Ericsson AB 1996-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -71,6 +71,18 @@ %%----------------------------------------------------------------- +%% read_files(Dir, Files) -> Configs +%% Dir - string() - Full path to the config dir. +%% Files - [{Gen, Filter, Check, FileName}] +%% Gen - function/2 - In case of failure when reading the config file, +%% this function is called to either generate a +%% default file or issue the error. +%% Filter - function/1 - Filters all the config entries read from the file +%% Check - function/1 - Check each entry as they are read from the file. +%% FileName - string() - Name of the config file. +%% Configs - [config_entry()] +%% config_entry() - term() + read_files(Dir, Files) when is_list(Dir) andalso is_list(Files) -> read_files(Dir, Files, []). @@ -90,7 +102,7 @@ read_files(Dir, [{Gen, Filter, Check, FileName}|Files], Res) {error, R} -> ?vlog("failed reading file info for ~s: " "~n ~p", [FileName, R]), - Gen(Dir), + Gen(Dir, R), read_files(Dir, Files, [Filter([])|Res]) end. @@ -99,6 +111,7 @@ read_files(Dir, [{Gen, Filter, Check, FileName}|Files], Res) read(File, Check) when is_function(Check) -> ?vdebug("read -> entry with" "~n File: ~p", [File]), + Fd = open_file(File), case loop(Fd, [], Check, 1, File) of diff --git a/lib/snmp/src/misc/snmp_config.erl b/lib/snmp/src/misc/snmp_config.erl index 6ab20e3e48..1da2c339c7 100644 --- a/lib/snmp/src/misc/snmp_config.erl +++ b/lib/snmp/src/misc/snmp_config.erl @@ -90,6 +90,17 @@ ]). +-export_type([void/0, + verify_config_entry_function/0, + verify_config_function/0, + write_config_function/0]). + + +%%---------------------------------------------------------------------- + +-type void() :: term(). % Any value - ignored + + %%---------------------------------------------------------------------- %% Handy SNMP configuration %%---------------------------------------------------------------------- @@ -2356,53 +2367,109 @@ write_sys_config_file_manager_atl_opt(Fid, {seqno, SeqNo}) -> header() -> - {Y,Mo,D} = date(), - {H,Mi,S} = time(), + {Y, Mo, D} = date(), + {H, Mi, S} = time(), io_lib:format("%% This file was generated by " - "snmp_config (version-~s) ~w-~2.2.0w-~2.2.0w " + "~w (version-~s) ~w-~2.2.0w-~2.2.0w " "~2.2.0w:~2.2.0w:~2.2.0w\n", - [?version,Y,Mo,D,H,Mi,S]). + [?MODULE, ?version, Y, Mo, D, H, Mi, S]). + +%% *If* these functions are successfull, they successfully return anything +%% (which is ignored), but they fail with either a throw or an exit or +%% something similar. + +%% Verification of one config entry read from a file +-type(verify_config_entry_function() :: + fun((Entry :: term()) -> ok | {error, Reason :: term()})). + +%% Verification of config to be written +-type(verify_config_function() :: + fun(() -> void())). + +%% Write config to file (as defined by Fd) +-type(write_config_function() :: + fun((Fd :: file:io_device()) -> void())). + +-spec write_config_file(Dir :: string(), + FileName :: string(), + Verify :: verify_config_function(), + Write :: write_config_function()) -> + ok | {error, Reason :: term()}. write_config_file(Dir, FileName, Verify, Write) when (is_list(Dir) andalso is_list(FileName) andalso is_function(Verify) andalso is_function(Write)) -> - (catch do_write_config_file(Dir, FileName, Verify, Write)). + try + begin + do_write_config_file(Dir, FileName, Verify, Write) + end + catch + throw:Error -> + Error; + T:E -> + {error, {failed_write, Dir, FileName, T, E}} + end. + do_write_config_file(Dir, FileName, Verify, Write) -> Verify(), case file:open(filename:join(Dir, FileName), [write]) of {ok, Fd} -> - (catch Write(Fd)), - file:close(Fd), - ok; + file_write_and_close(Write, Fd, Dir, FileName); Error -> Error end. - append_config_file(Dir, FileName, Verify, Write) when (is_list(Dir) andalso is_list(FileName) andalso is_function(Verify) andalso is_function(Write)) -> - (catch do_append_config_file(Dir, FileName, Verify, Write)). + try + begin + do_append_config_file(Dir, FileName, Verify, Write) + end + catch + throw:Error -> + Error; + T:E -> + {error, {failed_append, Dir, FileName, T, E}} + end. do_append_config_file(Dir, FileName, Verify, Write) -> Verify(), case file:open(filename:join(Dir, FileName), [read, write]) of {ok, Fd} -> file:position(Fd, eof), - (catch Write(Fd)), - file:close(Fd), - ok; + file_write_and_close(Write, Fd, Dir, FileName); Error -> Error end. +file_write_and_close(Write, Fd, Dir, FileName) -> + ok = Write(Fd), + case file:sync(Fd) of + ok -> + case file:close(Fd) of + ok -> + ok; + {error, Reason} -> + {error, {failed_closing, Dir, FileName, Reason}} + end; + {error, Reason} -> + {error, {failed_syncing, Dir, FileName, Reason}} + end. + + +-spec read_config_file(Dir :: string(), + FileName :: string(), + Verify :: verify_config_entry_function()) -> + {ok, Config :: list()} | {error, Reason :: term()}. + read_config_file(Dir, FileName, Verify) when is_list(Dir) andalso is_list(FileName) andalso is_function(Verify) -> (catch do_read_config_file(Dir, FileName, Verify)). diff --git a/lib/snmp/src/misc/snmp_log.erl b/lib/snmp/src/misc/snmp_log.erl index 2c781810ef..a8c5df0b64 100644 --- a/lib/snmp/src/misc/snmp_log.erl +++ b/lib/snmp/src/misc/snmp_log.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2011. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -21,7 +21,7 @@ -export([ - create/4, create/5, create/6, + create/4, create/5, create/6, open/1, open/2, change_size/2, close/1, sync/1, info/1, log/4, log_to_txt/5, log_to_txt/6, log_to_txt/7, @@ -109,6 +109,24 @@ create(Name, File, SeqNoGen, Size, Repair, Notify) -> {error, {bad_args, Name, File, SeqNoGen, Size, Repair, Notify}}. +%% -- open --- + +%% Open an already existing ( = open ) log + +open(Name) -> + open(Name, #snmp_log{seqno = disabled}). +open(Name, #snmp_log{seqno = SeqNoGen} = _OldLog) -> + %% We include mode in the opts just to be on the safe side + case disk_log:open([{name, Name}, {mode, read_write}]) of + {ok, Log} -> + %% SeqNo must be proprly initiated also + {ok, #snmp_log{id = Log, seqno = SeqNoGen}}; + {repaired, Log, _RecBytes, _BadBytes} -> + {ok, #snmp_log{id = Log, seqno = SeqNoGen}}; + ERROR -> + ERROR + end. + %% -- close --- @@ -394,6 +412,14 @@ log_to_io(Log, FileName, Dir, Mibs, Start) -> log_to_io(Log, FileName, Dir, Mibs, Start, Stop) when is_list(Mibs) -> + ?vtrace("log_to_io -> entry with" + "~n Log: ~p" + "~n FileName: ~p" + "~n Dir: ~p" + "~n Mibs: ~p" + "~n Start: ~p" + "~n Stop: ~p", + [Log, FileName, Dir, Mibs, Start, Stop]), File = filename:join(Dir, FileName), Converter = fun(L) -> do_log_to_io(L, Mibs, Start, Stop) @@ -401,28 +427,10 @@ log_to_io(Log, FileName, Dir, Mibs, Start, Stop) log_convert(Log, File, Converter). -%% -- log_to_plain --- - -%% log_to_plain(Log, FileName, Dir) -> -%% log_to_plain(Log, FileName, Dir, null, null). - -%% log_to_plain(Log, FileName, Dir, Start) -> -%% log_to_plain(Log, FileName, Dir, Start, null). - -%% log_to_plain(Log, FileName, Dir, Start, Stop) -%% when is_list(Mibs) -> -%% File = filename:join(Dir, FileName), -%% Converter = fun(L) -> -%% do_log_to_plain(L, Start, Stop) -%% end, -%% log_convert(Log, File, Converter). - - %% -------------------------------------------------------------------- %% Internal functions %% -------------------------------------------------------------------- - %% -- log_convert --- log_convert(#snmp_log{id = Log}, File, Converter) -> @@ -431,6 +439,26 @@ log_convert(Log, File, Converter) -> do_log_convert(Log, File, Converter). do_log_convert(Log, File, Converter) -> + %% ?vtrace("do_log_converter -> entry with" + %% "~n Log: ~p" + %% "~n File: ~p" + %% "~n disk_log:info(Log): ~p", [Log, File, disk_log:info(Log)]), + {Pid, Ref} = + erlang:spawn_monitor( + fun() -> + Result = do_log_convert2(Log, File, Converter), + exit(Result) + end), + receive + {'DOWN', Ref, process, Pid, Result} -> + %% ?vtrace("do_log_converter -> received result" + %% "~n Result: ~p" + %% "~n disk_log:info(Log): ~p", + %% [Result, disk_log:info(Log)]), + Result + end. + +do_log_convert2(Log, File, Converter) -> %% First check if the caller process has already opened the %% log, because if we close an already open log we will cause %% a runtime error. @@ -439,29 +467,18 @@ do_log_convert(Log, File, Converter) -> Converter(Log); false -> %% Not yet member of the ruling party, apply for membership... - %% If a log is opened as read_write it is not possible to - %% open it as read_only. So, to get around this we open - %% it under a different name... - Log2 = convert_name(Log), - case log_open(Log2, File) of + case log_open(Log, File) of {ok, _} -> - Res = Converter(Log2), - disk_log:close(Log2), + Res = Converter(Log), + disk_log:close(Log), Res; {error, {name_already_open, _}} -> - Converter(Log2); + Converter(Log); {error, Reason} -> {error, {Log, Reason}} end end. -convert_name(Name) when is_list(Name) -> - Name ++ "_tmp"; -convert_name(Name) when is_atom(Name) -> - list_to_atom(atom_to_list(Name) ++ "_tmp"); -convert_name(Name) -> - lists:flatten(io_lib:format("~w_tmp", [Name])). - %% -- do_log_to_text --- @@ -705,21 +722,21 @@ tsf_ge(_Local,Universal,{universal_time,DateTime}) -> tsf_ge(Local,_Universal,DateTime) -> tsf_ge(Local,DateTime). -tsf_ge(TimeStamp,DateTime) -> +tsf_ge(TimeStamp, DateTime) -> T1 = calendar:datetime_to_gregorian_seconds(TimeStamp), T2 = calendar:datetime_to_gregorian_seconds(DateTime), T1 >= T2. -tsf_le(_Local,_Universal,null) -> +tsf_le(_Local, _Universal, null) -> true; -tsf_le(Local,_Universal,{local_time,DateTime}) -> - tsf_le(Local,DateTime); -tsf_le(_Local,Universal,{universal_time,DateTime}) -> - tsf_le(Universal,DateTime); -tsf_le(Local,_Universal,DateTime) -> +tsf_le(Local, _Universal, {local_time, DateTime}) -> + tsf_le(Local, DateTime); +tsf_le(_Local, Universal, {universal_time, DateTime}) -> + tsf_le(Universal, DateTime); +tsf_le(Local, _Universal, DateTime) -> tsf_le(Local,DateTime). -tsf_le(TimeStamp,DateTime) -> +tsf_le(TimeStamp, DateTime) -> T1 = calendar:datetime_to_gregorian_seconds(TimeStamp), T2 = calendar:datetime_to_gregorian_seconds(DateTime), T1 =< T2. @@ -864,11 +881,8 @@ do_std_log_open(Name, File, Size, Repair, Notify) -> log_open(Name, File) -> - Opts = [{name, Name}, - {file, File}, - {type, ?LOG_TYPE}, - {format, ?LOG_FORMAT}, - {mode, read_only}], + Opts = [{name, Name}, + {file, File}], case disk_log:open(Opts) of {error, {badarg, size}} -> {error, no_such_log}; diff --git a/lib/snmp/src/misc/snmp_verbosity.erl b/lib/snmp/src/misc/snmp_verbosity.erl index 85037ba2ae..df5986b7bc 100644 --- a/lib/snmp/src/misc/snmp_verbosity.erl +++ b/lib/snmp/src/misc/snmp_verbosity.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2009. All Rights Reserved. +%% Copyright Ericsson AB 2000-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -76,7 +76,7 @@ format_timestamp({_N1, _N2, N3} = Now) -> {YYYY,MM,DD} = Date, {Hour,Min,Sec} = Time, FormatDate = - io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w 4~w", + io_lib:format("~.4w:~.2.0w:~.2.0w ~.2.0w:~.2.0w:~.2.0w ~w", [YYYY,MM,DD,Hour,Min,Sec,round(N3/1000)]), lists:flatten(FormatDate). @@ -144,6 +144,8 @@ image_of_sname(mse) -> "M-SERVER"; image_of_sname(msew) -> io_lib:format("M-SERVER-worker(~p)", [self()]); image_of_sname(mns) -> "M-NOTE-STORE"; image_of_sname(mnif) -> "M-NET-IF"; +image_of_sname(mnifl) -> "M-NET-IF-LOGGER"; +image_of_sname(mnifw) -> io_lib:format("M-NET-IF-worker(~p)", [self()]); image_of_sname(mconf) -> "M-CONF"; image_of_sname(mgr) -> "MGR"; diff --git a/lib/snmp/test/Makefile b/lib/snmp/test/Makefile index 78ffb1c255..8c1f53e51a 100644 --- a/lib/snmp/test/Makefile +++ b/lib/snmp/test/Makefile @@ -224,6 +224,9 @@ $(SNMP_BIN_TARGET_DIR)/Klas4.bin: $(SNMP_BIN_TARGET_DIR)/Klas3.bin $(SNMP_BIN_TARGET_DIR)/SA-MIB.bin: $(SNMP_BIN_TARGET_DIR)/OLD-SNMPEA-MIB.bin +$(SNMP_BIN_TARGET_DIR)/Test3.bin: $(SNMP_BIN_TARGET_DIR)/Test2.bin + + # ---------------------------------------------------- # Release Target # ---------------------------------------------------- diff --git a/lib/snmp/test/exp/.gitignore b/lib/snmp/test/exp/.gitignore new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/lib/snmp/test/exp/.gitignore diff --git a/lib/snmp/test/snmp_agent_bl_test.erl b/lib/snmp/test/exp/snmp_agent_bl_test.erl index b17489a755..b17489a755 100644 --- a/lib/snmp/test/snmp_agent_bl_test.erl +++ b/lib/snmp/test/exp/snmp_agent_bl_test.erl diff --git a/lib/snmp/test/snmp_agent_ms_test.erl b/lib/snmp/test/exp/snmp_agent_ms_test.erl index 1f34f1c8d1..1f34f1c8d1 100644 --- a/lib/snmp/test/snmp_agent_ms_test.erl +++ b/lib/snmp/test/exp/snmp_agent_ms_test.erl diff --git a/lib/snmp/test/snmp_agent_mt_test.erl b/lib/snmp/test/exp/snmp_agent_mt_test.erl index 4f125c0017..4f125c0017 100644 --- a/lib/snmp/test/snmp_agent_mt_test.erl +++ b/lib/snmp/test/exp/snmp_agent_mt_test.erl diff --git a/lib/snmp/test/snmp_agent_v1_test.erl b/lib/snmp/test/exp/snmp_agent_v1_test.erl index 737bb25cc3..737bb25cc3 100644 --- a/lib/snmp/test/snmp_agent_v1_test.erl +++ b/lib/snmp/test/exp/snmp_agent_v1_test.erl diff --git a/lib/snmp/test/snmp_agent_v2_test.erl b/lib/snmp/test/exp/snmp_agent_v2_test.erl index dc94c18ad9..dc94c18ad9 100644 --- a/lib/snmp/test/snmp_agent_v2_test.erl +++ b/lib/snmp/test/exp/snmp_agent_v2_test.erl diff --git a/lib/snmp/test/snmp_agent_v3_test.erl b/lib/snmp/test/exp/snmp_agent_v3_test.erl index 266be72878..266be72878 100644 --- a/lib/snmp/test/snmp_agent_v3_test.erl +++ b/lib/snmp/test/exp/snmp_agent_v3_test.erl diff --git a/lib/snmp/test/modules.mk b/lib/snmp/test/modules.mk index eacc749b53..7b0bdc5b8f 100644 --- a/lib/snmp/test/modules.mk +++ b/lib/snmp/test/modules.mk @@ -76,7 +76,8 @@ MIB_FILES = \ TestTrap.mib \ TestTrapv2.mib \ Test1.mib \ - Test2.mib + Test2.mib \ + Test3.mib SPECS = snmp.spec snmp.spec.vxworks diff --git a/lib/snmp/test/snmp_SUITE.erl b/lib/snmp/test/snmp_SUITE.erl index b6d72da2fa..22b9c64588 100644 --- a/lib/snmp/test/snmp_SUITE.erl +++ b/lib/snmp/test/snmp_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2011. All Rights Reserved. +%% Copyright Ericsson AB 1997-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -19,6 +19,8 @@ -module(snmp_SUITE). +-include("snmp_test_lib.hrl"). + -export([all/0, suite/0, groups/0, @@ -39,6 +41,21 @@ end_per_testcase(_Case, Config) when is_list(Config) -> Config. +init_per_suite(Config) when is_list(Config) -> + + ?DBG("init_per_suite -> entry with" + "~n Config: ~p", [Config]), + + Config. + +end_per_suite(Config) when is_list(Config) -> + + ?DBG("end_per_suite -> entry with" + "~n Config: ~p", [Config]), + + Config. + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Top test case @@ -53,7 +70,8 @@ all() -> {group, manager}]. groups() -> - [{app, [], [{group, app_test}, + [ + {app, [], [{group, app_test}, {group, appup_test}]}, {compiler, [], [{group, compiler_test}]}, {misc, [], [{group, conf_test}, @@ -66,6 +84,7 @@ groups() -> {manager, [], [{group, manager_config_test}, {group, manager_user_test}, {group, manager_test}]}, + {app_test, [], [{snmp_app_test, all}]}, {appup_test, [], [{snmp_appup_test, all}]}, {compiler_test, [], [{snmp_compiler_test, all}]}, @@ -78,17 +97,25 @@ groups() -> {agent_test, [], [{snmp_agent_test, all}]}, {manager_config_test, [], [{snmp_manager_config_test, all}]}, {manager_user_test, [], [{snmp_manager_user_test, all}]}, - {manager_test, [], [{snmp_manager_test, all}]}]. + {manager_test, [], [{snmp_manager_test, all}]} + ]. -init_per_suite(Config) -> - Config. -end_per_suite(_Config) -> - ok. +init_per_group(GroupName, Config0) -> -init_per_group(_GroupName, Config) -> - Config. + ?DBG("init_per_group -> entry with" + "~n GroupName: ~p" + "~n Config0: ~p", [GroupName, Config0]), + + %% Group name is not really the suite name + %% (but it is a good enough approximation), + %% but it does not matter since we only need + %% it to be unique. + snmp_test_lib:init_suite_top_dir(GroupName, Config0). + end_per_group(_GroupName, Config) -> - Config. + lists:keydelete(snmp_suite_top_dir, 1, Config). + + diff --git a/lib/snmp/test/snmp_agent_test.erl b/lib/snmp/test/snmp_agent_test.erl index e968bc65b1..8ee5dd534d 100644 --- a/lib/snmp/test/snmp_agent_test.erl +++ b/lib/snmp/test/snmp_agent_test.erl @@ -224,52 +224,82 @@ groups() -> }, {tickets2, [], [otp8395, otp9884]}, {otp_4394, [], [otp_4394_test]}, - {otp_7157, [], [otp_7157_test] - } + {otp_7157, [], [otp_7157_test]} ]. -init_per_group(all_tcs, Config) -> - init_all(Config); -init_per_group(otp_7157, Config) -> - init_otp_7157(Config); -init_per_group(otp_4394, Config) -> - init_otp_4394(Config); -init_per_group(v2_inform, Config) -> - init_v2_inform(Config); -init_per_group(multiple_reqs_2, Config) -> - init_mul(Config); -init_per_group(multiple_reqs, Config) -> - init_mul(Config); -init_per_group(test_multi_threaded, Config) -> - init_mt(Config); -init_per_group(test_v3, Config) -> - init_v3(Config); -init_per_group(test_v1_v2, Config) -> - init_v1_v2(Config); -init_per_group(test_v2, Config) -> - init_v2(Config); -init_per_group(test_v1, Config) -> - init_v1(Config); -init_per_group(misc, Config) -> - init_misc(Config); -init_per_group(mib_storage_varm_mnesia, Config) -> - init_varm_mib_storage_mnesia(Config); -init_per_group(mib_storage_varm_dets, Config) -> - init_varm_mib_storage_dets(Config); -init_per_group(mib_storage_size_check_mnesia, Config) -> - init_size_check_msm(Config); -init_per_group(mib_storage_size_check_dets, Config) -> - init_size_check_msd(Config); -init_per_group(mib_storage_size_check_ets, Config) -> - init_size_check_mse(Config); -init_per_group(mib_storage_mnesia, Config) -> - init_mib_storage_mnesia(Config); -init_per_group(mib_storage_dets, Config) -> - init_mib_storage_dets(Config); -init_per_group(mib_storage_ets, Config) -> - init_mib_storage_ets(Config); -init_per_group(_GroupName, Config) -> - Config. + +init_per_suite(Config0) when is_list(Config0) -> + + ?DBG("init_per_suite -> entry with" + "~n Config0: ~p", [Config0]), + + Config1 = snmp_test_lib:init_suite_top_dir(?MODULE, Config0), + Config2 = snmp_test_lib:fix_data_dir(Config1), + + %% Mib-dirs + MibDir = snmp_test_lib:lookup(data_dir, Config2), + StdMibDir = filename:join([code:priv_dir(snmp), "mibs"]), + + Config3 = [{mib_dir, MibDir}, {std_mib_dir, StdMibDir} | Config2], + + ?DBG("init_per_suite -> end with" + "~n Config3: ~p", [Config3]), + + Config3. + +end_per_suite(Config) when is_list(Config) -> + + ?DBG("end_per_suite -> entry with" + "~n Config: ~p", [Config]), + + Config. + + +init_per_group(all_tcs = GroupName, Config) -> + init_all(snmp_test_lib:init_group_top_dir(GroupName, Config)); +init_per_group(otp_7157 = GroupName, Config) -> + init_otp_7157(snmp_test_lib:init_group_top_dir(GroupName, Config)); +init_per_group(otp_4394 = GroupName, Config) -> + init_otp_4394(snmp_test_lib:init_group_top_dir(GroupName, Config)); +init_per_group(v2_inform = GroupName, Config) -> + init_v2_inform(snmp_test_lib:init_group_top_dir(GroupName, Config)); +init_per_group(multiple_reqs_2 = GroupName, Config) -> + init_mul(snmp_test_lib:init_group_top_dir(GroupName, Config)); +init_per_group(multiple_reqs = GroupName, Config) -> + init_mul(snmp_test_lib:init_group_top_dir(GroupName, Config)); +init_per_group(test_multi_threaded = GroupName, Config) -> + init_mt(snmp_test_lib:init_group_top_dir(GroupName, Config)); +init_per_group(test_v3 = GroupName, Config) -> + init_v3(snmp_test_lib:init_group_top_dir(GroupName, Config)); +init_per_group(test_v1_v2 = GroupName, Config) -> + init_v1_v2(snmp_test_lib:init_group_top_dir(GroupName, Config)); +init_per_group(test_v2 = GroupName, Config) -> + init_v2(snmp_test_lib:init_group_top_dir(GroupName, Config)); +init_per_group(test_v1 = GroupName, Config) -> + init_v1(snmp_test_lib:init_group_top_dir(GroupName, Config)); +init_per_group(misc = GroupName, Config) -> + init_misc(snmp_test_lib:init_group_top_dir(GroupName, Config)); +init_per_group(mib_storage_varm_mnesia = GroupName, Config) -> + init_varm_mib_storage_mnesia(snmp_test_lib:init_group_top_dir(GroupName, + Config)); +init_per_group(mib_storage_varm_dets = GroupName, Config) -> + init_varm_mib_storage_dets(snmp_test_lib:init_group_top_dir(GroupName, + Config)); +init_per_group(mib_storage_size_check_mnesia = GroupName, Config) -> + init_size_check_msm(snmp_test_lib:init_group_top_dir(GroupName, Config)); +init_per_group(mib_storage_size_check_dets = GroupName, Config) -> + init_size_check_msd(snmp_test_lib:init_group_top_dir(GroupName, Config)); +init_per_group(mib_storage_size_check_ets = GroupName, Config) -> + init_size_check_mse(snmp_test_lib:init_group_top_dir(GroupName, Config)); +init_per_group(mib_storage_mnesia = GroupName, Config) -> + init_mib_storage_mnesia(snmp_test_lib:init_group_top_dir(GroupName, + Config)); +init_per_group(mib_storage_dets = GroupName, Config) -> + init_mib_storage_dets(snmp_test_lib:init_group_top_dir(GroupName, Config)); +init_per_group(mib_storage_ets = GroupName, Config) -> + init_mib_storage_ets(snmp_test_lib:init_group_top_dir(GroupName, Config)); +init_per_group(GroupName, Config) -> + snmp_test_lib:init_group_top_dir(GroupName, Config). end_per_group(all_tcs, Config) -> finish_all(Config); @@ -320,38 +350,36 @@ init_per_testcase(otp8395 = Case, Config) when is_list(Config) -> ?DBG("init_per_testcase -> entry with" "~n Case: ~p" "~n Config: ~p", [Case, Config]), - Config2 = init_per_testcase2(Case, init_per_suite(Config)), - otp8395({init, Config2}); + otp8395({init, init_per_testcase2(Case, Config)}); init_per_testcase(otp9884 = Case, Config) when is_list(Config) -> ?DBG("init_per_testcase -> entry with" "~n Case: ~p" "~n Config: ~p", [Case, Config]), - Config2 = init_per_testcase2(Case, init_per_suite(Config)), - otp9884({init, Config2}); + otp9884({init, init_per_testcase2(Case, Config)}); init_per_testcase(otp_7157_test = _Case, Config) when is_list(Config) -> ?DBG("init_per_testcase -> entry with" "~n Case: ~p" "~n Config: ~p", [_Case, Config]), Dog = ?WD_START(?MINS(1)), - [{watchdog, Dog}|Config]; + [{watchdog, Dog} | Config ]; init_per_testcase(v2_inform_i = _Case, Config) when is_list(Config) -> ?DBG("init_per_testcase -> entry with" "~n Case: ~p" "~n Config: ~p", [_Case, Config]), Dog = ?WD_START(?MINS(10)), - [{watchdog, Dog}|Config]; + [{watchdog, Dog} | Config ]; init_per_testcase(v3_inform_i = _Case, Config) when is_list(Config) -> ?DBG("init_per_testcase -> entry with" "~n Case: ~p" "~n Config: ~p", [_Case, Config]), Dog = ?WD_START(?MINS(10)), - [{watchdog, Dog}|Config]; + [{watchdog, Dog} | Config ]; init_per_testcase(_Case, Config) when is_list(Config) -> ?DBG("init_per_testcase -> entry with" "~n Case: ~p" "~n Config: ~p", [_Case, Config]), Dog = ?WD_START(?MINS(6)), - [{watchdog, Dog}|Config]. + [{watchdog, Dog}| Config ]. end_per_testcase(otp8395, Config) when is_list(Config) -> otp8395({fin, Config}); @@ -366,65 +394,13 @@ end_per_testcase(_Case, Config) when is_list(Config) -> Config. -init_per_suite(Config) -> - ?DBG("init_per_suite -> entry with" - "~n Config: ~p", [Config]), - - %% Suite root dir for test suite - PrivDir = ?config(priv_dir, Config), - - %% Create top-directory for this sub-suite - SuiteTopDir = filename:join([PrivDir, ?MODULE]), - case file:make_dir(SuiteTopDir) of - ok -> - ok; - {error, eexist} -> - %% This can happen since this is not really a - %% suite-init function. - ok; - {error, Reason} -> - ?FAIL({failed_creating_suite_top_dir, SuiteTopDir, Reason}) - end, - - - %% -- - %% Fix config (data-dir is not correct): - %% - - Config1 = fix_data_dir(Config), - %% Config1 = Config, - - %% Mib-dirs - MibDir = ?config(data_dir, Config1), - StdMibDir = filename:join([code:priv_dir(snmp), "mibs"]), - - Config2 = [{suite_top_dir, SuiteTopDir}, - {mib_dir, MibDir}, - {std_mib_dir, StdMibDir} | Config1], - - ?DBG("init_per_suite -> done when" - "~n Config2: ~p", [Config2]), - Config2. - -%% end_per_suite(Config) -> -end_per_suite(Config) -> - Config. - -fix_data_dir(Config) -> - DataDir0 = ?config(data_dir, Config), - DataDir1 = filename:split(filename:absname(DataDir0)), - [_|DataDir2] = lists:reverse(DataDir1), - DataDir = filename:join(lists:reverse(DataDir2) ++ [?snmp_test_data]), - Config1 = lists:keydelete(data_dir, 1, Config), - [{data_dir, DataDir} | Config1]. +init_per_testcase2(Case, Config) -> + ?DBG("end_per_testcase2 -> entry with" + "~n Case: ~p" + "~n Config: ~p", [Case, Config]), -init_per_testcase2(Case, Config) -> - SuiteToDir = ?config(suite_top_dir, Config), - - %% Create top-directory for this test-case - CaseTopDir = filename:join([SuiteToDir, Case]), - ok = file:make_dir(CaseTopDir), + CaseTopDir = snmp_test_lib:init_testcase_top_dir(Case, Config), %% Create agent top-dir(s) AgentTopDir = filename:join([CaseTopDir, agent]), @@ -623,19 +599,19 @@ mib_storage_mnesia_cases() -> msm_mib_of]. mse_size_check_cases() -> -[mse_size_check]. + [mse_size_check]. msd_size_check_cases() -> -[msd_size_check]. + [msd_size_check]. msm_size_check_cases() -> -[msm_size_check]. + [msm_size_check]. varm_mib_storage_dets_cases() -> -[msd_varm_mib_start]. + [msd_varm_mib_start]. varm_mib_storage_mnesia_cases() -> -[msm_varm_mib_start]. + [msm_varm_mib_start]. init_mib_storage_ets(Config) when is_list(Config) -> ?LOG("init_mib_storage_ets -> entry", []), @@ -644,36 +620,37 @@ init_mib_storage_ets(Config) when is_list(Config) -> init_mib_storage_dets(Config) when is_list(Config) -> ?LOG("init_mib_storage_ets -> entry", []), - ?line AgentDir = ?GCONF(agent_dir, Config), - MibStorage = {snmp_mib_storage,{dets,AgentDir}}, + ?line AgentDbDir = ?GCONF(agent_db_dir, Config), + MibStorage = {snmp_mib_storage, {dets, AgentDbDir}}, init_ms(Config, [MibStorage]). init_mib_storage_mnesia(Config) when is_list(Config) -> ?LOG("init_mib_storage_ets -> entry", []), - MibStorage = {snmp_mib_storage,{mnesia,[]}}, + MibStorage = {snmp_mib_storage, {mnesia,[]}}, init_ms(Config, [MibStorage]). init_ms(Config, Opts) when is_list(Config) -> ?LOG("init_mib_storage_ets -> entry", []), - ?line SaNode = ?GCONF(snmp_sa, Config), + ?line SaNode = ?GCONF(snmp_sa, Config), ?line create_tables(SaNode), - ?line AgentDir = ?GCONF(agent_dir, Config), - ?line MgrDir = ?GCONF(mgr_dir, Config), - ?line Ip = ?GCONF(ip, Config), - ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + ?line AgentConfDir = ?GCONF(agent_conf_dir, Config), + ?line MgrDir = ?GCONF(mgr_dir, Config), + ?line Ip = ?GCONF(ip, Config), + ?line config([v1], MgrDir, AgentConfDir, + tuple_to_list(Ip), tuple_to_list(Ip)), MasterAgentVerbosity = {snmp_master_agent_verbosity, trace}, MibsVerbosity = {snmp_mibserver_verbosity, trace}, SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace}, - Opts1 = [MasterAgentVerbosity,MibsVerbosity,SymStoreVerbosity|Opts], - [{vsn, v1} | start_v1_agent(Config,Opts1)]. + Opts1 = [MasterAgentVerbosity, MibsVerbosity, SymStoreVerbosity | Opts], + [{vsn, v1} | start_v1_agent(Config, Opts1)]. init_size_check_mse(Config) when is_list(Config) -> MibStorage = {snmp_mib_storage, ets}, init_size_check_ms(Config, [MibStorage]). init_size_check_msd(Config) when is_list(Config) -> - AgentDir = ?GCONF(agent_dir, Config), - MibStorage = {snmp_mib_storage, {dets, AgentDir}}, + AgentDbDir = ?GCONF(agent_db_dir, Config), + MibStorage = {snmp_mib_storage, {dets, AgentDbDir}}, init_size_check_ms(Config, [MibStorage]). init_size_check_msm(Config) when is_list(Config) -> @@ -695,22 +672,24 @@ init_size_check_ms(Config, Opts) when is_list(Config) -> ?SKIP({failed_starting_crypto, Reason}) end, create_tables(SaNode), - AgentDir = ?GCONF(agent_dir, Config), - MgrDir = ?GCONF(mgr_dir, Config), - Ip = ?GCONF(ip, Config), - ?line ok = - config([v3], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + AgentConfDir = ?GCONF(agent_conf_dir, Config), + MgrDir = ?GCONF(mgr_dir, Config), + Ip = ?GCONF(ip, Config), + ?line ok = config([v3], MgrDir, AgentConfDir, + tuple_to_list(Ip), tuple_to_list(Ip)), [{vsn, v3} | start_v3_agent(Config, Opts)]. init_varm_mib_storage_dets(Config) when is_list(Config) -> ?LOG("init_varm_mib_storage_dets -> entry", []), - ?line SaNode = ?GCONF(snmp_sa, Config), + ?line SaNode = ?GCONF(snmp_sa, Config), ?line create_tables(SaNode), - ?line AgentDir = ?GCONF(agent_dir, Config), - ?line MgrDir = ?GCONF(mgr_dir, Config), - ?line Ip = ?GCONF(ip, Config), - ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), - MibStorage = {snmp_mib_storage,{dets,AgentDir}}, + ?line AgentDbDir = ?GCONF(agent_db_dir, Config), + ?line AgentConfDir = ?GCONF(agent_conf_dir, Config), + ?line MgrDir = ?GCONF(mgr_dir, Config), + ?line Ip = ?GCONF(ip, Config), + ?line config([v1], MgrDir, AgentConfDir, + tuple_to_list(Ip), tuple_to_list(Ip)), + MibStorage = {snmp_mib_storage, {dets, AgentDbDir}}, MasterAgentVerbosity = {snmp_master_agent_verbosity, trace}, MibsVerbosity = {snmp_mibserver_verbosity, trace}, SymStoreVerbosity = {snmp_symbolic_store_verbosity, trace}, @@ -719,12 +698,13 @@ init_varm_mib_storage_dets(Config) when is_list(Config) -> init_varm_mib_storage_mnesia(Config) when is_list(Config) -> ?LOG("init_varm_mib_storage_mnesia -> entry", []), - ?line SaNode = ?GCONF(snmp_sa, Config), + ?line SaNode = ?GCONF(snmp_sa, Config), ?line create_tables(SaNode), - ?line AgentDir = ?GCONF(agent_dir, Config), - ?line MgrDir = ?GCONF(mgr_dir, Config), - ?line Ip = ?GCONF(ip, Config), - ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + ?line AgentConfDir = ?GCONF(agent_conf_dir, Config), + ?line MgrDir = ?GCONF(mgr_dir, Config), + ?line Ip = ?GCONF(ip, Config), + ?line config([v1], MgrDir, AgentConfDir, + tuple_to_list(Ip), tuple_to_list(Ip)), MibStorage = {snmp_mib_storage,{mnesia,[]}}, MasterAgentVerbosity = {snmp_master_agent_verbosity, trace}, MibsVerbosity = {snmp_mibserver_verbosity, trace}, @@ -1189,10 +1169,11 @@ v1_cases() -> init_v1(Config) when is_list(Config) -> ?line SaNode = ?config(snmp_sa, Config), ?line create_tables(SaNode), - ?line AgentDir = ?config(agent_dir, Config), + ?line AgentConfDir = ?config(agent_conf_dir, Config), ?line MgrDir = ?config(mgr_dir, Config), ?line Ip = ?config(ip, Config), - ?line config([v1], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + ?line config([v1], MgrDir, AgentConfDir, + tuple_to_list(Ip), tuple_to_list(Ip)), [{vsn, v1} | start_v1_agent(Config)]. finish_v1(Config) when is_list(Config) -> @@ -1232,10 +1213,11 @@ v2_cases() -> init_v2(Config) when is_list(Config) -> SaNode = ?config(snmp_sa, Config), create_tables(SaNode), - AgentDir = ?config(agent_dir, Config), + AgentConfDir = ?config(agent_conf_dir, Config), MgrDir = ?config(mgr_dir, Config), Ip = ?config(ip, Config), - config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + config([v2], MgrDir, AgentConfDir, + tuple_to_list(Ip), tuple_to_list(Ip)), [{vsn, v2} | start_v2_agent(Config)]. finish_v2(Config) when is_list(Config) -> @@ -1251,10 +1233,11 @@ v1_v2_cases() -> init_v1_v2(Config) when is_list(Config) -> SaNode = ?config(snmp_sa, Config), create_tables(SaNode), - AgentDir = ?config(agent_dir, Config), + AgentConfDir = ?config(agent_conf_dir, Config), MgrDir = ?config(mgr_dir, Config), Ip = ?config(ip, Config), - config([v1,v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + config([v1,v2], MgrDir, AgentConfDir, + tuple_to_list(Ip), tuple_to_list(Ip)), [{vsn, bilingual} | start_bilingual_agent(Config)]. finish_v1_v2(Config) when is_list(Config) -> @@ -1315,10 +1298,10 @@ init_v3(Config) when is_list(Config) -> end, SaNode = ?config(snmp_sa, Config), create_tables(SaNode), - AgentDir = ?config(agent_dir, Config), + AgentConfDir = ?config(agent_conf_dir, Config), MgrDir = ?config(mgr_dir, Config), Ip = ?config(ip, Config), - ?line ok = config([v3], MgrDir, AgentDir, + ?line ok = config([v3], MgrDir, AgentConfDir, tuple_to_list(Ip), tuple_to_list(Ip)), [{vsn, v3} | start_v3_agent(Config)]. @@ -1338,11 +1321,11 @@ mt_cases() -> init_mt(Config) when is_list(Config) -> SaNode = ?config(snmp_sa, Config), create_tables(SaNode), - AgentDir = ?config(agent_dir, Config), + AgentConfDir = ?config(agent_conf_dir, Config), MgrDir = ?config(mgr_dir, Config), Ip = ?config(ip, Config), - ?line ok = - config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + ?line ok = config([v2], MgrDir, AgentConfDir, + tuple_to_list(Ip), tuple_to_list(Ip)), [{vsn, v2} | start_multi_threaded_agent(Config)]. finish_mt(Config) when is_list(Config) -> @@ -1421,7 +1404,13 @@ simple(Config) when is_list(Config) -> ?P(simple), init_case(Config), - try_test(simple_standard_test). + try_test(simple_standard_test), + + p("Display log"), + display_log(Config), + + p("done"), + ok. simple_2(X) -> ?P(simple_2), simple(X). @@ -1601,7 +1590,7 @@ change_target_addr_config(Config) when is_list(Config) -> try_test(ma_trap1, [MA]), ?LOG("change_target_addr_config -> set silence verbosity for local_db",[]), - ?line snmpa:verbosity(local_db,silence), + ?line snmpa:verbosity(local_db, silence), %% Start new dummy listener ?LOG("change_target_addr_config -> start dummy manager",[]), @@ -1609,9 +1598,9 @@ change_target_addr_config(Config) when is_list(Config) -> %% Reconfigure ?LOG("change_target_addr_config -> reconfigure",[]), - AgentDir = ?config(agent_dir, Config), - ?line rewrite_target_addr_conf(AgentDir, NewPort), - ?line snmp_target_mib:reconfigure(AgentDir), + AgentConfDir = ?config(agent_conf_dir, Config), + ?line rewrite_target_addr_conf(AgentConfDir, NewPort), + ?line snmp_target_mib:reconfigure(AgentConfDir), %% Send the trap again ?LOG("change_target_addr_config -> send trap again",[]), @@ -1624,7 +1613,7 @@ change_target_addr_config(Config) when is_list(Config) -> ?line ok = dummy_manager_stop(Pid), ?LOG("change_target_addr_config -> reset target address config",[]), - ?line reset_target_addr_conf(AgentDir), + ?line reset_target_addr_conf(AgentConfDir), ?LOG("change_target_addr_config -> unload TestTrap",[]), ?line unload_master("TestTrap"). @@ -2067,7 +2056,7 @@ v3_inform(_X) -> {req, [], {conf, init_v3_inform, [v3_inform_i], finish_v3_inform}}. init_v2_inform(Config) when is_list(Config) -> - _Dir = ?config(agent_dir, Config), + _Dir = ?config(agent_conf_dir, Config), %% snmp_internal_mib:configure(Dir), Config. @@ -2075,7 +2064,7 @@ init_v3_inform(X) -> init_v2_inform(X). finish_v2_inform(Config) when is_list(Config) -> - _Dir = ?config(agent_dir, Config), + _Dir = ?config(agent_conf_dir, Config), %% snmp_internal_mib:configure(Dir), Config. @@ -2377,9 +2366,9 @@ v3_md5_auth(Config) when is_list(Config) -> ?P1("Testing MD5 authentication...takes a few seconds..."), - AgentDir = ?config(agent_dir, Config), - ?line rewrite_target_params_conf(AgentDir, "authMD5", authNoPriv), - ?line snmp_target_mib:reconfigure(AgentDir), + AgentConfDir = ?config(agent_conf_dir, Config), + ?line rewrite_target_params_conf(AgentConfDir, "authMD5", authNoPriv), + ?line snmp_target_mib:reconfigure(AgentConfDir), MA = whereis(snmp_master_agent), @@ -2388,14 +2377,14 @@ v3_md5_auth(Config) when is_list(Config) -> ?line load_master("TestTrapv2"), try_test(v3_sync, [[{v2_proc, []}, - {ma_v2_trap1, [MA]}, - {v3_inform_sync, [MA]}]], - [{sec_level, authNoPriv}, {user, "authMD5"}]), + {ma_v2_trap1, [MA]}, + {v3_inform_sync, [MA]}]], + [{sec_level, authNoPriv}, {user, "authMD5"}]), ?line unload_master("TestTrapv2"), ?line unload_master("TestTrap"), ?line unload_master("Test2"), - ?line reset_target_params_conf(AgentDir). + ?line reset_target_params_conf(AgentConfDir). v3_sha_auth(suite) -> []; v3_sha_auth(Config) when is_list(Config) -> @@ -2404,9 +2393,9 @@ v3_sha_auth(Config) when is_list(Config) -> ?P1("Testing SHA authentication...takes a few seconds..."), - AgentDir = ?config(agent_dir, Config), - ?line rewrite_target_params_conf(AgentDir, "authSHA", authNoPriv), - ?line snmp_target_mib:reconfigure(AgentDir), + AgentConfDir = ?config(agent_conf_dir, Config), + ?line rewrite_target_params_conf(AgentConfDir, "authSHA", authNoPriv), + ?line snmp_target_mib:reconfigure(AgentConfDir), MA = whereis(snmp_master_agent), @@ -2415,14 +2404,14 @@ v3_sha_auth(Config) when is_list(Config) -> ?line load_master("TestTrapv2"), try_test(v3_sync, [[{v2_proc, []}, - {ma_v2_trap1, [MA]}, - {v3_inform_sync, [MA]}]], - [{sec_level, authNoPriv}, {user, "authSHA"}]), + {ma_v2_trap1, [MA]}, + {v3_inform_sync, [MA]}]], + [{sec_level, authNoPriv}, {user, "authSHA"}]), ?line unload_master("TestTrapv2"), ?line unload_master("TestTrap"), ?line unload_master("Test2"), - ?line reset_target_params_conf(AgentDir). + ?line reset_target_params_conf(AgentConfDir). v3_des_priv(suite) -> []; v3_des_priv(Config) when is_list(Config) -> @@ -2431,9 +2420,9 @@ v3_des_priv(Config) when is_list(Config) -> ?P1("Testing DES encryption...takes a few seconds..."), - AgentDir = ?config(agent_dir, Config), - ?line rewrite_target_params_conf(AgentDir, "privDES", authPriv), - ?line snmp_target_mib:reconfigure(AgentDir), + AgentConfDir = ?config(agent_conf_dir, Config), + ?line rewrite_target_params_conf(AgentConfDir, "privDES", authPriv), + ?line snmp_target_mib:reconfigure(AgentConfDir), MA = whereis(snmp_master_agent), @@ -2444,14 +2433,14 @@ v3_des_priv(Config) when is_list(Config) -> ?line load_master("TestTrapv2"), try_test(v3_sync, [[{v2_proc, []}, - {ma_v2_trap1, [MA]}, - {v3_inform_sync, [MA]}]], - [{sec_level, authPriv}, {user, "privDES"}]), + {ma_v2_trap1, [MA]}, + {v3_inform_sync, [MA]}]], + [{sec_level, authPriv}, {user, "privDES"}]), ?line unload_master("TestTrapv2"), ?line unload_master("TestTrap"), ?line unload_master("Test2"), - ?line reset_target_params_conf(AgentDir). + ?line reset_target_params_conf(AgentConfDir). %% -define(usmStatsNotInTimeWindows_instance, [1,3,6,1,6,3,15,1,1,2,0]). @@ -4795,7 +4784,7 @@ snmp_user_based_sm_mib_3(Config) when is_list(Config) -> ?P(snmp_user_based_sm_mib_3), init_case(Config), - _AgentDir = ?config(agent_dir, Config), + _AgentDir = ?config(agent_conf_dir, Config), ?line load_master_std("SNMP-USER-BASED-SM-MIB"), %% The newUser used here already has VACM access. @@ -5727,28 +5716,28 @@ otp_3725_test(MaNode) -> init_otp_4394(Config) when is_list(Config) -> ?DBG("init_otp_4394 -> entry with" "~n Config: ~p", [Config]), - ?line AgentDir = ?config(agent_dir, Config), - ?line MgrDir = ?config(mgr_dir, Config), - ?line Ip = ?config(ip, Config), - ?line otp_4394_config(AgentDir, MgrDir, Ip), + ?line AgentConfDir = ?config(agent_conf_dir, Config), + ?line MgrDir = ?config(mgr_dir, Config), + ?line Ip = ?config(ip, Config), + ?line otp_4394_config(AgentConfDir, MgrDir, Ip), MasterAgentVerbosity = {master_agent_verbosity, trace}, NetIfVerbosity = {net_if_verbosity, trace}, - Opts = [MasterAgentVerbosity,NetIfVerbosity], - [{vsn, v1} | start_v1_agent(Config,Opts)]. + Opts = [MasterAgentVerbosity, NetIfVerbosity], + [{vsn, v1} | start_v1_agent(Config, Opts)]. -otp_4394_config(AgentDir, MgrDir, Ip0) -> +otp_4394_config(AgentConfDir, MgrDir, Ip0) -> ?DBG("otp_4394_config -> entry with" - "~n AgentDir: ~p" - "~n MgrDir: ~p" - "~n Ip0: ~p", [AgentDir, MgrDir, Ip0]), + "~n AgentConfDir: ~p" + "~n MgrDir: ~p" + "~n Ip0: ~p", [AgentConfDir, MgrDir, Ip0]), Vsn = [v1], Ip = tuple_to_list(Ip0), - ?line snmp_config:write_agent_snmp_files(AgentDir, Vsn, Ip, + ?line snmp_config:write_agent_snmp_files(AgentConfDir, Vsn, Ip, ?TRAP_UDP, Ip, 4000, "OTP-4394 test"), - ?line case update_usm(Vsn, AgentDir) of + ?line case update_usm(Vsn, AgentConfDir) of true -> - ?line copy_file(filename:join(AgentDir, "usm.conf"), + ?line copy_file(filename:join(AgentConfDir, "usm.conf"), filename:join(MgrDir, "usm.conf")), ?line update_usm_mgr(Vsn, MgrDir); false -> @@ -5756,8 +5745,8 @@ otp_4394_config(AgentDir, MgrDir, Ip0) -> end, C1 = {"a", "all-rights", "initial", "", "pc"}, C2 = {"c", "secret", "secret_name", "", "secret_tag"}, - ?line write_community_conf(AgentDir, [C1, C2]), - ?line update_vacm(Vsn, AgentDir), + ?line write_community_conf(AgentConfDir, [C1, C2]), + ?line update_vacm(Vsn, AgentConfDir), Ta1 = {"shelob v1", [134,138,177,177], 5000, 1500, 3, %% Anv�nd Ip och modda "pc1", @@ -5771,9 +5760,9 @@ otp_4394_config(AgentDir, MgrDir, Ip0) -> "target_v1", "", %% [255,255,255,255,0,0], [], 2048}, - ?line write_target_addr_conf(AgentDir, [Ta1, Ta2]), - ?line write_target_params_conf(AgentDir, Vsn), - ?line write_notify_conf(AgentDir), + ?line write_target_addr_conf(AgentConfDir, [Ta1, Ta2]), + ?line write_target_params_conf(AgentConfDir, Vsn), + ?line write_notify_conf(AgentConfDir), ok. @@ -5826,10 +5815,11 @@ init_otp_7157(Config) when is_list(Config) -> ?DBG("init_otp_7157 -> entry with" "~n Config: ~p", [Config]), - ?line AgentDir = ?config(agent_dir, Config), + ?line AgentConfDir = ?config(agent_conf_dir, Config), ?line MgrDir = ?config(mgr_dir, Config), ?line Ip = ?config(ip, Config), - ?line config([v2], MgrDir, AgentDir, tuple_to_list(Ip), tuple_to_list(Ip)), + ?line config([v2], MgrDir, AgentConfDir, + tuple_to_list(Ip), tuple_to_list(Ip)), MasterAgentVerbosity = {master_agent_verbosity, trace}, NetIfVerbosity = {net_if_verbosity, trace}, Opts = [MasterAgentVerbosity, NetIfVerbosity], @@ -6562,8 +6552,8 @@ write_community_conf(Dir, Conf) -> write_target_addr_conf(Dir, Conf) -> snmp_agent_test_lib:write_target_addr_conf(Dir, Conf). -write_target_addr_conf(Dir, ManagerIp, UDP, Vsns) -> - snmp_agent_test_lib:write_target_addr_conf(Dir, ManagerIp, UDP, Vsns). +%% write_target_addr_conf(Dir, ManagerIp, UDP, Vsns) -> +%% snmp_agent_test_lib:write_target_addr_conf(Dir, ManagerIp, UDP, Vsns). rewrite_target_addr_conf(Dir, NewPort) -> snmp_agent_test_lib:rewrite_target_addr_conf(Dir, NewPort). @@ -6596,9 +6586,42 @@ copy_file(From, To) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +display_log(Config) -> + case lists:keysearch(agent_log_dir, 1, Config) of + {value, {_, Dir}} -> + case lists:keysearch(snmp_master, 1, Config) of + {value, {_, Node}} -> + LogDir = Dir, + Mibs = [], + OutFile = filename:join(LogDir, "snmpa_log.txt"), + p("~n" + "=========================" + " < Audit Trail Log > " + "=========================" + "~n"), + rcall(Node, snmpa, log_to_txt, [LogDir, Mibs, OutFile]), + rcall(Node, snmpa, log_to_io, [LogDir, Mibs]), + p("~n" + "=========================" + " < / Audit Trail Log > " + "=========================" + "~n", []); + false -> + p("display_log -> no agent node found"), + ok + end; + false -> + p("display_log -> no agent log dir found: " + "~n ~p", [Config]), + ok + end. + + +%% ------ + display_memory_usage() -> Info = snmpa:info(snmp_master_agent), - AMU = display_agent_memory_uasge(Info), + AMU = display_agent_memory_usage(Info), NIMU = display_net_if_memory_usage(Info), NSMU = display_note_store_memory_usage(Info), SSMU = display_symbolic_store_memory_usage(Info), @@ -6608,7 +6631,7 @@ display_memory_usage() -> AMU ++ NIMU ++ NSMU ++ SSMU ++ LDBMU ++ MSMU, []), ok. -display_agent_memory_uasge(Info) -> +display_agent_memory_usage(Info) -> AgentInfo = lists_key1search(agent, Info), ProcMem = lists_key1search([process_memory,master_agent], AgentInfo), @@ -6717,3 +6740,27 @@ lists_key1search(Key, List) when is_atom(Key) -> regs() -> lists:sort(registered()). + +%% ------ + +rcall(Node, Mod, Func, Args) -> + case rpc:call(Node, Mod, Func, Args) of + {badrpc, nodedown} -> + ?FAIL({rpc_failure, Node}); + Else -> + Else + end. + + +%% ------ + +p(F) -> + p(F, []). + +p(F, A) -> + io:format("*** [~s] ***" + "~n" ++ F ++ "~n", [formated_timestamp()|A]). + +formated_timestamp() -> + snmp_test_lib:formated_timestamp(). + diff --git a/lib/snmp/test/snmp_agent_test_lib.erl b/lib/snmp/test/snmp_agent_test_lib.erl index 084b3ee8da..cd9a87eab8 100644 --- a/lib/snmp/test/snmp_agent_test_lib.erl +++ b/lib/snmp/test/snmp_agent_test_lib.erl @@ -119,20 +119,10 @@ %%% didn't undo (since it failed). %%%----------------------------------------------------------------- -init_all(Config0) when is_list(Config0) -> - ?LOG("init_all -> entry with" - "~n Config0: ~p",[Config0]), - - %% -- - %% Fix config: - %% +init_all(Config) when is_list(Config) -> - DataDir0 = ?config(data_dir, Config0), - DataDir1 = filename:split(filename:absname(DataDir0)), - [_|DataDir2] = lists:reverse(DataDir1), - DataDir3 = filename:join(lists:reverse(DataDir2) ++ [?snmp_test_data]), - Config1 = lists:keydelete(data_dir, 1, Config0), - Config = [{data_dir, DataDir3 ++ "/"}|Config1], + ?LOG("init_all -> entry with" + "~n Config: ~p",[Config]), %% -- %% Start nodes @@ -143,34 +133,43 @@ init_all(Config0) when is_list(Config0) -> %% -- - %% Create necessary files + %% Create necessary files ( and dirs ) %% - PrivDir = ?config(priv_dir, Config), - ?DBG("init_all -> PrivDir ~p", [PrivDir]), + SuiteTopDir = ?config(snmp_suite_top_dir, Config), + ?DBG("init_all -> SuiteTopDir ~p", [SuiteTopDir]), - TopDir = filename:join(PrivDir, snmp_agent_test), - case file:make_dir(TopDir) of - ok -> - ok; - {error, eexist} -> - ok; - Error -> - ?FAIL({failed_creating_subsuite_top_dir, Error}) - end, + AgentDir = filename:join(SuiteTopDir, "agent/"), + ?line ok = file:make_dir(AgentDir), + ?DBG("init_all -> AgentDir ~p", [AgentDir]), - DataDir = ?config(data_dir, Config), - ?DBG("init_all -> DataDir ~p", [DataDir]), + AgentDbDir = filename:join(AgentDir, "db/"), + ?line ok = file:make_dir(AgentDbDir), + ?DBG("init_all -> AgentDbDir ~p", [AgentDbDir]), - ?line ok = file:make_dir(MgrDir = filename:join(TopDir, "mgr_dir/")), - ?DBG("init_all -> MgrDir ~p", [MgrDir]), + AgentLogDir = filename:join(AgentDir, "log/"), + ?line ok = file:make_dir(AgentLogDir), + ?DBG("init_all -> AgentLogDir ~p", [AgentLogDir]), - ?line ok = file:make_dir(AgentDir = filename:join(TopDir, "agent_dir/")), - ?DBG("init_all -> AgentDir ~p", [AgentDir]), + AgentConfDir = filename:join(AgentDir, "conf/"), + ?line ok = file:make_dir(AgentConfDir), + ?DBG("init_all -> AgentConfDir ~p", [AgentConfDir]), - ?line ok = file:make_dir(SaDir = filename:join(TopDir, "sa_dir/")), + MgrDir = filename:join(SuiteTopDir, "mgr/"), + ?line ok = file:make_dir(MgrDir), + ?DBG("init_all -> MgrDir ~p", [MgrDir]), + + SaDir = filename:join(SuiteTopDir, "sa/"), + ?line ok = file:make_dir(SaDir), ?DBG("init_all -> SaDir ~p", [SaDir]), + SaDbDir = filename:join(SaDir, "db/"), + ?line ok = file:make_dir(SaDbDir), + ?DBG("init_all -> SaDbDir ~p", [SaDbDir]), + + %% MibDir = ?config(mib_dir, Config), + %% ?DBG("init_all -> MibDir ~p", [DataDir]), + %% -- %% Start and initiate mnesia @@ -184,11 +183,11 @@ init_all(Config0) when is_list(Config0) -> ?DBG("init_all -> application mnesia: set_env dir",[]), ?line application_controller:set_env(mnesia, dir, - filename:join(TopDir, "Mnesia1")), + filename:join(AgentDbDir, "Mnesia1")), ?DBG("init_all -> application mnesia: set_env dir on node ~p",[SaNode]), - ?line rpc:call(SaNode, application_controller, set_env, - [mnesia, dir, filename:join(TopDir, "Mnesia2")]), + ?line rpc:call(SaNode, application_controller, set_env, + [mnesia, dir, filename:join(SaDir, "Mnesia2")]), ?DBG("init_all -> create mnesia schema",[]), ?line ok = mnesia:create_schema([SaNode, node()]), @@ -199,13 +198,18 @@ init_all(Config0) when is_list(Config0) -> ?DBG("init_all -> start application mnesia on ~p",[SaNode]), ?line ok = rpc:call(SaNode, application, start, [mnesia]), Ip = ?LOCALHOST(), - [{snmp_sa, SaNode}, - {snmp_mgr, MgrNode}, - {agent_dir, AgentDir ++ "/"}, - {mgr_dir, MgrDir ++ "/"}, - {sa_dir, SaDir ++ "/"}, - {mib_dir, DataDir}, - {ip, Ip} | + [{snmp_sa, SaNode}, + {snmp_mgr, MgrNode}, + {snmp_master, node()}, + {agent_dir, AgentDir ++ "/"}, + {agent_db_dir, AgentDbDir ++ "/"}, + {agent_log_dir, AgentLogDir ++ "/"}, + {agent_conf_dir, AgentConfDir ++ "/"}, + {sa_dir, SaDir ++ "/"}, + {sa_db_dir, SaDbDir ++ "/"}, + {mgr_dir, MgrDir ++ "/"}, + %% {mib_dir, DataDir}, + {ip, Ip} | Config]. @@ -220,11 +224,14 @@ finish_all(Config) when is_list(Config) -> %% --- This one *must* be run first in each case --- init_case(Config) when is_list(Config) -> + ?DBG("init_case -> entry with" - "~n Config: ~p", [Config]), - SaNode = ?config(snmp_sa, Config), - MgrNode = ?config(snmp_mgr, Config), - MasterNode = node(), + "~n Config: ~p", [Config]), + + SaNode = ?config(snmp_sa, Config), + MgrNode = ?config(snmp_mgr, Config), + MasterNode = ?config(snmp_master, Config), + %% MasterNode = node(), SaHost = ?HOSTNAME(SaNode), MgrHost = ?HOSTNAME(MgrNode), @@ -411,7 +418,8 @@ start_v3_agent(Config, Opts) when is_list(Config) andalso is_list(Opts) -> start_bilingual_agent(Config) when is_list(Config) -> start_agent(Config, [v1,v2]). -start_bilingual_agent(Config, Opts) when is_list(Config) andalso is_list(Opts) -> +start_bilingual_agent(Config, Opts) + when is_list(Config) andalso is_list(Opts) -> start_agent(Config, [v1,v2], Opts). start_mt_agent(Config) when is_list(Config) -> @@ -423,57 +431,33 @@ start_mt_agent(Config, Opts) when is_list(Config) andalso is_list(Opts) -> start_agent(Config, Vsns) -> start_agent(Config, Vsns, []). start_agent(Config, Vsns, Opts) -> + ?LOG("start_agent -> entry (~p) with" "~n Config: ~p" "~n Vsns: ~p" "~n Opts: ~p", [node(), Config, Vsns, Opts]), - ?line AgentDir = ?config(agent_dir, Config), - ?line SaNode = ?config(snmp_sa, Config), - -%% AgentConfig = -%% [{agent_type, master}, -%% %% {multi_threaded, MultiT}, -%% %% {priority, Prio}, -%% %% {error_report_mod, ErrorReportMod}, -%% {versions, Vsns}, -%% {db_dir, AgentDir}, -%% %% {db_init_error, DbInitError}, -%% %% {set_mechanism, SetModule}, -%% %% {authentication_service, AuthModule}, -%% {audit_trail_log, [{type, read_write}, -%% {dir, AgentDir}, -%% {size, {10240, 10}}, -%% {repair, true}]}, -%% {config, [{verbosity, info}, -%% {dir, AgentDir}, -%% {force_load, false}]}, -%% {mibs, Mibs}, -%% %% {mib_storage, MibStorage}, -%% {local_db, []}, -%% {mib_server, []}, -%% {symbolic_store, []}, -%% {note_store, []}, -%% {net_if, []}, -%% %% {supervisor, SupOpts} -%% ], - + ?line AgentLogDir = ?config(agent_log_dir, Config), + ?line AgentConfDir = ?config(agent_conf_dir, Config), + ?line AgentDbDir = ?config(agent_db_dir, Config), + ?line SaNode = ?config(snmp_sa, Config), + app_env_init(vsn_init(Vsns) ++ - [{audit_trail_log, read_write_log}, - {audit_trail_log_dir, AgentDir}, - {audit_trail_log_size, {10240, 10}}, - {force_config_reload, false}, - {snmp_agent_type, master}, - {snmp_config_dir, AgentDir}, - {snmp_db_dir, AgentDir}, - {snmp_local_db_auto_repair, true}, - {snmp_local_db_verbosity, log}, - {snmp_master_agent_verbosity, trace}, - {snmp_supervisor_verbosity, trace}, - {snmp_mibserver_verbosity, log}, + [{audit_trail_log, read_write_log}, + {audit_trail_log_dir, AgentLogDir}, + {audit_trail_log_size, {10240, 10}}, + {force_config_reload, false}, + {snmp_agent_type, master}, + {snmp_config_dir, AgentConfDir}, + {snmp_db_dir, AgentDbDir}, + {snmp_local_db_auto_repair, true}, + {snmp_local_db_verbosity, log}, + {snmp_master_agent_verbosity, trace}, + {snmp_supervisor_verbosity, trace}, + {snmp_mibserver_verbosity, log}, {snmp_symbolic_store_verbosity, log}, - {snmp_note_store_verbosity, log}, - {snmp_net_if_verbosity, trace}], + {snmp_note_store_verbosity, log}, + {snmp_net_if_verbosity, trace}], Opts), @@ -1237,30 +1221,44 @@ stop_node(Node) -> %%% Configuration %%%----------------------------------------------------------------- -config(Vsns, MgrDir, AgentDir, MIp, AIp) -> - ?line snmp_config:write_agent_snmp_files(AgentDir, Vsns, MIp, - ?TRAP_UDP, AIp, 4000, +config(Vsns, MgrDir, AgentConfDir, MIp, AIp) -> + ?LOG("config -> entry with" + "~n Vsns: ~p" + "~n MgrDir: ~p" + "~n AgentConfDir: ~p" + "~n MIp: ~p" + "~n AIp: ~p", + [Vsns, MgrDir, AgentConfDir, MIp, AIp]), + ?line snmp_config:write_agent_snmp_files(AgentConfDir, Vsns, + MIp, ?TRAP_UDP, AIp, 4000, "test"), - ?line case update_usm(Vsns, AgentDir) of + ?line case update_usm(Vsns, AgentConfDir) of true -> - ?line copy_file(filename:join(AgentDir, "usm.conf"), + ?line copy_file(filename:join(AgentConfDir, "usm.conf"), filename:join(MgrDir, "usm.conf")), ?line update_usm_mgr(Vsns, MgrDir); false -> ?line ok end, - ?line update_community(Vsns, AgentDir), - ?line update_vacm(Vsns, AgentDir), - ?line write_target_addr_conf(AgentDir, MIp, ?TRAP_UDP, Vsns), - ?line write_target_params_conf(AgentDir, Vsns), - ?line write_notify_conf(AgentDir), + ?line update_community(Vsns, AgentConfDir), + ?line update_vacm(Vsns, AgentConfDir), + ?line write_target_addr_conf(AgentConfDir, MIp, ?TRAP_UDP, Vsns), + ?line write_target_params_conf(AgentConfDir, Vsns), + ?line write_notify_conf(AgentConfDir), ok. delete_files(Config) -> - Dir = ?config(agent_dir, Config), - {ok, List} = file:list_dir(Dir), + AgentDir = ?config(agent_dir, Config), + delete_files(AgentDir, [db, conf]). + +delete_files(_AgentFiles, []) -> + ok; +delete_files(AgentDir, [DirName|DirNames]) -> + Dir = filename:join(AgentDir, DirName), + {ok, Files} = file:list_dir(Dir), lists:foreach(fun(FName) -> file:delete(filename:join(Dir, FName)) end, - List). + Files), + delete_files(AgentDir, DirNames). update_usm(Vsns, Dir) -> case lists:member(v3, Vsns) of @@ -1418,8 +1416,8 @@ rewrite_target_addr_conf2(_NewPort,O) -> O. reset_target_addr_conf(Dir) -> - ?line ok = file:rename(filename:join(Dir,"target_addr.old"), - filename:join(Dir,"target_addr.conf")). + ?line ok = file:rename(filename:join(Dir, "target_addr.old"), + filename:join(Dir, "target_addr.conf")). write_target_params_conf(Dir, Vsns) -> F = fun(v1) -> {"target_v1", v1, v1, "all-rights", noAuthNoPriv}; @@ -1458,7 +1456,6 @@ copy_file(From, To) -> ok = file:write_file(To, Bin). - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% display_memory_usage() -> diff --git a/lib/snmp/test/snmp_app_test.erl b/lib/snmp/test/snmp_app_test.erl index bc62c8d530..0a320dbbce 100644 --- a/lib/snmp/test/snmp_app_test.erl +++ b/lib/snmp/test/snmp_app_test.erl @@ -23,8 +23,9 @@ -module(snmp_app_test). -export([ - all/0,groups/0,init_per_group/2,end_per_group/2, init_per_suite/1, - end_per_suite/1, + all/0, groups/0, + init_per_group/2, end_per_group/2, + init_per_suite/1, end_per_suite/1, init_per_testcase/2, end_per_testcase/2, fields/1, @@ -52,33 +53,47 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% all() -> -Cases = [fields, modules, exportall, app_depend, - undef_funcs, {group, start_and_stop}], - Cases. + Cases = + [ + fields, + modules, + exportall, + app_depend, + undef_funcs, + {group, start_and_stop} + ], + Cases. groups() -> [{start_and_stop, [], - [start_and_stop_empty, start_and_stop_with_agent, - start_and_stop_with_manager, - start_and_stop_with_agent_and_manager, - start_epmty_and_then_agent_and_manager_and_stop, - start_with_agent_and_then_manager_and_stop, - start_with_manager_and_then_agent_and_stop]}]. + [start_and_stop_empty, + start_and_stop_with_agent, + start_and_stop_with_manager, + start_and_stop_with_agent_and_manager, + start_epmty_and_then_agent_and_manager_and_stop, + start_with_agent_and_then_manager_and_stop, + start_with_manager_and_then_agent_and_stop]}]. init_per_group(_GroupName, Config) -> - Config. + Config. end_per_group(_GroupName, Config) -> - Config. + Config. init_per_suite(Config) when is_list(Config) -> ?DISPLAY_SUITE_INFO(), + + %% Note that part of this stuff (the suite top dir creation) + %% may already be done (if we run the entire snmp suite). + PrivDir = ?config(priv_dir, Config), TopDir = filename:join(PrivDir, app), case file:make_dir(TopDir) of ok -> ok; + {error, eexist} -> + ok; Error -> fail({failed_creating_subsuite_top_dir, Error}) end, diff --git a/lib/snmp/test/snmp_compiler_test.erl b/lib/snmp/test/snmp_compiler_test.erl index 0a147130b0..257fc47952 100644 --- a/lib/snmp/test/snmp_compiler_test.erl +++ b/lib/snmp/test/snmp_compiler_test.erl @@ -40,6 +40,7 @@ all/0, groups/0, init_per_group/2, end_per_group/2, init_per_testcase/2, end_per_testcase/2, + init_per_suite/1, end_per_suite/1, description/1, oid_conflicts/1, @@ -48,6 +49,7 @@ agent_capabilities/1, module_compliance/1, warnings_as_errors/1, + augments_extra_info/1, otp_6150/1, otp_8574/1, @@ -58,6 +60,7 @@ %%---------------------------------------------------------------------- %% Internal exports %%---------------------------------------------------------------------- + -export([ ]). @@ -74,19 +77,41 @@ %% External functions %%====================================================================== -init_per_testcase(_Case, Config) when is_list(Config) -> - Dir = ?config(priv_dir, Config), - DataDir = ?config(data_dir, Config), - [_|RL] = lists:reverse(filename:split(DataDir)), - MibDir = join(lists:reverse(["snmp_test_data"|RL])), - CompDir = join(Dir, "comp_dir/"), - ?line ok = file:make_dir(CompDir), - [{comp_dir, CompDir}, {mib_dir, MibDir} | Config]. +init_per_suite(Config0) when is_list(Config0) -> + + ?DBG("init_per_suite -> entry with" + "~n Config0: ~p", [Config0]), + + Config1 = snmp_test_lib:init_suite_top_dir(?MODULE, Config0), + Config2 = snmp_test_lib:fix_data_dir(Config1), + + %% Mib-dirs + %% data_dir is trashed by the test-server / common-test + %% so there is no point in fixing it... + MibDir = snmp_test_lib:lookup(data_dir, Config2), + StdMibDir = filename:join([code:priv_dir(snmp), "mibs"]), + + [{mib_dir, MibDir}, {std_mib_dir, StdMibDir} | Config2]. + +end_per_suite(Config) when is_list(Config) -> + + ?DBG("end_per_suite -> entry with" + "~n Config: ~p", [Config]), + + Config. + + +init_per_testcase(Case, Config) when is_list(Config) -> + + ?DBG("init_per_testcase -> entry with" + "~n Config: ~p", [Config]), + + CaseTopDir = snmp_test_lib:init_testcase_top_dir(Case, Config), + + [{case_top_dir, CaseTopDir} | Config]. end_per_testcase(_Case, Config) when is_list(Config) -> - CompDir = ?config(comp_dir, Config), - ?line ok = ?DEL_DIR(CompDir), - lists:keydelete(comp_dir, 1, Config). + Config. %%====================================================================== @@ -102,6 +127,7 @@ all() -> agent_capabilities, module_compliance, warnings_as_errors, + augments_extra_info, {group, tickets} ]. @@ -126,7 +152,7 @@ description(Config) when is_list(Config) -> put(tname,desc), p("starting with Config: ~p~n", [Config]), - Dir = ?config(comp_dir, Config), + Dir = ?config(case_top_dir, Config), Filename = join(Dir,"test"), MibSrcName = Filename ++ ".mib", MibBinName = Filename ++ ".bin", @@ -161,7 +187,7 @@ oid_conflicts(Config) when is_list(Config) -> put(tname,oid_conflicts), p("starting with Config: ~p~n", [Config]), - Dir = ?config(comp_dir, Config), + Dir = ?config(case_top_dir, Config), Mib = join(Dir,"TESTv2.mib"), ?line ok = write_oid_conflict_mib(Mib), ?line {error,compilation_failed} = @@ -278,7 +304,7 @@ warnings_as_errors(suite) -> warnings_as_errors(Config) when is_list(Config) -> put(tname,warnings_as_errors), p("starting with Config: ~p~n", [Config]), - Dir = ?config(comp_dir, Config), + Dir = ?config(case_top_dir, Config), MibDir = ?config(mib_dir, Config), MibFile = join(MibDir, "OTP8574-MIB.mib"), OutFile = join(Dir, "OTP8574-MIB.bin"), @@ -303,7 +329,7 @@ otp_6150(Config) when is_list(Config) -> put(tname,otp_6150), p("starting with Config: ~p~n", [Config]), - Dir = ?config(comp_dir, Config), + Dir = ?config(case_top_dir, Config), MibDir = ?config(mib_dir, Config), MibFile = join(MibDir, "ERICSSON-TOP-MIB.mib"), ?line {ok, Mib} = snmpc:compile(MibFile, [{outdir, Dir}, {verbosity, trace}]), @@ -319,7 +345,7 @@ otp_8574(Config) when is_list(Config) -> put(tname,otp_8574), p("starting with Config: ~p~n", [Config]), - Dir = ?config(comp_dir, Config), + Dir = ?config(case_top_dir, Config), MibDir = ?config(mib_dir, Config), MibFile = join(MibDir, "OTP8574-MIB.mib"), @@ -352,7 +378,7 @@ otp_8595(Config) when is_list(Config) -> put(tname,otp_8595), p("starting with Config: ~p~n", [Config]), - Dir = ?config(comp_dir, Config), + Dir = ?config(case_top_dir, Config), MibDir = ?config(mib_dir, Config), MibFile = join(MibDir, "OTP8595-MIB.mib"), ?line {ok, Mib} = @@ -364,6 +390,47 @@ otp_8595(Config) when is_list(Config) -> %%====================================================================== + +augments_extra_info(suite) -> + []; +augments_extra_info(Config) when is_list(Config) -> + put(tname, augments_extra_info), + p("starting with Config: ~p~n", [Config]), + + Dir = ?config(case_top_dir, Config), + MibDir = ?config(mib_dir, Config), + Test2File = join(MibDir, "Test2.mib"), + Test3File = join(MibDir, "Test3.mib"), + ?line {ok, Test2BinFile} = + snmpc:compile(Test2File, [{outdir, Dir}, + {verbosity, silence}, + {group_check, false}]), + io:format("Test2BinFile: ~n~p~n", [Test2BinFile]), + ?line {ok, Test3BinFile} = + snmpc:compile(Test3File, [{i, [MibDir]}, + {outdir, Dir}, + {verbosity, silence}, + {group_check, true}]), + io:format("Test3BinFile: ~n~p~n", [Test3BinFile]), + {ok, Test3Mib} = snmp_misc:read_mib(Test3BinFile), + io:format("Test3Mib: ~n~p~n", [Test3Mib]), + %% There is only one table in this mib + #mib{table_infos = [{TableName, TI}]} = Test3Mib, + io:format("TableName: ~p" + "~n Table Info: ~p" + "~n", [TableName, TI]), + #table_info{nbr_of_cols = 4, + defvals = DefVals, + not_accessible = [2,4], + index_types = {augments, {tEntry, undefined}}, + first_accessible = 1} = TI, + io:format("Table info: ~p" + "~n DefVals: ~p" + "~n", [TableName, DefVals]), + ok. + + +%%====================================================================== %% Internal functions %%====================================================================== @@ -517,11 +584,11 @@ DESCRIPTION \"" ++ Desc ++ "\" ::= { test 1 } END", - Message = file:write_file(Filename ,Binary), + Message = file:write_file(Filename, Binary), case Message of ok -> ok; {error, Reason} -> - exit({failed_writing_mib,Reason}) + exit({failed_writing_mib, Reason}) end. @@ -546,8 +613,8 @@ check_desc(Desc1, Desc2) -> exit({'description not equal', Desc1, Desc2}). -join(Comp) -> - filename:join(Comp). +%% join(Comp) -> +%% filename:join(Comp). join(A,B) -> filename:join(A,B). diff --git a/lib/snmp/test/snmp_log_test.erl b/lib/snmp/test/snmp_log_test.erl index b692017407..8478825f59 100644 --- a/lib/snmp/test/snmp_log_test.erl +++ b/lib/snmp/test/snmp_log_test.erl @@ -42,7 +42,11 @@ -export([ init_per_testcase/2, end_per_testcase/2, - all/0,groups/0,init_per_group/2,end_per_group/2, + all/0, + groups/0, + init_per_group/2, + end_per_group/2, + open_and_close/1, open_write_and_close1/1, @@ -109,16 +113,21 @@ end_per_testcase(_Case, Config) when is_list(Config) -> %%====================================================================== %% ?SKIP(not_yet_implemented). all() -> -[open_and_close, {group, open_write_and_close}, - {group, log_to_io}, {group, log_to_txt}]. + [ + open_and_close, + {group, open_write_and_close}, + {group, log_to_io}, + {group, log_to_txt}]. groups() -> - [{open_write_and_close, [], - [open_write_and_close1, open_write_and_close2, - open_write_and_close3, open_write_and_close4]}, - {log_to_io, [], [log_to_io1, log_to_io2]}, - {log_to_txt, [], - [log_to_txt1, log_to_txt2, log_to_txt3]}]. + [ + {open_write_and_close, [], + [open_write_and_close1, open_write_and_close2, + open_write_and_close3, open_write_and_close4]}, + {log_to_io, [], [log_to_io1, log_to_io2]}, + {log_to_txt, [], + [log_to_txt1, log_to_txt2, log_to_txt3]} + ]. init_per_group(_GroupName, Config) -> Config. diff --git a/lib/snmp/test/snmp_manager_test.erl b/lib/snmp/test/snmp_manager_test.erl index 75c9f7b277..c374a2f0a6 100644 --- a/lib/snmp/test/snmp_manager_test.erl +++ b/lib/snmp/test/snmp_manager_test.erl @@ -49,6 +49,8 @@ init_per_group/2, end_per_group/2, init_per_testcase/2, end_per_testcase/2, + init_per_suite/1, end_per_suite/1, + simple_start_and_stop1/1, simple_start_and_stop2/1, @@ -146,36 +148,43 @@ %% External functions %%====================================================================== +init_per_suite(Config0) when is_list(Config0) -> + + ?DBG("init_per_suite -> entry with" + "~n Config0: ~p", [Config0]), + + Config1 = snmp_test_lib:init_suite_top_dir(?MODULE, Config0), + Config2 = snmp_test_lib:fix_data_dir(Config1), + + %% Mib-dirs + %% data_dir is trashed by the test-server / common-test + %% so there is no point in fixing it... + MibDir = snmp_test_lib:lookup(data_dir, Config2), + StdMibDir = filename:join([code:priv_dir(snmp), "mibs"]), + + [{mib_dir, MibDir}, {std_mib_dir, StdMibDir} | Config2]. + +end_per_suite(Config) when is_list(Config) -> + + ?DBG("end_per_suite -> entry with" + "~n Config: ~p", [Config]), + + Config. + + init_per_testcase(Case, Config) when is_list(Config) -> io:format(user, "~n~n*** INIT ~w:~w ***~n~n", [?MODULE,Case]), init_per_testcase2(Case, Config). init_per_testcase2(Case, Config) -> - ?DBG("init [~w] Nodes [1]: ~p", [Case, erlang:nodes()]), - - %% Fix a correct data dir (points to the wrong location): - DataDir0 = ?config(data_dir, Config), - DataDir1 = filename:split(filename:absname(DataDir0)), - [_|DataDir2] = lists:reverse(DataDir1), - DataDir = filename:join(lists:reverse(DataDir2) ++ [?snmp_test_data]), + ?DBG("init_per_testcase2 -> ~p", [erlang:nodes()]), - PrivDir = ?config(priv_dir, Config), + CaseTopDir = snmp_test_lib:init_testcase_top_dir(Case, Config), - TopDir = filename:join(PrivDir, ?MODULE), - case file:make_dir(TopDir) of - ok -> - ok; - {error, eexist} -> - ok; - Error -> - ?FAIL({failed_creating_subsuite_top_dir, Error}) - end, - - CaseTopDir = filename:join(TopDir, Case), - ?line ok = file:make_dir(CaseTopDir), - %% -- Manager dirs -- - MgrTopDir = filename:join(CaseTopDir, "manager/"), + MgrTopDir = filename:join(CaseTopDir, "manager/"), + ?DBG("init_per_testcase2 -> try create manager top dir: ~n~p", + [MgrTopDir]), ?line ok = file:make_dir(MgrTopDir), MgrConfDir = filename:join(MgrTopDir, "conf/"), @@ -200,10 +209,9 @@ init_per_testcase2(Case, Config) -> AgLogDir = filename:join(AgTopDir, "log/"), ?line ok = file:make_dir(AgLogDir), - Conf = [{snmp_data_dir, DataDir}, - {watchdog, ?WD_START(?MINS(5))}, + Conf = [{watchdog, ?WD_START(?MINS(5))}, {ip, ?LOCALHOST()}, - {top_dir, TopDir}, + {case_top_dir, CaseTopDir}, {agent_dir, AgTopDir}, {agent_conf_dir, AgConfDir}, {agent_db_dir, AgDbDir}, @@ -388,9 +396,11 @@ all() -> {group, user_tests}, {group, agent_tests}, {group, request_tests}, + {group, request_tests_mt}, {group, event_tests}, + {group, event_tests_mt}, discovery, - {group, tickets} + {group, tickets} ]. groups() -> @@ -431,6 +441,15 @@ groups() -> {group, misc_request_tests} ] }, + {request_tests_mt, [], + [ + {group, get_tests}, + {group, get_next_tests}, + {group, set_tests}, + {group, bulk_tests}, + {group, misc_request_tests} + ] + }, {get_tests, [], [ simple_sync_get1, @@ -477,18 +496,30 @@ groups() -> misc_async2 ] }, - {event_tests, [], - [ - trap1%% , - %% trap2, - %% inform1, - %% inform2, - %% inform3, - %% inform4, - %% inform_swarm, - %% report - ] - }, + {event_tests, [], + [ + trap1, + trap2, + inform1, + inform2, + inform3, + inform4, + inform_swarm, + report + ] + }, + {event_tests_mt, [], + [ + trap1, + trap2, + inform1, + inform2, + inform3, + inform4, + inform_swarm, + report + ] + }, {tickets, [], [ {group, otp8015}, @@ -507,11 +538,21 @@ groups() -> } ]. -init_per_group(_GroupName, Config) -> - Config. +init_per_group(request_tests_mt = GroupName, Config) -> + snmp_test_lib:init_group_top_dir( + GroupName, + [{manager_net_if_module, snmpm_net_if_mt} | Config]); +init_per_group(event_tests_mt = GroupName, Config) -> + snmp_test_lib:init_group_top_dir( + GroupName, + [{manager_net_if_module, snmpm_net_if_mt} | Config]); +init_per_group(GroupName, Config) -> + snmp_test_lib:init_group_top_dir(GroupName, Config). + end_per_group(_GroupName, Config) -> - Config. + %% Do we really need to do this? + lists:keydelete(snmp_group_top_dir, 1, Config). %%====================================================================== @@ -1571,6 +1612,11 @@ simple_sync_get1(Config) when is_list(Config) -> ?line ok = mgr_user_load_mib(Node, std_mib()), Oids2 = [[sysObjectID, 0], [sysDescr, 0], [sysUpTime, 0]], ?line ok = do_simple_sync_get(Node, Addr, Port, Oids2), + + p("Display log"), + display_log(Config), + + p("done"), ok. do_simple_sync_get(Node, Addr, Port, Oids) -> @@ -1578,7 +1624,7 @@ do_simple_sync_get(Node, Addr, Port, Oids) -> ?DBG("~n Reply: ~p" "~n Rem: ~w", [Reply, Rem]), - + %% verify that the operation actually worked: %% The order should be the same, so no need to seach ?line ok = case Reply of @@ -1612,7 +1658,9 @@ simple_sync_get2(suite) -> []; simple_sync_get2(Config) when is_list(Config) -> process_flag(trap_exit, true), put(tname, ssg2), - do_simple_sync_get2(Config). + do_simple_sync_get2(Config), + display_log(Config), + ok. do_simple_sync_get2(Config) -> Get = fun(Node, TargetName, Oids) -> @@ -1677,7 +1725,9 @@ simple_sync_get3(suite) -> []; simple_sync_get3(Config) when is_list(Config) -> process_flag(trap_exit, true), put(tname, ssg3), - do_simple_sync_get3(Config). + do_simple_sync_get3(Config), + display_log(Config), + ok. do_simple_sync_get3(Config) -> Self = self(), @@ -1703,8 +1753,8 @@ do_simple_sync_get3(Config) -> %%====================================================================== -simple_async_get1(doc) -> ["Simple (async) get-request - " - "Old style (Addr & Port)"]; +simple_async_get1(doc) -> + ["Simple (async) get-request - Old style (Addr & Port)"]; simple_async_get1(suite) -> []; simple_async_get1(Config) when is_list(Config) -> process_flag(trap_exit, true), @@ -1766,6 +1816,7 @@ simple_async_get1(Config) when is_list(Config) -> p("manager info when ending test: ~n~p", [mgr_info(MgrNode)]), p("agent info when ending test: ~n~p", [agent_info(AgentNode)]), + display_log(Config), ok. async_g_exec1(Node, Addr, Port, Oids) -> @@ -1816,7 +1867,9 @@ simple_async_get2(Config) when is_list(Config) -> TargetName = ?config(manager_agent_target_name, Config), Get = fun(Oids) -> async_g_exec2(MgrNode, TargetName, Oids) end, PostVerify = fun(Res) -> Res end, - do_simple_async_sync_get2(Config, MgrNode, AgentNode, Get, PostVerify). + do_simple_async_sync_get2(Config, MgrNode, AgentNode, Get, PostVerify), + display_log(Config), + ok. do_simple_async_sync_get2(Config, MgrNode, AgentNode, Get, PostVerify) -> ?line ok = mgr_user_load_mib(MgrNode, std_mib()), @@ -1905,7 +1958,9 @@ simple_async_get3(Config) when is_list(Config) -> PostVerify = fun(ok) -> receive Msg -> ok end; (Error) -> Error end, - do_simple_async_sync_get2(Config, MgrNode, AgentNode, Get, PostVerify). + do_simple_async_sync_get2(Config, MgrNode, AgentNode, Get, PostVerify), + display_log(Config), + ok. async_g_exec3(Node, TargetName, Oids, SendOpts) -> mgr_user_async_get2(Node, TargetName, Oids, SendOpts). @@ -1999,6 +2054,8 @@ simple_sync_get_next1(Config) when is_list(Config) -> end, ?line ok = do_simple_get_next(8, MgrNode, Addr, Port, Oids08, VF08), + + display_log(Config), ok. @@ -2062,7 +2119,10 @@ simple_sync_get_next2(Config) when is_list(Config) -> mgr_user_sync_get_next(Node, TargetName, Oids) end, PostVerify = fun(Res) -> Res end, - do_simple_sync_get_next2(Config, GetNext, PostVerify). + do_simple_sync_get_next2(Config, GetNext, PostVerify), + display_log(Config), + ok. + do_simple_sync_get_next2(Config, GetNext, PostVerify) when is_function(GetNext, 3) andalso is_function(PostVerify, 1) -> @@ -2193,7 +2253,9 @@ simple_sync_get_next3(Config) when is_list(Config) -> PostVerify = fun(ok) -> receive Msg -> ok end; (Error) -> Error end, - do_simple_sync_get_next2(Config, GetNext, PostVerify). + do_simple_sync_get_next2(Config, GetNext, PostVerify), + display_log(Config), + ok. %%====================================================================== @@ -2286,6 +2348,7 @@ simple_async_get_next1(Config) when is_list(Config) -> p("manager info when ending test: ~n~p", [mgr_info(MgrNode)]), p("agent info when ending test: ~n~p", [agent_info(AgentNode)]), + display_log(Config), ok. @@ -2315,7 +2378,9 @@ simple_async_get_next2(Config) when is_list(Config) -> async_gn_exec2(MgrNode, TargetName, Oids) end, PostVerify = fun(Res) -> Res end, - do_simple_async_get_next2(MgrNode, AgentNode, GetNext, PostVerify). + do_simple_async_get_next2(MgrNode, AgentNode, GetNext, PostVerify), + display_log(Config), + ok. do_simple_async_get_next2(MgrNode, AgentNode, GetNext, PostVerify) when is_function(GetNext, 1) andalso is_function(PostVerify, 1) -> @@ -2437,7 +2502,9 @@ simple_async_get_next3(Config) when is_list(Config) -> (Error) -> Error end, - do_simple_async_get_next2(MgrNode, AgentNode, GetNext, PostVerify). + do_simple_async_get_next2(MgrNode, AgentNode, GetNext, PostVerify), + display_log(Config), + ok. async_gn_exec3(Node, TargetName, Oids, SendOpts) -> mgr_user_async_get_next2(Node, TargetName, Oids, SendOpts). @@ -2475,6 +2542,8 @@ simple_sync_set1(Config) when is_list(Config) -> {[sysLocation, 0], Val22} ], ?line ok = do_simple_set1(Node, Addr, Port, VAVs2), + + display_log(Config), ok. do_simple_set1(Node, Addr, Port, VAVs) -> @@ -2527,7 +2596,9 @@ simple_sync_set2(Config) when is_list(Config) -> end, PostVerify = fun() -> ok end, - do_simple_sync_set2(Config, Set, PostVerify). + do_simple_sync_set2(Config, Set, PostVerify), + display_log(Config), + ok. do_simple_sync_set2(Config, Set, PostVerify) when is_function(Set, 3) andalso is_function(PostVerify, 0) -> @@ -2604,7 +2675,9 @@ simple_sync_set3(Config) when is_list(Config) -> end, PostVerify = fun() -> receive Msg -> ok end end, - do_simple_sync_set2(Config, Set, PostVerify). + do_simple_sync_set2(Config, Set, PostVerify), + display_log(Config), + ok. %%====================================================================== @@ -2663,6 +2736,7 @@ simple_async_set1(Config) when is_list(Config) -> p("manager info when ending test: ~n~p", [mgr_info(MgrNode)]), p("agent info when ending test: ~n~p", [agent_info(AgentNode)]), + display_log(Config), ok. @@ -2724,7 +2798,9 @@ simple_async_set2(Config) when is_list(Config) -> end, PostVerify = fun(Res) -> Res end, - do_simple_async_set2(MgrNode, AgentNode, Set, PostVerify). + do_simple_async_set2(MgrNode, AgentNode, Set, PostVerify), + display_log(Config), + ok. do_simple_async_set2(MgrNode, AgentNode, Set, PostVerify) -> Requests = @@ -2806,7 +2882,9 @@ simple_async_set3(Config) when is_list(Config) -> (Res) -> Res end, - do_simple_async_set2(MgrNode, AgentNode, Set, PostVerify). + do_simple_async_set2(MgrNode, AgentNode, Set, PostVerify), + display_log(Config), + ok. async_s_exec3(Node, TargetName, VAVs, SendOpts) -> mgr_user_async_set2(Node, TargetName, VAVs, SendOpts). @@ -2932,6 +3010,7 @@ simple_sync_get_bulk1(Config) when is_list(Config) -> 0, 2, [[TCnt2, 1]], VF11), + display_log(Config), ok. fl(L) -> @@ -3004,7 +3083,9 @@ simple_sync_get_bulk2(Config) when is_list(Config) -> end, PostVerify = fun(Res) -> Res end, - do_simple_sync_get_bulk2(Config, MgrNode, AgentNode, GetBulk, PostVerify). + do_simple_sync_get_bulk2(Config, MgrNode, AgentNode, GetBulk, PostVerify), + display_log(Config), + ok. do_simple_sync_get_bulk2(Config, MgrNode, AgentNode, GetBulk, PostVerify) -> %% -- 1 -- @@ -3169,7 +3250,9 @@ simple_sync_get_bulk3(Config) when is_list(Config) -> (Res) -> Res end, - do_simple_sync_get_bulk2(Config, MgrNode, AgentNode, GetBulk, PostVerify). + do_simple_sync_get_bulk2(Config, MgrNode, AgentNode, GetBulk, PostVerify), + display_log(Config), + ok. %%====================================================================== @@ -3308,6 +3391,7 @@ simple_async_get_bulk1(Config) when is_list(Config) -> p("manager info when ending test: ~n~p", [mgr_info(MgrNode)]), p("agent info when ending test: ~n~p", [agent_info(AgentNode)]), + display_log(Config), ok. @@ -3340,7 +3424,9 @@ simple_async_get_bulk2(Config) when is_list(Config) -> end, PostVerify = fun(Res) -> Res end, - do_simple_async_get_bulk2(MgrNode, AgentNode, GetBulk, PostVerify). + do_simple_async_get_bulk2(MgrNode, AgentNode, GetBulk, PostVerify), + display_log(Config), + ok. do_simple_async_get_bulk2(MgrNode, AgentNode, GetBulk, PostVerify) -> %% We re-use the verification functions from the ssgb test-case @@ -3505,7 +3591,9 @@ simple_async_get_bulk3(Config) when is_list(Config) -> (Res) -> Res end, - do_simple_async_get_bulk2(MgrNode, AgentNode, GetBulk, PostVerify). + do_simple_async_get_bulk2(MgrNode, AgentNode, GetBulk, PostVerify), + display_log(Config), + ok. async_gb_exec3(Node, TargetName, {NR, MR, Oids}, SendOpts) -> mgr_user_async_get_bulk2(Node, TargetName, NR, MR, Oids, SendOpts). @@ -3697,6 +3785,7 @@ misc_async1(Config) when is_list(Config) -> p("manager info when ending test: ~n~p", [mgr_info(MgrNode)]), p("agent info when ending test: ~n~p", [agent_info(AgentNode)]), + display_log(Config), ok. @@ -3885,6 +3974,7 @@ misc_async2(Config) when is_list(Config) -> p("manager info when ending test: ~n~p", [mgr_info(MgrNode)]), p("agent info when ending test: ~n~p", [agent_info(AgentNode)]), + display_log(Config), ok. @@ -4099,7 +4189,9 @@ trap1(Config) when is_list(Config) -> {5, "Manager and agent info after test completion", Cmd1} ], - command_handler(Commands). + command_handler(Commands), + display_log(Config), + ok. %%====================================================================== @@ -4290,7 +4382,9 @@ trap2(Config) when is_list(Config) -> {7, "Manager and agent info after test completion", Cmd1} ], - command_handler(Commands). + command_handler(Commands), + display_log(Config), + ok. %%====================================================================== @@ -4415,7 +4509,9 @@ inform1(Config) when is_list(Config) -> {6, "Manager and agent info after test completion", Cmd1} ], - command_handler(Commands). + command_handler(Commands), + display_log(Config), + ok. %%====================================================================== @@ -4423,7 +4519,7 @@ inform1(Config) when is_list(Config) -> inform2(suite) -> []; inform2(Config) when is_list(Config) -> process_flag(trap_exit, true), - put(tname,i2), + put(tname, i2), p("starting with Config: ~p~n", [Config]), MgrNode = ?config(manager_node, Config), @@ -4577,7 +4673,7 @@ inform2(Config) when is_list(Config) -> [ {1, "Manager and agent info at start of test", Cmd1}, {2, "Send notifcation [no receiver] from agent", Cmd2}, - {3, "await inform-sent acknowledge from agent", Cmd3}, + {3, "Await inform-sent acknowledge from agent", Cmd3}, {4, "Await first inform to manager - do not reply", Cmd4}, {5, "Await second inform to manager - reply", Cmd5}, {6, "await inform-acknowledge from agent", Cmd6}, @@ -4585,7 +4681,9 @@ inform2(Config) when is_list(Config) -> {8, "Manager and agent info after test completion", Cmd1} ], - command_handler(Commands). + command_handler(Commands), + display_log(Config), + ok. %%====================================================================== @@ -4719,7 +4817,9 @@ inform3(Config) when is_list(Config) -> {9, "Manager and agent info after test completion", Cmd1} ], - command_handler(Commands). + command_handler(Commands), + display_log(Config), + ok. %%====================================================================== @@ -4835,7 +4935,9 @@ inform4(Config) when is_list(Config) -> {6, "Manager and agent info after test completion", Cmd1} ], - command_handler(Commands). + command_handler(Commands), + display_log(Config), + ok. %%====================================================================== @@ -4923,7 +5025,10 @@ inform_swarm(Config) when is_list(Config) -> {5, "Manager and agent info after test completion", Cmd1} ], - command_handler(Commands). + command_handler(Commands), + display_log(Config), + ok. + inform_swarm_collector(N) -> inform_swarm_collector(N, 0, 0, 0, 10000). @@ -5227,8 +5332,8 @@ init_agent(Config) -> %% -- %% Retrieve some dir's %% - Dir = ?config(top_dir, Config), - DataDir = ?config(data_dir, Config), + Dir = ?config(agent_dir, Config), + MibDir = ?config(mib_dir, Config), %% -- %% Start node @@ -5259,7 +5364,7 @@ init_agent(Config) -> ?line ok = write_agent_config(Vsns, Config), Conf = [{agent_node, Node}, - {mib_dir, DataDir} | Config], + {mib_dir, MibDir} | Config], %% %% Start the agent @@ -5720,6 +5825,15 @@ start_manager(Node, Vsns, Conf0, Opts) -> AtlSeqNo = get_opt(manager_atl_seqno, Conf0, false), + NetIfConf = + case get_opt(manager_net_if_module, Conf0, no_module) of + no_module -> + [{verbosity, NetIfVerbosity}]; + NetIfModule -> + [{module, NetIfModule}, + {verbosity, NetIfVerbosity}] + end, + Env = [{versions, Vsns}, {inform_request_behaviour, IRB}, {audit_trail_log, [{type, read_write}, @@ -5732,7 +5846,7 @@ start_manager(Node, Vsns, Conf0, Opts) -> {verbosity, ConfigVerbosity}]}, {note_store, [{verbosity, NoteStoreVerbosity}]}, {server, [{verbosity, ServerVerbosity}]}, - {net_if, [{verbosity, NetIfVerbosity}]}], + {net_if, NetIfConf}], ?line ok = set_mgr_env(Node, Env), ?line ok = start_snmp(Node), @@ -6018,6 +6132,38 @@ write_conf_file(Dir, File, Str) -> %% ------ +display_log(Config) -> + case lists:keysearch(manager_log_dir, 1, Config) of + {value, {_, Dir}} -> + case lists:keysearch(manager_node, 1, Config) of + {value, {_, Node}} -> + LogDir = Dir, + Mibs = [], + OutFile = j(LogDir, "snmpm_log.txt"), + p("~n" + "=========================" + " < Audit Trail Log > " + "=========================" + "~n"), + rcall(Node, snmpm, log_to_txt, [LogDir, Mibs, OutFile]), + rcall(Node, snmpm, log_to_io, [LogDir, Mibs]), + p("~n" + "=========================" + " < / Audit Trail Log > " + "=========================" + "~n"); + false -> + p("display_log -> no manager node found"), + ok + end; + false -> + p("display_log -> no manager log dir found"), + ok + end. + + +%% ------ + test2_mib(Config) -> j(test_mib_dir(Config), "Test2.bin"). @@ -6034,7 +6180,7 @@ snmpv2_mib() -> j(mib_dir(), "SNMPv2-MIB.bin"). test_mib_dir(Config) -> - ?config(snmp_data_dir, Config). + ?config(mib_dir, Config). mib_dir() -> j(code:priv_dir(snmp), "mibs"). diff --git a/lib/snmp/test/snmp_test_data/Test3.mib b/lib/snmp/test/snmp_test_data/Test3.mib new file mode 100644 index 0000000000..7f76e4dba4 --- /dev/null +++ b/lib/snmp/test/snmp_test_data/Test3.mib @@ -0,0 +1,123 @@ +Test3 DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY, OBJECT-TYPE, Integer32, snmpModules, mib-2 + FROM SNMPv2-SMI + MODULE-COMPLIANCE, OBJECT-GROUP + FROM SNMPv2-CONF + tEntry + FROM Test2; + +t3MIB MODULE-IDENTITY + LAST-UPDATED "1203090000Z" + ORGANIZATION "" + CONTACT-INFO + "" + DESCRIPTION + "Test mib, used to test processing of requests." + ::= { snmpModules 42 } + + +-- Administrative assignments **************************************** + +t3MIBObjects OBJECT IDENTIFIER ::= { t3MIB 1 } +t3MIBConformance OBJECT IDENTIFIER ::= { t3MIB 2 } + + +-- test4 OBJECT IDENTIFIER ::= { mib-2 18 } + +tAugTable OBJECT-TYPE + SYNTAX SEQUENCE OF TAugEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "This table AUGMENTS tTable of the Test2 MIB." + ::= { t3MIBObjects 1 } + +tAugEntry OBJECT-TYPE + SYNTAX TAugEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An entry (conceptual row) in the sysORTable." + AUGMENTS { tEntry } + ::= { tAugTable 1 } + +TAugEntry ::= SEQUENCE { + tFoo1 OCTET STRING, + tFoo2 OCTET STRING, + tBar1 Integer32, + tBar2 Integer32 +} + +tFoo1 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..255)) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "A string." + DEFVAL { "foo 1" } + ::= { tAugEntry 1 } + +tFoo2 OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..255)) + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A string." + DEFVAL { "foo 2" } + ::= { tAugEntry 2 } + +tBar1 OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "An integer." + DEFVAL { 42 } + ::= { tAugEntry 3 } + +tBar2 OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An integer." + DEFVAL { 42 } + ::= { tAugEntry 4 } + + +-- Conformance Information ******************************************* + +t3MIBCompliances OBJECT IDENTIFIER + ::= { t3MIBConformance 1 } +t3MIBGroups OBJECT IDENTIFIER + ::= { t3MIBConformance 2 } + +-- Compliance statements + +t3MIBCompliance MODULE-COMPLIANCE + STATUS current + DESCRIPTION + "The compliance statement for SNMP engines which + implement the SNMP-COMMUNITY-MIB." + + MODULE -- this module + MANDATORY-GROUPS { t3Group } + + ::= { t3MIBCompliances 1 } + +t3Group OBJECT-GROUP + OBJECTS { + tFoo1, + tFoo2, + tBar1, + tBar2 + } + STATUS current + DESCRIPTION + "A group." + ::= { t3MIBGroups 1 } + + +END diff --git a/lib/snmp/test/snmp_test_lib.erl b/lib/snmp/test/snmp_test_lib.erl index e4d58a1253..26115a0c74 100644 --- a/lib/snmp/test/snmp_test_lib.erl +++ b/lib/snmp/test/snmp_test_lib.erl @@ -25,7 +25,10 @@ -export([hostname/0, hostname/1, localhost/0, os_type/0, sz/1, display_suite_info/1]). -export([non_pc_tc_maybe_skip/4, os_based_skip/1]). --export([replace_config/3, set_config/3, get_config/2, get_config/3]). +-export([fix_data_dir/1, + init_suite_top_dir/2, init_group_top_dir/2, init_testcase_top_dir/2, + lookup/2, + replace_config/3, set_config/3, get_config/2, get_config/3]). -export([fail/3, skip/3]). -export([millis/0, millis_diff/2, hours/1, minutes/1, seconds/1, sleep/1]). -export([flush_mqueue/0, trap_exit/0, trap_exit/1]). @@ -198,6 +201,97 @@ os_based_skip(_Crap) -> %% Test suite utility functions %% +fix_data_dir(Config) -> + DataDir0 = lookup(data_dir, Config), + DataDir1 = filename:split(filename:absname(DataDir0)), + [_|DataDir2] = lists:reverse(DataDir1), + DataDir = filename:join(lists:reverse(DataDir2) ++ [?snmp_test_data]), + Config1 = lists:keydelete(data_dir, 1, Config), + [{data_dir, DataDir ++ "/"} | Config1]. + + +init_suite_top_dir(Suite, Config0) -> + io:format("~w:init_suite_top_dir -> entry with" + "~n Suite: ~p" + "~n Config0: ~p" + "~n", [?MODULE, Suite, Config0]), + Dir = lookup(priv_dir, Config0), + SuiteTopDir = filename:join(Dir, Suite), + case file:make_dir(SuiteTopDir) of + ok -> + ok; + {error, eexist} -> + ok; + {error, Reason} -> + fail({failed_creating_suite_top_dir, SuiteTopDir, Reason}, + ?MODULE, ?LINE) + end, + + %% This is just in case... + Config1 = lists:keydelete(snmp_group_top_dir, 1, Config0), + Config2 = lists:keydelete(snmp_suite_top_dir, 1, Config1), + [{snmp_suite_top_dir, SuiteTopDir} | Config2]. + + +init_group_top_dir(GroupName, Config) -> + io:format("~w:init_group_top_dir -> entry with" + "~n GroupName: ~p" + "~n Config: ~p" + "~n", [?MODULE, GroupName, Config]), + case lists:keysearch(snmp_group_top_dir, 1, Config) of + {value, {_Key, Dir}} -> + %% This is a sub-group, so create our dir within Dir + GroupTopDir = filename:join(Dir, GroupName), + case file:make_dir(GroupTopDir) of + ok -> + ok; + {error, Reason} -> + fail({failed_creating_group_top_dir, GroupTopDir, Reason}, + ?MODULE, ?LINE) + end, + [{snmp_group_top_dir, GroupTopDir} | Config]; + + _ -> + case lists:keysearch(snmp_suite_top_dir, 1, Config) of + {value, {_Key, Dir}} -> + GroupTopDir = filename:join(Dir, GroupName), + case file:make_dir(GroupTopDir) of + ok -> + ok; + {error, Reason} -> + fail({failed_creating_group_top_dir, + GroupTopDir, Reason}, + ?MODULE, ?LINE) + end, + [{snmp_group_top_dir, GroupTopDir} | Config]; + _ -> + fail(could_not_find_suite_top_dir, ?MODULE, ?LINE) + end + end. + + +init_testcase_top_dir(Case, Config) -> + io:format("~w:init_testcase_top_dir -> entry with" + "~n Case: ~p" + "~n Config: ~p" + "~n", [?MODULE, Case, Config]), + case lists:keysearch(snmp_group_top_dir, 1, Config) of + {value, {_Key, Dir}} -> + CaseTopDir = filename:join(Dir, Case), + ok = file:make_dir(CaseTopDir), + CaseTopDir; + false -> + case lists:keysearch(snmp_suite_top_dir, 1, Config) of + {value, {_Key, Dir}} -> + CaseTopDir = filename:join(Dir, Case), + ok = file:make_dir(CaseTopDir), + CaseTopDir; + false -> + fail(failed_creating_case_top_dir, ?MODULE, ?LINE) + end + end. + + replace_config(Key, Config, NewValue) -> lists:keyreplace(Key, 1, Config, {Key, NewValue}). @@ -220,6 +314,9 @@ get_config(Key,C,Default) -> Default end. +lookup(Key, Config) -> + {value, {Key, Value}} = lists:keysearch(Key, 1, Config), + Value. fail(Reason, Mod, Line) -> exit({suite_failed, Reason, Mod, Line}). diff --git a/lib/snmp/test/test-mibs/RMON-MIB.mib b/lib/snmp/test/test-mibs/RMON-MIB.mib index 0824dbde1d..fa5bc82f4a 100644 --- a/lib/snmp/test/test-mibs/RMON-MIB.mib +++ b/lib/snmp/test/test-mibs/RMON-MIB.mib @@ -1,3826 +1,3958 @@ - RMON-MIB DEFINITIONS ::= BEGIN - - IMPORTS - Counter FROM RFC1155-SMI - mib-2,DisplayString FROM RFC1213-MIB - OBJECT-TYPE FROM RFC-1212 - TRAP-TYPE FROM RFC-1215; - - -- Remote Network Monitoring MIB - - rmon OBJECT IDENTIFIER ::= { mib-2 16 } - - - -- textual conventions - - OwnerString ::= DisplayString - -- This data type is used to model an administratively - -- assigned name of the owner of a resource. This - -- information is taken from the NVT ASCII character - -- set. It is suggested that this name contain one or - - - -- more of the following: IP address, management station - -- name, network manager's name, location, or phone - -- number. - -- In some cases the agent itself will be the owner of - -- an entry. In these cases, this string shall be set - -- to a string starting with 'monitor'. - -- - -- SNMP access control is articulated entirely in terms - -- of the contents of MIB views; access to a particular - -- SNMP object instance depends only upon its presence - -- or absence in a particular MIB view and never upon - -- its value or the value of related object instances. - -- Thus, objects of this type afford resolution of - -- resource contention only among cooperating managers; - -- they realize no access control function with respect - -- to uncooperative parties. - -- - -- By convention, objects with this syntax are declared as - -- having - -- - -- SIZE (0..127) - - EntryStatus ::= INTEGER - { valid(1), - createRequest(2), - underCreation(3), - invalid(4) - } - -- The status of a table entry. - -- - -- Setting this object to the value invalid(4) has the - -- effect of invalidating the corresponding entry. - -- That is, it effectively disassociates the mapping - -- identified with said entry. - -- It is an implementation-specific matter as to whether - -- the agent removes an invalidated entry from the table. - -- Accordingly, management stations must be prepared to - -- receive tabular information from agents that - -- corresponds to entries currently not in use. Proper - -- interpretation of such entries requires examination - -- of the relevant EntryStatus object. - -- - -- An existing instance of this object cannot be set to - -- createRequest(2). This object may only be set to - -- createRequest(2) when this instance is created. When - -- this object is created, the agent may wish to create - -- supplemental object instances with default values - -- to complete a conceptual row in this table. Because - - - -- the creation of these default objects is entirely at - -- the option of the agent, the manager must not assume - -- that any will be created, but may make use of any that - -- are created. Immediately after completing the create - -- operation, the agent must set this object to - -- underCreation(3). - -- - -- When in the underCreation(3) state, an entry is - -- allowed to exist in a possibly incomplete, possibly - -- inconsistent state, usually to allow it to be - -- modified in mutiple PDUs. When in this state, an - -- entry is not fully active. Entries shall exist in - -- the underCreation(3) state until the management - -- station is finished configuring the entry and sets - -- this object to valid(1) or aborts, setting this - -- object to invalid(4). If the agent determines that - -- an entry has been in the underCreation(3) state for - -- an abnormally long time, it may decide that the - -- management station has crashed. If the agent makes - -- this decision, it may set this object to invalid(4) - -- to reclaim the entry. A prudent agent will - -- understand that the management station may need to - -- wait for human input and will allow for that - -- possibility in its determination of this abnormally - -- long period. - -- - -- An entry in the valid(1) state is fully configured and - -- consistent and fully represents the configuration or - -- operation such a row is intended to represent. For - -- example, it could be a statistical function that is - -- configured and active, or a filter that is available - -- in the list of filters processed by the packet capture - -- process. - -- - -- A manager is restricted to changing the state of an - -- entry in the following ways: - -- - -- create under - -- To: valid Request Creation invalid - -- From: - -- valid OK NO OK OK - -- createRequest N/A N/A N/A N/A - -- underCreation OK NO OK OK - -- invalid NO NO NO OK - -- nonExistent NO OK NO OK - -- - -- In the table above, it is not applicable to move the - -- state from the createRequest state to any other - - - -- state because the manager will never find the - -- variable in that state. The nonExistent state is - -- not a value of the enumeration, rather it means that - -- the entryStatus variable does not exist at all. - -- - -- An agent may allow an entryStatus variable to change - -- state in additional ways, so long as the semantics - -- of the states are followed. This allowance is made - -- to ease the implementation of the agent and is made - -- despite the fact that managers should never - -- excercise these additional state transitions. - - - statistics OBJECT IDENTIFIER ::= { rmon 1 } - history OBJECT IDENTIFIER ::= { rmon 2 } - alarm OBJECT IDENTIFIER ::= { rmon 3 } - hosts OBJECT IDENTIFIER ::= { rmon 4 } - hostTopN OBJECT IDENTIFIER ::= { rmon 5 } - matrix OBJECT IDENTIFIER ::= { rmon 6 } - filter OBJECT IDENTIFIER ::= { rmon 7 } - capture OBJECT IDENTIFIER ::= { rmon 8 } - event OBJECT IDENTIFIER ::= { rmon 9 } - - - -- The Ethernet Statistics Group - -- - -- Implementation of the Ethernet Statistics group is - -- optional. - -- - -- The ethernet statistics group contains statistics - -- measured by the probe for each monitored interface on - -- this device. These statistics take the form of free - -- running counters that start from zero when a valid entry - -- is created. - -- - -- This group currently has statistics defined only for - -- Ethernet interfaces. Each etherStatsEntry contains - -- statistics for one Ethernet interface. The probe must - -- create one etherStats entry for each monitored Ethernet - -- interface on the device. - - etherStatsTable OBJECT-TYPE - SYNTAX SEQUENCE OF EtherStatsEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A list of Ethernet statistics entries." - ::= { statistics 1 } - - - etherStatsEntry OBJECT-TYPE - SYNTAX EtherStatsEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A collection of statistics kept for a particular - Ethernet interface. As an example, an instance of the - etherStatsPkts object might be named etherStatsPkts.1" - INDEX { etherStatsIndex } - ::= { etherStatsTable 1 } - - EtherStatsEntry ::= SEQUENCE { - etherStatsIndex INTEGER (1..65535), - etherStatsDataSource OBJECT IDENTIFIER, - etherStatsDropEvents Counter, - etherStatsOctets Counter, - etherStatsPkts Counter, - etherStatsBroadcastPkts Counter, - etherStatsMulticastPkts Counter, - etherStatsCRCAlignErrors Counter, - etherStatsUndersizePkts Counter, - etherStatsOversizePkts Counter, - etherStatsFragments Counter, - etherStatsJabbers Counter, - etherStatsCollisions Counter, - etherStatsPkts64Octets Counter, - etherStatsPkts65to127Octets Counter, - etherStatsPkts128to255Octets Counter, - etherStatsPkts256to511Octets Counter, - etherStatsPkts512to1023Octets Counter, - etherStatsPkts1024to1518Octets Counter, - etherStatsOwner OwnerString, - etherStatsStatus EntryStatus - } - - etherStatsIndex OBJECT-TYPE - SYNTAX INTEGER (1..65535) - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The value of this object uniquely identifies this - etherStats entry." - ::= { etherStatsEntry 1 } - - etherStatsDataSource OBJECT-TYPE - SYNTAX OBJECT IDENTIFIER - ACCESS read-write - STATUS mandatory - - - DESCRIPTION - "This object identifies the source of the data that - this etherStats entry is configured to analyze. This - source can be any ethernet interface on this device. - In order to identify a particular interface, this - object shall identify the instance of the ifIndex - object, defined in RFC 1213 and RFC 1573 [4,6], for - the desired interface. For example, if an entry - were to receive data from interface #1, this object - would be set to ifIndex.1. - - The statistics in this group reflect all packets - on the local network segment attached to the - identified interface. - - An agent may or may not be able to tell if - fundamental changes to the media of the interface - have occurred and necessitate an invalidation of - this entry. For example, a hot-pluggable ethernet - card could be pulled out and replaced by a - token-ring card. In such a case, if the agent has - such knowledge of the change, it is recommended that - it invalidate this entry. - - This object may not be modified if the associated - etherStatsStatus object is equal to valid(1)." - ::= { etherStatsEntry 2 } - - etherStatsDropEvents OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of events in which packets - were dropped by the probe due to lack of resources. - Note that this number is not necessarily the number of - packets dropped; it is just the number of times this - condition has been detected." - ::= { etherStatsEntry 3 } - - etherStatsOctets OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of octets of data (including - those in bad packets) received on the - network (excluding framing bits but including - - - FCS octets). - - This object can be used as a reasonable estimate of - ethernet utilization. If greater precision is - desired, the etherStatsPkts and etherStatsOctets - objects should be sampled before and after a common - interval. The differences in the sampled values are - Pkts and Octets, respectively, and the number of - seconds in the interval is Interval. These values - are used to calculate the Utilization as follows: - - Pkts * (9.6 + 6.4) + (Octets * .8) - Utilization = ------------------------------------- - Interval * 10,000 - - The result of this equation is the value Utilization - which is the percent utilization of the ethernet - segment on a scale of 0 to 100 percent." - ::= { etherStatsEntry 4 } - - etherStatsPkts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of packets (including bad packets, - broadcast packets, and multicast packets) received." - ::= { etherStatsEntry 5 } - - etherStatsBroadcastPkts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of good packets received that were - directed to the broadcast address. Note that this - does not include multicast packets." - ::= { etherStatsEntry 6 } - - etherStatsMulticastPkts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of good packets received that were - directed to a multicast address. Note that this - number does not include packets directed to the - broadcast address." - - - ::= { etherStatsEntry 7 } - - etherStatsCRCAlignErrors OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of packets received that - had a length (excluding framing bits, but - including FCS octets) of between 64 and 1518 - octets, inclusive, but but had either a bad - Frame Check Sequence (FCS) with an integral - number of octets (FCS Error) or a bad FCS with - a non-integral number of octets (Alignment Error)." - ::= { etherStatsEntry 8 } - - etherStatsUndersizePkts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of packets received that were - less than 64 octets long (excluding framing bits, - but including FCS octets) and were otherwise well - formed." - ::= { etherStatsEntry 9 } - - etherStatsOversizePkts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of packets received that were - longer than 1518 octets (excluding framing bits, - but including FCS octets) and were otherwise - well formed." - ::= { etherStatsEntry 10 } - - etherStatsFragments OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of packets received that were less - than 64 octets in length (excluding framing bits but - including FCS octets) and had either a bad Frame - Check Sequence (FCS) with an integral number of - octets (FCS Error) or a bad FCS with a non-integral - - - number of octets (Alignment Error). - - Note that it is entirely normal for - etherStatsFragments to increment. This is because - it counts both runts (which are normal occurrences - due to collisions) and noise hits." - ::= { etherStatsEntry 11 } - - etherStatsJabbers OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of packets received that were - longer than 1518 octets (excluding framing bits, - but including FCS octets), and had either a bad - Frame Check Sequence (FCS) with an integral number - of octets (FCS Error) or a bad FCS with a - non-integral number of octets (Alignment Error). - - Note that this definition of jabber is different - than the definition in IEEE-802.3 section 8.2.1.5 - (10BASE5) and section 10.3.1.4 (10BASE2). These - documents define jabber as the condition where any - packet exceeds 20 ms. The allowed range to detect - jabber is between 20 ms and 150 ms." - ::= { etherStatsEntry 12 } - - etherStatsCollisions OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The best estimate of the total number of collisions - on this Ethernet segment. - - The value returned will depend on the location of - the RMON probe. Section 8.2.1.3 (10BASE-5) and - section 10.3.1.3 (10BASE-2) of IEEE standard 802.3 - states that a station must detect a collision, in - the receive mode, if three or more stations are - transmitting simultaneously. A repeater port must - detect a collision when two or more stations are - transmitting simultaneously. Thus a probe placed on - a repeater port could record more collisions than a - probe connected to a station on the same segment - would. - - - - Probe location plays a much smaller role when - considering 10BASE-T. 14.2.1.4 (10BASE-T) of IEEE - standard 802.3 defines a collision as the - simultaneous presence of signals on the DO and RD - circuits (transmitting and receiving at the same - time). A 10BASE-T station can only detect - collisions when it is transmitting. Thus probes - placed on a station and a repeater, should report - the same number of collisions. - - Note also that an RMON probe inside a repeater - should ideally report collisions between the - repeater and one or more other hosts (transmit - collisions as defined by IEEE 802.3k) plus receiver - collisions observed on any coax segments to which - the repeater is connected." - ::= { etherStatsEntry 13 } - - etherStatsPkts64Octets OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of packets (including bad - packets) received that were 64 octets in length - (excluding framing bits but including FCS octets)." - ::= { etherStatsEntry 14 } - - etherStatsPkts65to127Octets OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of packets (including bad - packets) received that were between - 65 and 127 octets in length inclusive - (excluding framing bits but including FCS octets)." - ::= { etherStatsEntry 15 } - - etherStatsPkts128to255Octets OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of packets (including bad - packets) received that were between - 128 and 255 octets in length inclusive - (excluding framing bits but including FCS octets)." - - - ::= { etherStatsEntry 16 } - - etherStatsPkts256to511Octets OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of packets (including bad - packets) received that were between - 256 and 511 octets in length inclusive - (excluding framing bits but including FCS octets)." - ::= { etherStatsEntry 17 } - - etherStatsPkts512to1023Octets OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of packets (including bad - packets) received that were between - 512 and 1023 octets in length inclusive - (excluding framing bits but including FCS octets)." - ::= { etherStatsEntry 18 } - - etherStatsPkts1024to1518Octets OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of packets (including bad - packets) received that were between - 1024 and 1518 octets in length inclusive - (excluding framing bits but including FCS octets)." - ::= { etherStatsEntry 19 } - - etherStatsOwner OBJECT-TYPE - SYNTAX OwnerString - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The entity that configured this entry and is - therefore using the resources assigned to it." - ::= { etherStatsEntry 20 } - - etherStatsStatus OBJECT-TYPE - SYNTAX EntryStatus - ACCESS read-write - STATUS mandatory - - - DESCRIPTION - "The status of this etherStats entry." - ::= { etherStatsEntry 21 } - - - -- The History Control Group - - -- Implementation of the History Control group is optional. - -- - -- The history control group controls the periodic statistical - -- sampling of data from various types of networks. The - -- historyControlTable stores configuration entries that each - -- define an interface, polling period, and other parameters. - -- Once samples are taken, their data is stored in an entry - -- in a media-specific table. Each such entry defines one - -- sample, and is associated with the historyControlEntry that - -- caused the sample to be taken. Each counter in the - -- etherHistoryEntry counts the same event as its - -- similarly-named counterpart in the etherStatsEntry, - -- except that each value here is a cumulative sum during a - -- sampling period. - -- - -- If the probe keeps track of the time of day, it should - -- start the first sample of the history at a time such that - -- when the next hour of the day begins, a sample is - -- started at that instant. This tends to make more - -- user-friendly reports, and enables comparison of reports - -- from different probes that have relatively accurate time - -- of day. - -- - -- The probe is encouraged to add two history control entries - -- per monitored interface upon initialization that describe - -- a short term and a long term polling period. Suggested - -- parameters are 30 seconds for the short term polling period - -- and 30 minutes for the long term period. - - historyControlTable OBJECT-TYPE - SYNTAX SEQUENCE OF HistoryControlEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A list of history control entries." - ::= { history 1 } - - historyControlEntry OBJECT-TYPE - SYNTAX HistoryControlEntry - ACCESS not-accessible - STATUS mandatory - - - DESCRIPTION - "A list of parameters that set up a periodic sampling - of statistics. As an example, an instance of the - historyControlInterval object might be named - historyControlInterval.2" - INDEX { historyControlIndex } - ::= { historyControlTable 1 } - - HistoryControlEntry ::= SEQUENCE { - historyControlIndex INTEGER (1..65535), - historyControlDataSource OBJECT IDENTIFIER, - historyControlBucketsRequested INTEGER (1..65535), - historyControlBucketsGranted INTEGER (1..65535), - historyControlInterval INTEGER (1..3600), - historyControlOwner OwnerString, - historyControlStatus EntryStatus - } - - historyControlIndex OBJECT-TYPE - SYNTAX INTEGER (1..65535) - ACCESS read-only - STATUS mandatory - DESCRIPTION - "An index that uniquely identifies an entry in the - historyControl table. Each such entry defines a - set of samples at a particular interval for an - interface on the device." - ::= { historyControlEntry 1 } - - historyControlDataSource OBJECT-TYPE - SYNTAX OBJECT IDENTIFIER - ACCESS read-write - STATUS mandatory - DESCRIPTION - "This object identifies the source of the data for - which historical data was collected and - placed in a media-specific table on behalf of this - historyControlEntry. This source can be any - interface on this device. In order to identify - a particular interface, this object shall identify - the instance of the ifIndex object, defined - in RFC 1213 and RFC 1573 [4,6], for the desired - interface. For example, if an entry were to receive - data from interface #1, this object would be set - to ifIndex.1. - - The statistics in this group reflect all packets - on the local network segment attached to the - - - identified interface. - - An agent may or may not be able to tell if fundamental - changes to the media of the interface have occurred - and necessitate an invalidation of this entry. For - example, a hot-pluggable ethernet card could be - pulled out and replaced by a token-ring card. In - such a case, if the agent has such knowledge of the - change, it is recommended that it invalidate this - entry. - - This object may not be modified if the associated - historyControlStatus object is equal to valid(1)." - ::= { historyControlEntry 2 } - - historyControlBucketsRequested OBJECT-TYPE - SYNTAX INTEGER (1..65535) - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The requested number of discrete time intervals - over which data is to be saved in the part of the - media-specific table associated with this - historyControlEntry. - - When this object is created or modified, the probe - should set historyControlBucketsGranted as closely to - this object as is possible for the particular probe - implementation and available resources." - DEFVAL { 50 } - ::= { historyControlEntry 3 } - - historyControlBucketsGranted OBJECT-TYPE - SYNTAX INTEGER (1..65535) - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of discrete sampling intervals - over which data shall be saved in the part of - the media-specific table associated with this - historyControlEntry. - - When the associated historyControlBucketsRequested - object is created or modified, the probe - should set this object as closely to the requested - value as is possible for the particular - probe implementation and available resources. The - probe must not lower this value except as a result - - - of a modification to the associated - historyControlBucketsRequested object. - - There will be times when the actual number of - buckets associated with this entry is less than - the value of this object. In this case, at the - end of each sampling interval, a new bucket will - be added to the media-specific table. - - When the number of buckets reaches the value of - this object and a new bucket is to be added to the - media-specific table, the oldest bucket associated - with this historyControlEntry shall be deleted by - the agent so that the new bucket can be added. - - When the value of this object changes to a value less - than the current value, entries are deleted - from the media-specific table associated with this - historyControlEntry. Enough of the oldest of these - entries shall be deleted by the agent so that their - number remains less than or equal to the new value of - this object. - - When the value of this object changes to a value - greater than the current value, the number of - associated media- specific entries may be allowed to - grow." - ::= { historyControlEntry 4 } - - historyControlInterval OBJECT-TYPE - SYNTAX INTEGER (1..3600) - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The interval in seconds over which the data is - sampled for each bucket in the part of the - media-specific table associated with this - historyControlEntry. This interval can - be set to any number of seconds between 1 and - 3600 (1 hour). - - Because the counters in a bucket may overflow at their - maximum value with no indication, a prudent manager - will take into account the possibility of overflow - in any of the associated counters. It is important - to consider the minimum time in which any counter - could overflow on a particular media type and set - the historyControlInterval object to a value less - - - than this interval. This is typically most - important for the 'octets' counter in any - media-specific table. For example, on an Ethernet - network, the etherHistoryOctets counter could - overflow in about one hour at the Ethernet's maximum - utilization. - - This object may not be modified if the associated - historyControlStatus object is equal to valid(1)." - DEFVAL { 1800 } - ::= { historyControlEntry 5 } - - historyControlOwner OBJECT-TYPE - SYNTAX OwnerString - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The entity that configured this entry and is - therefore using the resources assigned to it." - ::= { historyControlEntry 6 } - - historyControlStatus OBJECT-TYPE - SYNTAX EntryStatus - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The status of this historyControl entry. - - Each instance of the media-specific table associated - with this historyControlEntry will be deleted by the - agent if this historyControlEntry is not equal to - valid(1)." - ::= { historyControlEntry 7 } - - - -- The Ethernet History Group - - -- Implementation of the Ethernet History group is optional. - -- - -- The Ethernet History group records periodic - -- statistical samples from a network and stores them - -- for later retrieval. Once samples are taken, their - -- data is stored in an entry in a media-specific - -- table. Each such entry defines one sample, and is - -- associated with the historyControlEntry that caused - -- the sample to be taken. This group defines the - -- etherHistoryTable, for Ethernet networks. - -- - - - etherHistoryTable OBJECT-TYPE - SYNTAX SEQUENCE OF EtherHistoryEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A list of Ethernet history entries." - ::= { history 2 } - - etherHistoryEntry OBJECT-TYPE - SYNTAX EtherHistoryEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "An historical sample of Ethernet statistics on a - particular Ethernet interface. This sample is - associated with the historyControlEntry which set up - the parameters for a regular collection of these - samples. As an example, an instance of the - etherHistoryPkts object might be named - etherHistoryPkts.2.89" - INDEX { etherHistoryIndex , etherHistorySampleIndex } - ::= { etherHistoryTable 1 } - - EtherHistoryEntry ::= SEQUENCE { - etherHistoryIndex INTEGER (1..65535), - etherHistorySampleIndex INTEGER (1..2147483647), - etherHistoryIntervalStart TimeTicks, - etherHistoryDropEvents Counter, - etherHistoryOctets Counter, - etherHistoryPkts Counter, - etherHistoryBroadcastPkts Counter, - etherHistoryMulticastPkts Counter, - etherHistoryCRCAlignErrors Counter, - etherHistoryUndersizePkts Counter, - etherHistoryOversizePkts Counter, - etherHistoryFragments Counter, - etherHistoryJabbers Counter, - etherHistoryCollisions Counter, - etherHistoryUtilization INTEGER (0..10000) - } - - etherHistoryIndex OBJECT-TYPE - SYNTAX INTEGER (1..65535) - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The history of which this entry is a part. The - history identified by a particular value of this - - - index is the same history as identified - by the same value of historyControlIndex." - ::= { etherHistoryEntry 1 } - - etherHistorySampleIndex OBJECT-TYPE - SYNTAX INTEGER (1..2147483647) - ACCESS read-only - STATUS mandatory - DESCRIPTION - "An index that uniquely identifies the particular - sample this entry represents among all samples - associated with the same historyControlEntry. - This index starts at 1 and increases by one - as each new sample is taken." - ::= { etherHistoryEntry 2 } - - etherHistoryIntervalStart OBJECT-TYPE - SYNTAX TimeTicks - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The value of sysUpTime at the start of the interval - over which this sample was measured. If the probe - keeps track of the time of day, it should start - the first sample of the history at a time such that - when the next hour of the day begins, a sample is - started at that instant. Note that following this - rule may require the probe to delay collecting the - first sample of the history, as each sample must be - of the same interval. Also note that the sample which - is currently being collected is not accessible in this - table until the end of its interval." - ::= { etherHistoryEntry 3 } - - etherHistoryDropEvents OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of events in which packets - were dropped by the probe due to lack of resources - during this sampling interval. Note that this number - is not necessarily the number of packets dropped, it - is just the number of times this condition has been - detected." - ::= { etherHistoryEntry 4 } - - etherHistoryOctets OBJECT-TYPE - - - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of octets of data (including - those in bad packets) received on the - network (excluding framing bits but including - FCS octets)." - ::= { etherHistoryEntry 5 } - - etherHistoryPkts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of packets (including bad packets) - received during this sampling interval." - ::= { etherHistoryEntry 6 } - - etherHistoryBroadcastPkts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of good packets received during this - sampling interval that were directed to the - broadcast address." - ::= { etherHistoryEntry 7 } - - etherHistoryMulticastPkts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of good packets received during this - sampling interval that were directed to a - multicast address. Note that this number does not - include packets addressed to the broadcast address." - ::= { etherHistoryEntry 8 } - - etherHistoryCRCAlignErrors OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of packets received during this sampling - interval that had a length (excluding framing bits - but including FCS octets) between 64 and 1518 - - - octets, inclusive, but had either a bad Frame Check - Sequence (FCS) with an integral number of octets - (FCS Error) or a bad FCS with a non-integral number - of octets (Alignment Error)." - ::= { etherHistoryEntry 9 } - - etherHistoryUndersizePkts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of packets received during this - sampling interval that were less than 64 octets - long (excluding framing bits but including FCS - octets) and were otherwise well formed." - ::= { etherHistoryEntry 10 } - - etherHistoryOversizePkts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of packets received during this - sampling interval that were longer than 1518 - octets (excluding framing bits but including - FCS octets) but were otherwise well formed." - ::= { etherHistoryEntry 11 } - - etherHistoryFragments OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The total number of packets received during this - sampling interval that were less than 64 octets in - length (excluding framing bits but including FCS - octets) had either a bad Frame Check Sequence (FCS) - with an integral number of octets (FCS Error) or a bad - FCS with a non-integral number of octets (Alignment - Error). - - Note that it is entirely normal for - etherHistoryFragments to increment. This is because - it counts both runts (which are normal occurrences - due to collisions) and noise hits." - ::= { etherHistoryEntry 12 } - - etherHistoryJabbers OBJECT-TYPE - - - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of packets received during this - sampling interval that were longer than 1518 octets - (excluding framing bits but including FCS octets), - and had either a bad Frame Check Sequence (FCS) - with an integral number of octets (FCS Error) or - a bad FCS with a non-integral number of octets - (Alignment Error). - - Note that this definition of jabber is different - than the definition in IEEE-802.3 section 8.2.1.5 - (10BASE5) and section 10.3.1.4 (10BASE2). These - documents define jabber as the condition where any - packet exceeds 20 ms. The allowed range to detect - jabber is between 20 ms and 150 ms." - ::= { etherHistoryEntry 13 } - - etherHistoryCollisions OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The best estimate of the total number of collisions - on this Ethernet segment during this sampling - interval. - - The value returned will depend on the location of - the RMON probe. Section 8.2.1.3 (10BASE-5) and - section 10.3.1.3 (10BASE-2) of IEEE standard 802.3 - states that a station must detect a collision, in - the receive mode, if three or more stations are - transmitting simultaneously. A repeater port must - detect a collision when two or more stations are - transmitting simultaneously. Thus a probe placed on - a repeater port could record more collisions than a - probe connected to a station on the same segment - would. - - Probe location plays a much smaller role when - considering 10BASE-T. 14.2.1.4 (10BASE-T) of IEEE - standard 802.3 defines a collision as the - simultaneous presence of signals on the DO and RD - circuits (transmitting and receiving at the same - time). A 10BASE-T station can only detect - collisions when it is transmitting. Thus probes - - - placed on a station and a repeater, should report - the same number of collisions. - - Note also that an RMON probe inside a repeater - should ideally report collisions between the - repeater and one or more other hosts (transmit - collisions as defined by IEEE 802.3k) plus receiver - collisions observed on any coax segments to which - the repeater is connected." - ::= { etherHistoryEntry 14 } - - etherHistoryUtilization OBJECT-TYPE - SYNTAX INTEGER (0..10000) - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The best estimate of the mean physical layer - network utilization on this interface during this - sampling interval, in hundredths of a percent." - ::= { etherHistoryEntry 15 } - - - -- The Alarm Group - - -- Implementation of the Alarm group is optional. - -- - -- The Alarm Group requires the implementation of the Event - -- group. - -- - -- The Alarm group periodically takes - -- statistical samples from variables in the probe and - -- compares them to thresholds that have been - -- configured. The alarm table stores configuration - -- entries that each define a variable, polling period, - -- and threshold parameters. If a sample is found to - -- cross the threshold values, an event is generated. - -- Only variables that resolve to an ASN.1 primitive - -- type of INTEGER (INTEGER, Counter, Gauge, or - -- TimeTicks) may be monitored in this way. - -- - -- This function has a hysteresis mechanism to limit - -- the generation of events. This mechanism generates - -- one event as a threshold is crossed in the - -- appropriate direction. No more events are generated - -- for that threshold until the opposite threshold is - -- crossed. - -- - -- In the case of a sampling a deltaValue, a probe may - - - -- implement this mechanism with more precision if it - -- takes a delta sample twice per period, each time - -- comparing the sum of the latest two samples to the - -- threshold. This allows the detection of threshold - -- crossings that span the sampling boundary. Note - -- that this does not require any special configuration - -- of the threshold value. It is suggested that probes - -- implement this more precise algorithm. - - alarmTable OBJECT-TYPE - SYNTAX SEQUENCE OF AlarmEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A list of alarm entries." - ::= { alarm 1 } - - alarmEntry OBJECT-TYPE - SYNTAX AlarmEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A list of parameters that set up a periodic checking - for alarm conditions. For example, an instance of the - alarmValue object might be named alarmValue.8" - INDEX { alarmIndex } - ::= { alarmTable 1 } - - AlarmEntry ::= SEQUENCE { - alarmIndex INTEGER (1..65535), - alarmInterval INTEGER, - alarmVariable OBJECT IDENTIFIER, - alarmSampleType INTEGER, - alarmValue INTEGER, - alarmStartupAlarm INTEGER, - alarmRisingThreshold INTEGER, - alarmFallingThreshold INTEGER, - alarmRisingEventIndex INTEGER (0..65535), - alarmFallingEventIndex INTEGER (0..65535), - alarmOwner OwnerString, - alarmStatus EntryStatus - } - - alarmIndex OBJECT-TYPE - SYNTAX INTEGER (1..65535) - ACCESS read-only - STATUS mandatory - DESCRIPTION - - - "An index that uniquely identifies an entry in the - alarm table. Each such entry defines a - diagnostic sample at a particular interval - for an object on the device." - ::= { alarmEntry 1 } - - alarmInterval OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The interval in seconds over which the data is - sampled and compared with the rising and falling - thresholds. When setting this variable, care - should be taken in the case of deltaValue - sampling - the interval should be set short enough - that the sampled variable is very unlikely to - increase or decrease by more than 2^31 - 1 during - a single sampling interval. - - This object may not be modified if the associated - alarmStatus object is equal to valid(1)." - ::= { alarmEntry 2 } - - alarmVariable OBJECT-TYPE - SYNTAX OBJECT IDENTIFIER - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The object identifier of the particular variable to - be sampled. Only variables that resolve to an ASN.1 - primitive type of INTEGER (INTEGER, Counter, Gauge, - or TimeTicks) may be sampled. - - Because SNMP access control is articulated entirely - in terms of the contents of MIB views, no access - control mechanism exists that can restrict the value - of this object to identify only those objects that - exist in a particular MIB view. Because there is - thus no acceptable means of restricting the read - access that could be obtained through the alarm - mechanism, the probe must only grant write access to - this object in those views that have read access to - all objects on the probe. - - During a set operation, if the supplied variable - name is not available in the selected MIB view, a - badValue error must be returned. If at any time the - - - variable name of an established alarmEntry is no - longer available in the selected MIB view, the probe - must change the status of this alarmEntry to - invalid(4). - - This object may not be modified if the associated - alarmStatus object is equal to valid(1)." - ::= { alarmEntry 3 } - - alarmSampleType OBJECT-TYPE - SYNTAX INTEGER { - absoluteValue(1), - deltaValue(2) - } - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The method of sampling the selected variable and - calculating the value to be compared against the - thresholds. If the value of this object is - absoluteValue(1), the value of the selected variable - will be compared directly with the thresholds at the - end of the sampling interval. If the value of this - object is deltaValue(2), the value of the selected - variable at the last sample will be subtracted from - the current value, and the difference compared with - the thresholds. - - This object may not be modified if the associated - alarmStatus object is equal to valid(1)." - ::= { alarmEntry 4 } - - alarmValue OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The value of the statistic during the last sampling - period. For example, if the sample type is - deltaValue, this value will be the difference - between the samples at the beginning and end of the - period. If the sample type is absoluteValue, this - value will be the sampled value at the end of the - period. - - This is the value that is compared with the rising and - falling thresholds. - - - - The value during the current sampling period is not - made available until the period is completed and will - remain available until the next period completes." - ::= { alarmEntry 5 } - - alarmStartupAlarm OBJECT-TYPE - SYNTAX INTEGER { - risingAlarm(1), - fallingAlarm(2), - risingOrFallingAlarm(3) - } - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The alarm that may be sent when this entry is first - set to valid. If the first sample after this entry - becomes valid is greater than or equal to the - risingThreshold and alarmStartupAlarm is equal to - risingAlarm(1) or risingOrFallingAlarm(3), then a - single rising alarm will be generated. If the first - sample after this entry becomes valid is less than - or equal to the fallingThreshold and - alarmStartupAlarm is equal to fallingAlarm(2) or - risingOrFallingAlarm(3), then a single falling alarm - will be generated. - - This object may not be modified if the associated - alarmStatus object is equal to valid(1)." - ::= { alarmEntry 6 } - - alarmRisingThreshold OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-write - STATUS mandatory - DESCRIPTION - "A threshold for the sampled statistic. When the - current sampled value is greater than or equal to - this threshold, and the value at the last sampling - interval was less than this threshold, a single - event will be generated. A single event will also - be generated if the first sample after this entry - becomes valid is greater than or equal to this - threshold and the associated alarmStartupAlarm is - equal to risingAlarm(1) or risingOrFallingAlarm(3). - - After a rising event is generated, another such event - will not be generated until the sampled value - falls below this threshold and reaches the - - - alarmFallingThreshold. - - This object may not be modified if the associated - alarmStatus object is equal to valid(1)." - ::= { alarmEntry 7 } - - alarmFallingThreshold OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-write - STATUS mandatory - DESCRIPTION - "A threshold for the sampled statistic. When the - current sampled value is less than or equal to this - threshold, and the value at the last sampling - interval was greater than this threshold, a single - event will be generated. A single event will also - be generated if the first sample after this entry - becomes valid is less than or equal to this - threshold and the associated alarmStartupAlarm is - equal to fallingAlarm(2) or risingOrFallingAlarm(3). - - After a falling event is generated, another such event - will not be generated until the sampled value - rises above this threshold and reaches the - alarmRisingThreshold. - - This object may not be modified if the associated - alarmStatus object is equal to valid(1)." - ::= { alarmEntry 8 } - - alarmRisingEventIndex OBJECT-TYPE - SYNTAX INTEGER (0..65535) - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The index of the eventEntry that is - used when a rising threshold is crossed. The - eventEntry identified by a particular value of - this index is the same as identified by the same value - of the eventIndex object. If there is no - corresponding entry in the eventTable, then - no association exists. In particular, if this value - is zero, no associated event will be generated, as - zero is not a valid event index. - - This object may not be modified if the associated - alarmStatus object is equal to valid(1)." - ::= { alarmEntry 9 } - - - alarmFallingEventIndex OBJECT-TYPE - SYNTAX INTEGER (0..65535) - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The index of the eventEntry that is - used when a falling threshold is crossed. The - eventEntry identified by a particular value of - this index is the same as identified by the same value - of the eventIndex object. If there is no - corresponding entry in the eventTable, then - no association exists. In particular, if this value - is zero, no associated event will be generated, as - zero is not a valid event index. - - This object may not be modified if the associated - alarmStatus object is equal to valid(1)." - ::= { alarmEntry 10 } - - alarmOwner OBJECT-TYPE - SYNTAX OwnerString - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The entity that configured this entry and is - therefore using the resources assigned to it." - ::= { alarmEntry 11 } - - alarmStatus OBJECT-TYPE - SYNTAX EntryStatus - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The status of this alarm entry." - ::= { alarmEntry 12 } - - - -- The Host Group - - -- Implementation of the Host group is optional. - -- - -- The host group discovers new hosts on the network by - -- keeping a list of source and destination MAC Addresses seen - -- in good packets. For each of these addresses, the host - -- group keeps a set of statistics. The hostControlTable - -- controls which interfaces this function is performed on, - -- and contains some information about the process. On - -- behalf of each hostControlEntry, data is collected on an - - - -- interface and placed in both the hostTable and the - -- hostTimeTable. If the monitoring device finds itself - -- short of resources, it may delete entries as needed. It - -- is suggested that the device delete the least recently - -- used entries first. - - -- The hostTable contains entries for each address - -- discovered on a particular interface. Each entry - -- contains statistical data about that host. This table is - -- indexed by the MAC address of the host, through which a - -- random access may be achieved. - - -- The hostTimeTable contains data in the same format as the - -- hostTable, and must contain the same set of hosts, but is - -- indexed using hostTimeCreationOrder rather than - -- hostAddress. - -- The hostTimeCreationOrder is an integer which reflects - -- the relative order in which a particular entry was - -- discovered and thus inserted into the table. As this - -- order, and thus the index, is among those entries - -- currently in the table, the index for a particular entry - -- may change if an (earlier) entry is deleted. Thus the - -- association between hostTimeCreationOrder and - -- hostTimeEntry may be broken at any time. - - -- The hostTimeTable has two important uses. The first is the - -- fast download of this potentially large table. Because the - -- index of this table runs from 1 to the size of the table, - -- inclusive, its values are predictable. This allows very - -- efficient packing of variables into SNMP PDU's and allows - -- a table transfer to have multiple packets outstanding. - -- These benefits increase transfer rates tremendously. - - -- The second use of the hostTimeTable is the efficient - -- discovery by the management station of new entries added - -- to the table. After the management station has downloaded - -- the entire table, it knows that new entries will be added - -- immediately after the end of the current table. It can - -- thus detect new entries there and retrieve them easily. - - -- Because the association between hostTimeCreationOrder and - -- hostTimeEntry may be broken at any time, the management - -- station must monitor the related hostControlLastDeleteTime - -- object. When the management station thus detects a - -- deletion, it must assume that any such associations have - --- been broken, and invalidate any it has stored locally. - -- This includes restarting any download of the - -- hostTimeTable that may have been in progress, as well as - - - -- rediscovering the end of the hostTimeTable so that it may - -- detect new entries. If the management station does not - -- detect the broken association, it may continue to refer - -- to a particular host by its creationOrder while - -- unwittingly retrieving the data associated with another - -- host entirely. If this happens while downloading the - -- host table, the management station may fail to download - -- all of the entries in the table. - - hostControlTable OBJECT-TYPE - SYNTAX SEQUENCE OF HostControlEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A list of host table control entries." - ::= { hosts 1 } - - hostControlEntry OBJECT-TYPE - SYNTAX HostControlEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A list of parameters that set up the discovery of - hosts on a particular interface and the collection - of statistics about these hosts. For example, an - instance of the hostControlTableSize object might be - named hostControlTableSize.1" - INDEX { hostControlIndex } - ::= { hostControlTable 1 } - - HostControlEntry ::= SEQUENCE { - hostControlIndex INTEGER (1..65535), - hostControlDataSource OBJECT IDENTIFIER, - hostControlTableSize INTEGER, - hostControlLastDeleteTime TimeTicks, - hostControlOwner OwnerString, - hostControlStatus EntryStatus - } - - hostControlIndex OBJECT-TYPE - SYNTAX INTEGER (1..65535) - ACCESS read-only - STATUS mandatory - DESCRIPTION - "An index that uniquely identifies an entry in the - hostControl table. Each such entry defines - a function that discovers hosts on a particular - interface and places statistics about them in the - - - hostTable and the hostTimeTable on behalf of this - hostControlEntry." - ::= { hostControlEntry 1 } - - hostControlDataSource OBJECT-TYPE - SYNTAX OBJECT IDENTIFIER - ACCESS read-write - STATUS mandatory - DESCRIPTION - "This object identifies the source of the data for - this instance of the host function. This source - can be any interface on this device. In order - to identify a particular interface, this object shall - identify the instance of the ifIndex object, defined - in RFC 1213 and RFC 1573 [4,6], for the desired - interface. For example, if an entry were to receive - data from interface #1, this object would be set to - ifIndex.1. - - The statistics in this group reflect all packets - on the local network segment attached to the - identified interface. - - An agent may or may not be able to tell if - fundamental changes to the media of the interface - have occurred and necessitate an invalidation of - this entry. For example, a hot-pluggable ethernet - card could be pulled out and replaced by a - token-ring card. In such a case, if the agent has - such knowledge of the change, it is recommended that - it invalidate this entry. - - This object may not be modified if the associated - hostControlStatus object is equal to valid(1)." - ::= { hostControlEntry 2 } - - hostControlTableSize OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of hostEntries in the hostTable and the - hostTimeTable associated with this hostControlEntry." - ::= { hostControlEntry 3 } - - hostControlLastDeleteTime OBJECT-TYPE - SYNTAX TimeTicks - ACCESS read-only - - - STATUS mandatory - DESCRIPTION - "The value of sysUpTime when the last entry - was deleted from the portion of the hostTable - associated with this hostControlEntry. If no - deletions have occurred, this value shall be zero." - ::= { hostControlEntry 4 } - - hostControlOwner OBJECT-TYPE - SYNTAX OwnerString - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The entity that configured this entry and is - therefore using the resources assigned to it." - ::= { hostControlEntry 5 } - - hostControlStatus OBJECT-TYPE - SYNTAX EntryStatus - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The status of this hostControl entry. - - If this object is not equal to valid(1), all - associated entries in the hostTable, hostTimeTable, - and the hostTopNTable shall be deleted by the - agent." - ::= { hostControlEntry 6 } - - hostTable OBJECT-TYPE - SYNTAX SEQUENCE OF HostEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A list of host entries." - ::= { hosts 2 } - - hostEntry OBJECT-TYPE - SYNTAX HostEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A collection of statistics for a particular host - that has been discovered on an interface of this - device. For example, an instance of the - hostOutBroadcastPkts object might be named - hostOutBroadcastPkts.1.6.8.0.32.27.3.176" - - - INDEX { hostIndex, hostAddress } - ::= { hostTable 1 } - - HostEntry ::= SEQUENCE { - hostAddress OCTET STRING, - hostCreationOrder INTEGER (1..65535), - hostIndex INTEGER (1..65535), - hostInPkts Counter, - hostOutPkts Counter, - hostInOctets Counter, - hostOutOctets Counter, - hostOutErrors Counter, - hostOutBroadcastPkts Counter, - hostOutMulticastPkts Counter - } - - hostAddress OBJECT-TYPE - SYNTAX OCTET STRING - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The physical address of this host." - ::= { hostEntry 1 } - - hostCreationOrder OBJECT-TYPE - SYNTAX INTEGER (1..65535) - ACCESS read-only - STATUS mandatory - DESCRIPTION - "An index that defines the relative ordering of - the creation time of hosts captured for a - particular hostControlEntry. This index shall - be between 1 and N, where N is the value of - the associated hostControlTableSize. The ordering - of the indexes is based on the order of each entry's - insertion into the table, in which entries added - earlier have a lower index value than entries added - later. - - It is important to note that the order for a - particular entry may change as an (earlier) entry - is deleted from the table. Because this order may - change, management stations should make use of the - hostControlLastDeleteTime variable in the - hostControlEntry associated with the relevant - portion of the hostTable. By observing - this variable, the management station may detect - the circumstances where a previous association - - - between a value of hostCreationOrder - and a hostEntry may no longer hold." - ::= { hostEntry 2 } - - hostIndex OBJECT-TYPE - SYNTAX INTEGER (1..65535) - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The set of collected host statistics of which - this entry is a part. The set of hosts - identified by a particular value of this - index is associated with the hostControlEntry - as identified by the same value of hostControlIndex." - ::= { hostEntry 3 } - - hostInPkts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of good packets transmitted to this - address since it was added to the hostTable." - ::= { hostEntry 4 } - - hostOutPkts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of packets, including bad packets, - transmitted by this address since it was added - to the hostTable." - ::= { hostEntry 5 } - - hostInOctets OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of octets transmitted to this address - since it was added to the hostTable (excluding - framing bits but including FCS octets), except for - those octets in bad packets." - ::= { hostEntry 6 } - - hostOutOctets OBJECT-TYPE - SYNTAX Counter - - - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of octets transmitted by this address - since it was added to the hostTable (excluding - framing bits but including FCS octets), including - those octets in bad packets." - ::= { hostEntry 7 } - - hostOutErrors OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of bad packets transmitted by this address - since this host was added to the hostTable." - ::= { hostEntry 8 } - - hostOutBroadcastPkts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of good packets transmitted by this - address that were directed to the broadcast address - since this host was added to the hostTable." - ::= { hostEntry 9 } - - hostOutMulticastPkts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of good packets transmitted by this - address that were directed to a multicast address - since this host was added to the hostTable. - Note that this number does not include packets - directed to the broadcast address." - ::= { hostEntry 10 } - - -- host Time Table - - hostTimeTable OBJECT-TYPE - SYNTAX SEQUENCE OF HostTimeEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A list of time-ordered host table entries." - - - ::= { hosts 3 } - - hostTimeEntry OBJECT-TYPE - SYNTAX HostTimeEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A collection of statistics for a particular host - that has been discovered on an interface of this - device. This collection includes the relative - ordering of the creation time of this object. For - example, an instance of the hostTimeOutBroadcastPkts - object might be named - hostTimeOutBroadcastPkts.1.687" - INDEX { hostTimeIndex, hostTimeCreationOrder } - ::= { hostTimeTable 1 } - - HostTimeEntry ::= SEQUENCE { - hostTimeAddress OCTET STRING, - hostTimeCreationOrder INTEGER (1..65535), - hostTimeIndex INTEGER (1..65535), - hostTimeInPkts Counter, - hostTimeOutPkts Counter, - hostTimeInOctets Counter, - hostTimeOutOctets Counter, - hostTimeOutErrors Counter, - hostTimeOutBroadcastPkts Counter, - hostTimeOutMulticastPkts Counter - } - - hostTimeAddress OBJECT-TYPE - SYNTAX OCTET STRING - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The physical address of this host." - ::= { hostTimeEntry 1 } - - hostTimeCreationOrder OBJECT-TYPE - SYNTAX INTEGER (1..65535) - ACCESS read-only - STATUS mandatory - DESCRIPTION - "An index that uniquely identifies an entry in - the hostTime table among those entries associated - with the same hostControlEntry. This index shall - be between 1 and N, where N is the value of - the associated hostControlTableSize. The ordering - - - of the indexes is based on the order of each entry's - insertion into the table, in which entries added - earlier have a lower index value than entries added - later. Thus the management station has the ability to - learn of new entries added to this table without - downloading the entire table. - - It is important to note that the index for a - particular entry may change as an (earlier) entry - is deleted from the table. Because this order may - change, management stations should make use of the - hostControlLastDeleteTime variable in the - hostControlEntry associated with the relevant - portion of the hostTimeTable. By observing - this variable, the management station may detect - the circumstances where a download of the table - may have missed entries, and where a previous - association between a value of hostTimeCreationOrder - and a hostTimeEntry may no longer hold." - ::= { hostTimeEntry 2 } - - hostTimeIndex OBJECT-TYPE - SYNTAX INTEGER (1..65535) - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The set of collected host statistics of which - this entry is a part. The set of hosts - identified by a particular value of this - index is associated with the hostControlEntry - as identified by the same value of hostControlIndex." - ::= { hostTimeEntry 3 } - - hostTimeInPkts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of good packets transmitted to this - address since it was added to the hostTimeTable." - ::= { hostTimeEntry 4 } - - hostTimeOutPkts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of god packets transmitted by this - - - address since it was added to the hostTimeTable." - ::= { hostTimeEntry 5 } - - hostTimeInOctets OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of octets transmitted to this address - since it was added to the hostTimeTable (excluding - framing bits but including FCS octets), except for - those octets in bad packets." - ::= { hostTimeEntry 6 } - - hostTimeOutOctets OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of octets transmitted by this address - since it was added to the hostTimeTable (excluding - framing bits but including FCS octets), including - those octets in bad packets." - ::= { hostTimeEntry 7 } - - hostTimeOutErrors OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of bad packets transmitted by this address - since this host was added to the hostTimeTable." - ::= { hostTimeEntry 8 } - - hostTimeOutBroadcastPkts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of good packets transmitted by this - address that were directed to the broadcast address - since this host was added to the hostTimeTable." - ::= { hostTimeEntry 9 } - - hostTimeOutMulticastPkts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - - - DESCRIPTION - "The number of good packets transmitted by this - address that were directed to a multicast address - since this host was added to the hostTimeTable. - Note that this number does not include packets - directed to the broadcast address." - ::= { hostTimeEntry 10 } - - - -- The Host Top "N" Group - - -- Implementation of the Host Top N group is optional. - -- - -- The Host Top N group requires the implementation of the - -- host group. - -- - -- The Host Top N group is used to prepare reports that - -- describe the hosts that top a list ordered by one of - -- their statistics. - -- The available statistics are samples of one of their - -- base statistics, over an interval specified by the - -- management station. Thus, these statistics are rate - -- based. The management station also selects how many such - -- hosts are reported. - - -- The hostTopNControlTable is used to initiate the - -- generation of such a report. The management station - -- may select the parameters of such a report, such as - -- which interface, which statistic, how many hosts, - -- and the start and stop times of the sampling. When - -- the report is prepared, entries are created in the - -- hostTopNTable associated with the relevant - -- hostTopNControlEntry. These entries are static for - -- each report after it has been prepared. - - hostTopNControlTable OBJECT-TYPE - SYNTAX SEQUENCE OF HostTopNControlEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A list of top N host control entries." - ::= { hostTopN 1 } - - hostTopNControlEntry OBJECT-TYPE - SYNTAX HostTopNControlEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - - - "A set of parameters that control the creation of a - report of the top N hosts according to several - metrics. For example, an instance of the - hostTopNDuration object might be named - hostTopNDuration.3" - INDEX { hostTopNControlIndex } - ::= { hostTopNControlTable 1 } - - HostTopNControlEntry ::= SEQUENCE { - hostTopNControlIndex INTEGER (1..65535), - hostTopNHostIndex INTEGER (1..65535), - hostTopNRateBase INTEGER, - hostTopNTimeRemaining INTEGER, - hostTopNDuration INTEGER, - hostTopNRequestedSize INTEGER, - hostTopNGrantedSize INTEGER, - hostTopNStartTime TimeTicks, - hostTopNOwner OwnerString, - hostTopNStatus EntryStatus - } - - hostTopNControlIndex OBJECT-TYPE - SYNTAX INTEGER (1..65535) - ACCESS read-only - STATUS mandatory - DESCRIPTION - "An index that uniquely identifies an entry - in the hostTopNControl table. Each such - entry defines one top N report prepared for - one interface." - ::= { hostTopNControlEntry 1 } - - hostTopNHostIndex OBJECT-TYPE - SYNTAX INTEGER (1..65535) - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The host table for which a top N report will be - prepared on behalf of this entry. The host table - identified by a particular value of this index is - associated with the same host table as identified by - the same value of hostIndex. - - This object may not be modified if the associated - hostTopNStatus object is equal to valid(1)." - ::= { hostTopNControlEntry 2 } - - hostTopNRateBase OBJECT-TYPE - - - SYNTAX INTEGER { - hostTopNInPkts(1), - hostTopNOutPkts(2), - hostTopNInOctets(3), - hostTopNOutOctets(4), - hostTopNOutErrors(5), - hostTopNOutBroadcastPkts(6), - hostTopNOutMulticastPkts(7) - } - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The variable for each host that the hostTopNRate - variable is based upon. - - This object may not be modified if the associated - hostTopNStatus object is equal to valid(1)." - ::= { hostTopNControlEntry 3 } - - hostTopNTimeRemaining OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The number of seconds left in the report currently - being collected. When this object is modified by - the management station, a new collection is started, - possibly aborting a currently running report. The - new value is used as the requested duration of this - report, which is loaded into the associated - hostTopNDuration object. - - When this object is set to a non-zero value, any - associated hostTopNEntries shall be made - inaccessible by the monitor. While the value of - this object is non-zero, it decrements by one per - second until it reaches zero. During this time, all - associated hostTopNEntries shall remain - inaccessible. At the time that this object - decrements to zero, the report is made accessible in - the hostTopNTable. Thus, the hostTopN table needs - to be created only at the end of the collection - interval." - DEFVAL { 0 } - ::= { hostTopNControlEntry 4 } - - hostTopNDuration OBJECT-TYPE - SYNTAX INTEGER - - - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of seconds that this report has collected - during the last sampling interval, or if this - report is currently being collected, the number - of seconds that this report is being collected - during this sampling interval. - - When the associated hostTopNTimeRemaining object is - set, this object shall be set by the probe to the - same value and shall not be modified until the next - time the hostTopNTimeRemaining is set. - - This value shall be zero if no reports have been - requested for this hostTopNControlEntry." - DEFVAL { 0 } - ::= { hostTopNControlEntry 5 } - - hostTopNRequestedSize OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The maximum number of hosts requested for the top N - table. - - When this object is created or modified, the probe - should set hostTopNGrantedSize as closely to this - object as is possible for the particular probe - implementation and available resources." - DEFVAL { 10 } - ::= { hostTopNControlEntry 6 } - - hostTopNGrantedSize OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The maximum number of hosts in the top N table. - - When the associated hostTopNRequestedSize object is - created or modified, the probe should set this - object as closely to the requested value as is - possible for the particular implementation and - available resources. The probe must not lower this - value except as a result of a set to the associated - hostTopNRequestedSize object. - - - Hosts with the highest value of hostTopNRate shall be - placed in this table in decreasing order of this rate - until there is no more room or until there are no more - hosts." - ::= { hostTopNControlEntry 7 } - - hostTopNStartTime OBJECT-TYPE - SYNTAX TimeTicks - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The value of sysUpTime when this top N report was - last started. In other words, this is the time that - the associated hostTopNTimeRemaining object was - modified to start the requested report." - ::= { hostTopNControlEntry 8 } - - hostTopNOwner OBJECT-TYPE - SYNTAX OwnerString - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The entity that configured this entry and is - therefore using the resources assigned to it." - ::= { hostTopNControlEntry 9 } - - hostTopNStatus OBJECT-TYPE - SYNTAX EntryStatus - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The status of this hostTopNControl entry. - - If this object is not equal to valid(1), all - associated hostTopNEntries shall be deleted by the - agent." - ::= { hostTopNControlEntry 10 } - - hostTopNTable OBJECT-TYPE - SYNTAX SEQUENCE OF HostTopNEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A list of top N host entries." - ::= { hostTopN 2 } - - hostTopNEntry OBJECT-TYPE - SYNTAX HostTopNEntry - - - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A set of statistics for a host that is part of a - top N report. For example, an instance of the - hostTopNRate object might be named - hostTopNRate.3.10" - INDEX { hostTopNReport, hostTopNIndex } - ::= { hostTopNTable 1 } - - HostTopNEntry ::= SEQUENCE { - hostTopNReport INTEGER (1..65535), - hostTopNIndex INTEGER (1..65535), - hostTopNAddress OCTET STRING, - hostTopNRate INTEGER - } - - hostTopNReport OBJECT-TYPE - SYNTAX INTEGER (1..65535) - ACCESS read-only - STATUS mandatory - DESCRIPTION - "This object identifies the top N report of which - this entry is a part. The set of hosts - identified by a particular value of this - object is part of the same report as identified - by the same value of the hostTopNControlIndex object." - ::= { hostTopNEntry 1 } - - hostTopNIndex OBJECT-TYPE - SYNTAX INTEGER (1..65535) - ACCESS read-only - STATUS mandatory - DESCRIPTION - "An index that uniquely identifies an entry in - the hostTopN table among those in the same report. - This index is between 1 and N, where N is the - number of entries in this table. Increasing values - of hostTopNIndex shall be assigned to entries with - decreasing values of hostTopNRate until index N - is assigned to the entry with the lowest value of - hostTopNRate or there are no more hostTopNEntries." - ::= { hostTopNEntry 2 } - - hostTopNAddress OBJECT-TYPE - SYNTAX OCTET STRING - ACCESS read-only - STATUS mandatory - - - DESCRIPTION - "The physical address of this host." - ::= { hostTopNEntry 3 } - - hostTopNRate OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The amount of change in the selected variable - during this sampling interval. The selected - variable is this host's instance of the object - selected by hostTopNRateBase." - ::= { hostTopNEntry 4 } - - - -- The Matrix Group - - -- Implementation of the Matrix group is optional. - -- - -- The Matrix group consists of the matrixControlTable, - -- matrixSDTable and the matrixDSTable. These tables - -- store statistics for a particular conversation - -- between two addresses. As the device detects a new - -- conversation, including those to a non-unicast - -- address, it creates a new entry in both of the - -- matrix tables. It must only create new entries - -- based on information received in good packets. If - -- the monitoring device finds itself short of - -- resources, it may delete entries as needed. It is - -- suggested that the device delete the least recently - -- used entries first. - - matrixControlTable OBJECT-TYPE - SYNTAX SEQUENCE OF MatrixControlEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A list of information entries for the - traffic matrix on each interface." - ::= { matrix 1 } - - matrixControlEntry OBJECT-TYPE - SYNTAX MatrixControlEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "Information about a traffic matrix on a particular - - - interface. For example, an instance of the - matrixControlLastDeleteTime object might be named - matrixControlLastDeleteTime.1" - INDEX { matrixControlIndex } - ::= { matrixControlTable 1 } - - MatrixControlEntry ::= SEQUENCE { - matrixControlIndex INTEGER (1..65535), - matrixControlDataSource OBJECT IDENTIFIER, - matrixControlTableSize INTEGER, - matrixControlLastDeleteTime TimeTicks, - matrixControlOwner OwnerString, - matrixControlStatus EntryStatus - } - - matrixControlIndex OBJECT-TYPE - SYNTAX INTEGER (1..65535) - ACCESS read-only - STATUS mandatory - DESCRIPTION - "An index that uniquely identifies an entry in the - matrixControl table. Each such entry defines - a function that discovers conversations on a - particular interface and places statistics about - them in the matrixSDTable and the matrixDSTable on - behalf of this matrixControlEntry." - ::= { matrixControlEntry 1 } - - matrixControlDataSource OBJECT-TYPE - SYNTAX OBJECT IDENTIFIER - ACCESS read-write - STATUS mandatory - DESCRIPTION - "This object identifies the source of - the data from which this entry creates a traffic - matrix. This source can be any interface on this - device. In order to identify a particular - interface, this object shall identify the instance - of the ifIndex object, defined in RFC 1213 and RFC - 1573 [4,6], for the desired interface. For example, - if an entry were to receive data from interface #1, - this object would be set to ifIndex.1. - - The statistics in this group reflect all packets - on the local network segment attached to the - identified interface. - - An agent may or may not be able to tell if - - - fundamental changes to the media of the interface - have occurred and necessitate an invalidation of - this entry. For example, a hot-pluggable ethernet - card could be pulled out and replaced by a - token-ring card. In such a case, if the agent has - such knowledge of the change, it is recommended that - it invalidate this entry. - - This object may not be modified if the associated - matrixControlStatus object is equal to valid(1)." - ::= { matrixControlEntry 2 } - - matrixControlTableSize OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of matrixSDEntries in the matrixSDTable - for this interface. This must also be the value of - the number of entries in the matrixDSTable for this - interface." - ::= { matrixControlEntry 3 } - - matrixControlLastDeleteTime OBJECT-TYPE - SYNTAX TimeTicks - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The value of sysUpTime when the last entry - was deleted from the portion of the matrixSDTable - or matrixDSTable associated with this - matrixControlEntry. If no deletions have occurred, - this value shall be zero." - ::= { matrixControlEntry 4 } - - matrixControlOwner OBJECT-TYPE - SYNTAX OwnerString - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The entity that configured this entry and is - therefore using the resources assigned to it." - ::= { matrixControlEntry 5 } - - matrixControlStatus OBJECT-TYPE - SYNTAX EntryStatus - ACCESS read-write - STATUS mandatory - - - DESCRIPTION - "The status of this matrixControl entry. - - If this object is not equal to valid(1), all - associated entries in the matrixSDTable and the - matrixDSTable shall be deleted by the agent." - ::= { matrixControlEntry 6 } - - matrixSDTable OBJECT-TYPE - SYNTAX SEQUENCE OF MatrixSDEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A list of traffic matrix entries indexed by - source and destination MAC address." - ::= { matrix 2 } - - matrixSDEntry OBJECT-TYPE - SYNTAX MatrixSDEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A collection of statistics for communications between - two addresses on a particular interface. For example, - an instance of the matrixSDPkts object might be named - matrixSDPkts.1.6.8.0.32.27.3.176.6.8.0.32.10.8.113" - INDEX { matrixSDIndex, - matrixSDSourceAddress, matrixSDDestAddress } - ::= { matrixSDTable 1 } - - MatrixSDEntry ::= SEQUENCE { - matrixSDSourceAddress OCTET STRING, - matrixSDDestAddress OCTET STRING, - matrixSDIndex INTEGER (1..65535), - matrixSDPkts Counter, - matrixSDOctets Counter, - matrixSDErrors Counter - } - - matrixSDSourceAddress OBJECT-TYPE - SYNTAX OCTET STRING - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The source physical address." - ::= { matrixSDEntry 1 } - - matrixSDDestAddress OBJECT-TYPE - - - SYNTAX OCTET STRING - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The destination physical address." - ::= { matrixSDEntry 2 } - - matrixSDIndex OBJECT-TYPE - SYNTAX INTEGER (1..65535) - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The set of collected matrix statistics of which - this entry is a part. The set of matrix statistics - identified by a particular value of this index - is associated with the same matrixControlEntry - as identified by the same value of - matrixControlIndex." - ::= { matrixSDEntry 3 } - - matrixSDPkts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of packets transmitted from the source - address to the destination address (this number - includes bad packets)." - ::= { matrixSDEntry 4 } - - matrixSDOctets OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of octets (excluding framing bits but - including FCS octets) contained in all packets - transmitted from the source address to the - destination address." - ::= { matrixSDEntry 5 } - - matrixSDErrors OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of bad packets transmitted from - the source address to the destination address." - - - ::= { matrixSDEntry 6 } - - - -- Traffic matrix tables from destination to source - - matrixDSTable OBJECT-TYPE - SYNTAX SEQUENCE OF MatrixDSEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A list of traffic matrix entries indexed by - destination and source MAC address." - ::= { matrix 3 } - - matrixDSEntry OBJECT-TYPE - SYNTAX MatrixDSEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A collection of statistics for communications between - two addresses on a particular interface. For example, - an instance of the matrixSDPkts object might be named - matrixSDPkts.1.6.8.0.32.10.8.113.6.8.0.32.27.3.176" - INDEX { matrixDSIndex, - matrixDSDestAddress, matrixDSSourceAddress } - ::= { matrixDSTable 1 } - - MatrixDSEntry ::= SEQUENCE { - matrixDSSourceAddress OCTET STRING, - matrixDSDestAddress OCTET STRING, - matrixDSIndex INTEGER (1..65535), - matrixDSPkts Counter, - matrixDSOctets Counter, - matrixDSErrors Counter - } - - matrixDSSourceAddress OBJECT-TYPE - SYNTAX OCTET STRING - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The source physical address." - ::= { matrixDSEntry 1 } - - matrixDSDestAddress OBJECT-TYPE - SYNTAX OCTET STRING - ACCESS read-only - STATUS mandatory - - - DESCRIPTION - "The destination physical address." - ::= { matrixDSEntry 2 } - - matrixDSIndex OBJECT-TYPE - SYNTAX INTEGER (1..65535) - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The set of collected matrix statistics of which - this entry is a part. The set of matrix statistics - identified by a particular value of this index - is associated with the same matrixControlEntry - as identified by the same value of - matrixControlIndex." - ::= { matrixDSEntry 3 } - - matrixDSPkts OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of packets transmitted from the source - address to the destination address (this number - includes bad packets)." - ::= { matrixDSEntry 4 } - - matrixDSOctets OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of octets (excluding framing bits - but including FCS octets) contained in all packets - transmitted from the source address to the - destination address." - ::= { matrixDSEntry 5 } - - matrixDSErrors OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of bad packets transmitted from - the source address to the destination address." - ::= { matrixDSEntry 6 } - - - - - -- The Filter Group - - -- Implementation of the Filter group is optional. - -- - -- The Filter group allows packets to be captured with an - -- arbitrary filter expression. A logical data and - -- event stream or "channel" is formed by the packets - -- that match the filter expression. - -- - -- This filter mechanism allows the creation of an arbitrary - -- logical expression with which to filter packets. Each - -- filter associated with a channel is OR'ed with the others. - -- Within a filter, any bits checked in the data and status - -- are AND'ed with respect to other bits in the same filter. - -- The NotMask also allows for checking for inequality. - -- Finally, the channelAcceptType object allows for - -- inversion of the whole equation. - -- - -- If a management station wishes to receive a trap to alert - -- it that new packets have been captured and are available - -- for download, it is recommended that it set up an alarm - -- entry that monitors the value of the relevant - -- channelMatches instance. - -- - -- The channel can be turned on or off, and can also - -- generate events when packets pass through it. - - filterTable OBJECT-TYPE - SYNTAX SEQUENCE OF FilterEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A list of packet filter entries." - ::= { filter 1 } - - filterEntry OBJECT-TYPE - SYNTAX FilterEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A set of parameters for a packet filter applied on a - particular interface. As an example, an instance of - the filterPktData object might be named - filterPktData.12" - INDEX { filterIndex } - ::= { filterTable 1 } - - - - - FilterEntry ::= SEQUENCE { - filterIndex INTEGER (1..65535), - filterChannelIndex INTEGER (1..65535), - filterPktDataOffset INTEGER, - filterPktData OCTET STRING, - filterPktDataMask OCTET STRING, - filterPktDataNotMask OCTET STRING, - filterPktStatus INTEGER, - filterPktStatusMask INTEGER, - filterPktStatusNotMask INTEGER, - filterOwner OwnerString, - filterStatus EntryStatus - } - - filterIndex OBJECT-TYPE - SYNTAX INTEGER (1..65535) - ACCESS read-only - STATUS mandatory - DESCRIPTION - "An index that uniquely identifies an entry - in the filter table. Each such entry defines - one filter that is to be applied to every packet - received on an interface." - ::= { filterEntry 1 } - - filterChannelIndex OBJECT-TYPE - SYNTAX INTEGER (1..65535) - ACCESS read-write - STATUS mandatory - DESCRIPTION - "This object identifies the channel of which this - filter is a part. The filters identified by a - particular value of this object are associated with - the same channel as identified by the same value of - the channelIndex object." - ::= { filterEntry 2 } - - filterPktDataOffset OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The offset from the beginning of each packet where - a match of packet data will be attempted. This offset - is measured from the point in the physical layer - packet after the framing bits, if any. For example, - in an Ethernet frame, this point is at the beginning - of the destination MAC address. - - - This object may not be modified if the associated - filterStatus object is equal to valid(1)." - DEFVAL { 0 } - ::= { filterEntry 3 } - - filterPktData OBJECT-TYPE - SYNTAX OCTET STRING - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The data that is to be matched with the input - packet. For each packet received, this filter and - the accompanying filterPktDataMask and - filterPktDataNotMask will be adjusted for the - offset. The only bits relevant to this match - algorithm are those that have the corresponding - filterPktDataMask bit equal to one. The following - three rules are then applied to every packet: - - (1) If the packet is too short and does not have data - corresponding to part of the filterPktData, the - packet will fail this data match. - - (2) For each relevant bit from the packet with the - corresponding filterPktDataNotMask bit set to - zero, if the bit from the packet is not equal to - the corresponding bit from the filterPktData, - then the packet will fail this data match. - - (3) If for every relevant bit from the packet with the - corresponding filterPktDataNotMask bit set to one, - the bit from the packet is equal to the - corresponding bit from the filterPktData, then - the packet will fail this data match. - - Any packets that have not failed any of the three - matches above have passed this data match. In - particular, a zero length filter will match any - packet. - - This object may not be modified if the associated - filterStatus object is equal to valid(1)." - ::= { filterEntry 4 } - - filterPktDataMask OBJECT-TYPE - SYNTAX OCTET STRING - ACCESS read-write - STATUS mandatory - - - DESCRIPTION - "The mask that is applied to the match process. - After adjusting this mask for the offset, only those - bits in the received packet that correspond to bits - set in this mask are relevant for further processing - by the match algorithm. The offset is applied to - filterPktDataMask in the same way it is applied to the - filter. For the purposes of the matching algorithm, - if the associated filterPktData object is longer - than this mask, this mask is conceptually extended - with '1' bits until it reaches the length of the - filterPktData object. - - This object may not be modified if the associated - filterStatus object is equal to valid(1)." - ::= { filterEntry 5 } - - filterPktDataNotMask OBJECT-TYPE - SYNTAX OCTET STRING - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The inversion mask that is applied to the match - process. After adjusting this mask for the offset, - those relevant bits in the received packet that - correspond to bits cleared in this mask must all be - equal to their corresponding bits in the - filterPktData object for the packet to be accepted. - In addition, at least one of those relevant bits in - the received packet that correspond to bits set in - this mask must be different to its corresponding bit - in the filterPktData object. - - For the purposes of the matching algorithm, if the - associated filterPktData object is longer than this - mask, this mask is conceptually extended with '0' - bits until it reaches the length of the - filterPktData object. - - This object may not be modified if the associated - filterStatus object is equal to valid(1)." - ::= { filterEntry 6 } - - filterPktStatus OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-write - STATUS mandatory - DESCRIPTION - - - "The status that is to be matched with the input - packet. The only bits relevant to this match - algorithm are those that have the corresponding - filterPktStatusMask bit equal to one. The following - two rules are then applied to every packet: - - (1) For each relevant bit from the packet status - with the corresponding filterPktStatusNotMask bit - set to zero, if the bit from the packet status is - not equal to the corresponding bit from the - filterPktStatus, then the packet will fail this - status match. - - (2) If for every relevant bit from the packet status - with the corresponding filterPktStatusNotMask bit - set to one, the bit from the packet status is - equal to the corresponding bit from the - filterPktStatus, then the packet will fail this - status match. - - Any packets that have not failed either of the two - matches above have passed this status match. In - particular, a zero length status filter will match any - packet's status. - - The value of the packet status is a sum. This sum - initially takes the value zero. Then, for each - error, E, that has been discovered in this packet, - 2 raised to a value representing E is added to the - sum. The errors and the bits that represent them are - dependent on the media type of the interface that - this channel is receiving packets from. - - The errors defined for a packet captured off of an - Ethernet interface are as follows: - - bit # Error - 0 Packet is longer than 1518 octets - 1 Packet is shorter than 64 octets - 2 Packet experienced a CRC or Alignment - error - - For example, an Ethernet fragment would have a - value of 6 (2^1 + 2^2). - - As this MIB is expanded to new media types, this - object will have other media-specific errors - defined. - - - For the purposes of this status matching algorithm, - if the packet status is longer than this - filterPktStatus object, this object is conceptually - extended with '0' bits until it reaches the size of - the packet status. - - This object may not be modified if the associated - filterStatus object is equal to valid(1)." - ::= { filterEntry 7 } - - filterPktStatusMask OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The mask that is applied to the status match - process. Only those bits in the received packet - that correspond to bits set in this mask are - relevant for further processing by the status match - algorithm. For the purposes of the matching - algorithm, if the associated filterPktStatus object - is longer than this mask, this mask is conceptually - extended with '1' bits until it reaches the size of - the filterPktStatus. In addition, if a packet - status is longer than this mask, this mask is - conceptually extended with '0' bits until it reaches - the size of the packet status. - - This object may not be modified if the associated - filterStatus object is equal to valid(1)." - ::= { filterEntry 8 } - - filterPktStatusNotMask OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The inversion mask that is applied to the status - match process. Those relevant bits in the received - packet status that correspond to bits cleared in - this mask must all be equal to their corresponding - bits in the filterPktStatus object for the packet to - be accepted. In addition, at least one of those - relevant bits in the received packet status that - correspond to bits set in this mask must be - different to its corresponding bit in the - filterPktStatus object for the packet to be - accepted. - - - For the purposes of the matching algorithm, if the - associated filterPktStatus object or a packet status - is longer than this mask, this mask is conceptually - extended with '0' bits until it reaches the longer - of the lengths of the filterPktStatus object and the - packet status. - - This object may not be modified if the associated - filterStatus object is equal to valid(1)." - ::= { filterEntry 9 } - - filterOwner OBJECT-TYPE - SYNTAX OwnerString - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The entity that configured this entry and is - therefore using the resources assigned to it." - ::= { filterEntry 10 } - - filterStatus OBJECT-TYPE - SYNTAX EntryStatus - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The status of this filter entry." - ::= { filterEntry 11 } - - channelTable OBJECT-TYPE - SYNTAX SEQUENCE OF ChannelEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A list of packet channel entries." - ::= { filter 2 } - - channelEntry OBJECT-TYPE - SYNTAX ChannelEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A set of parameters for a packet channel applied on a - particular interface. As an example, an instance of - the channelMatches object might be named - channelMatches.3" - INDEX { channelIndex } - ::= { channelTable 1 } - - - - ChannelEntry ::= SEQUENCE { - channelIndex INTEGER (1..65535), - channelIfIndex INTEGER (1..65535), - channelAcceptType INTEGER, - channelDataControl INTEGER, - channelTurnOnEventIndex INTEGER (0..65535), - channelTurnOffEventIndex INTEGER (0..65535), - channelEventIndex INTEGER (0..65535), - channelEventStatus INTEGER, - channelMatches Counter, - channelDescription DisplayString (SIZE (0..127)), - channelOwner OwnerString, - channelStatus EntryStatus - } - - channelIndex OBJECT-TYPE - SYNTAX INTEGER (1..65535) - ACCESS read-only - STATUS mandatory - DESCRIPTION - "An index that uniquely identifies an entry in the - channel table. Each such entry defines one channel, - a logical data and event stream. - - It is suggested that before creating a channel, an - application should scan all instances of the - filterChannelIndex object to make sure that there - are no pre-existing filters that would be - inadvertently be linked to the channel." - ::= { channelEntry 1 } - - channelIfIndex OBJECT-TYPE - SYNTAX INTEGER (1..65535) - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The value of this object uniquely identifies the - interface on this remote network monitoring device - to which the associated filters are applied to allow - data into this channel. The interface identified by - a particular value of this object is the same - interface as identified by the same value of the - ifIndex object, defined in RFC 1213 and RFC 1573 - [4,6]. - - The filters in this group are applied to all packets - on the local network segment attached to the - identified interface. - - - An agent may or may not be able to tell if - fundamental changes to the media of the interface - have occurred and necessitate an invalidation of - this entry. For example, a hot-pluggable ethernet - card could be pulled out and replaced by a - token-ring card. In such a case, if the agent has - such knowledge of the change, it is recommended that - it invalidate this entry. - - This object may not be modified if the associated - channelStatus object is equal to valid(1)." - ::= { channelEntry 2 } - - channelAcceptType OBJECT-TYPE - SYNTAX INTEGER { - acceptMatched(1), - acceptFailed(2) - } - ACCESS read-write - STATUS mandatory - DESCRIPTION - "This object controls the action of the filters - associated with this channel. If this object is equal - to acceptMatched(1), packets will be accepted to this - channel if they are accepted by both the packet data - and packet status matches of an associated filter. If - this object is equal to acceptFailed(2), packets will - be accepted to this channel only if they fail either - the packet data match or the packet status match of - each of the associated filters. - - In particular, a channel with no associated filters - will match no packets if set to acceptMatched(1) - case and will match all packets in the - acceptFailed(2) case. - - This object may not be modified if the associated - channelStatus object is equal to valid(1)." - ::= { channelEntry 3 } - - channelDataControl OBJECT-TYPE - SYNTAX INTEGER { - on(1), - off(2) - } - ACCESS read-write - STATUS mandatory - DESCRIPTION - - - "This object controls the flow of data through this - channel. If this object is on(1), data, status and - events flow through this channel. If this object is - off(2), data, status and events will not flow - through this channel." - DEFVAL { off } - ::= { channelEntry 4 } - - channelTurnOnEventIndex OBJECT-TYPE - SYNTAX INTEGER (0..65535) - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The value of this object identifies the event - that is configured to turn the associated - channelDataControl from off to on when the event is - generated. The event identified by a particular value - of this object is the same event as identified by the - same value of the eventIndex object. If there is no - corresponding entry in the eventTable, then no - association exists. In fact, if no event is intended - for this channel, channelTurnOnEventIndex must be - set to zero, a non-existent event index. - - This object may not be modified if the associated - channelStatus object is equal to valid(1)." - ::= { channelEntry 5 } - - channelTurnOffEventIndex OBJECT-TYPE - SYNTAX INTEGER (0..65535) - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The value of this object identifies the event - that is configured to turn the associated - channelDataControl from on to off when the event is - generated. The event identified by a particular value - of this object is the same event as identified by the - same value of the eventIndex object. If there is no - corresponding entry in the eventTable, then no - association exists. In fact, if no event is intended - for this channel, channelTurnOffEventIndex must be - set to zero, a non-existent event index. - - This object may not be modified if the associated - channelStatus object is equal to valid(1)." - ::= { channelEntry 6 } - - - - channelEventIndex OBJECT-TYPE - SYNTAX INTEGER (0..65535) - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The value of this object identifies the event - that is configured to be generated when the - associated channelDataControl is on and a packet - is matched. The event identified by a particular - value of this object is the same event as identified - by the same value of the eventIndex object. If - there is no corresponding entry in the eventTable, - then no association exists. In fact, if no event is - intended for this channel, channelEventIndex must be - set to zero, a non-existent event index. - - This object may not be modified if the associated - channelStatus object is equal to valid(1)." - ::= { channelEntry 7 } - - channelEventStatus OBJECT-TYPE - SYNTAX INTEGER { - eventReady(1), - eventFired(2), - eventAlwaysReady(3) - } - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The event status of this channel. - - If this channel is configured to generate events - when packets are matched, a means of controlling - the flow of those events is often needed. When - this object is equal to eventReady(1), a single - event may be generated, after which this object - will be set by the probe to eventFired(2). While - in the eventFired(2) state, no events will be - generated until the object is modified to - eventReady(1) (or eventAlwaysReady(3)). The - management station can thus easily respond to a - notification of an event by re-enabling this object. - - If the management station wishes to disable this - flow control and allow events to be generated - at will, this object may be set to - eventAlwaysReady(3). Disabling the flow control - is discouraged as it can result in high network - - - traffic or other performance problems." - DEFVAL { eventReady } - ::= { channelEntry 8 } - - channelMatches OBJECT-TYPE - SYNTAX Counter - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of times this channel has matched a - packet. Note that this object is updated even when - channelDataControl is set to off." - ::= { channelEntry 9 } - - channelDescription OBJECT-TYPE - SYNTAX DisplayString (SIZE (0..127)) - ACCESS read-write - STATUS mandatory - DESCRIPTION - "A comment describing this channel." - ::= { channelEntry 10 } - - channelOwner OBJECT-TYPE - SYNTAX OwnerString - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The entity that configured this entry and is - therefore using the resources assigned to it." - ::= { channelEntry 11 } - - channelStatus OBJECT-TYPE - SYNTAX EntryStatus - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The status of this channel entry." - ::= { channelEntry 12 } - - - -- The Packet Capture Group - - -- Implementation of the Packet Capture group is optional. - -- - -- The Packet Capture Group requires implementation of the - -- Filter Group. - -- - -- The Packet Capture group allows packets to be captured - - - -- upon a filter match. The bufferControlTable controls - -- the captured packets output from a channel that is - -- associated with it. The captured packets are placed - -- in entries in the captureBufferTable. These entries are - -- associated with the bufferControlEntry on whose behalf they - -- were stored. - - bufferControlTable OBJECT-TYPE - SYNTAX SEQUENCE OF BufferControlEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A list of buffers control entries." - ::= { capture 1 } - - bufferControlEntry OBJECT-TYPE - SYNTAX BufferControlEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A set of parameters that control the collection of - a stream of packets that have matched filters. As - an example, an instance of the - bufferControlCaptureSliceSize object might be named - bufferControlCaptureSliceSize.3" - INDEX { bufferControlIndex } - ::= { bufferControlTable 1 } - - BufferControlEntry ::= SEQUENCE { - bufferControlIndex INTEGER (1..65535), - bufferControlChannelIndex INTEGER (1..65535), - bufferControlFullStatus INTEGER, - bufferControlFullAction INTEGER, - bufferControlCaptureSliceSize INTEGER, - bufferControlDownloadSliceSize INTEGER, - bufferControlDownloadOffset INTEGER, - bufferControlMaxOctetsRequested INTEGER, - bufferControlMaxOctetsGranted INTEGER, - bufferControlCapturedPackets INTEGER, - bufferControlTurnOnTime TimeTicks, - bufferControlOwner OwnerString, - bufferControlStatus EntryStatus - } - - bufferControlIndex OBJECT-TYPE - SYNTAX INTEGER (1..65535) - ACCESS read-only - STATUS mandatory - - - DESCRIPTION - "An index that uniquely identifies an entry - in the bufferControl table. The value of this - index shall never be zero. Each such - entry defines one set of packets that is - captured and controlled by one or more filters." - ::= { bufferControlEntry 1 } - - bufferControlChannelIndex OBJECT-TYPE - SYNTAX INTEGER (1..65535) - ACCESS read-write - STATUS mandatory - DESCRIPTION - "An index that identifies the channel that is the - source of packets for this bufferControl table. - The channel identified by a particular value of this - index is the same as identified by the same value of - the channelIndex object. - - This object may not be modified if the associated - bufferControlStatus object is equal to valid(1)." - ::= { bufferControlEntry 2 } - - bufferControlFullStatus OBJECT-TYPE - SYNTAX INTEGER { - spaceAvailable(1), - full(2) - } - ACCESS read-only - STATUS mandatory - DESCRIPTION - "This object shows whether the buffer has room to - accept new packets or if it is full. - - If the status is spaceAvailable(1), the buffer is - accepting new packets normally. If the status is - full(2) and the associated bufferControlFullAction - object is wrapWhenFull, the buffer is accepting new - packets by deleting enough of the oldest packets - to make room for new ones as they arrive. Otherwise, - if the status is full(2) and the - bufferControlFullAction object is lockWhenFull, - then the buffer has stopped collecting packets. - - When this object is set to full(2) the probe must - not later set it to spaceAvailable(1) except in the - case of a significant gain in resources such as - an increase of bufferControlOctetsGranted. In - - - particular, the wrap-mode action of deleting old - packets to make room for newly arrived packets - must not affect the value of this object." - ::= { bufferControlEntry 3 } - - bufferControlFullAction OBJECT-TYPE - SYNTAX INTEGER { - lockWhenFull(1), - wrapWhenFull(2) -- FIFO - } - ACCESS read-write - STATUS mandatory - DESCRIPTION - "Controls the action of the buffer when it - reaches the full status. When in the lockWhenFull(1) - state and a packet is added to the buffer that - fills the buffer, the bufferControlFullStatus will - be set to full(2) and this buffer will stop capturing - packets." - ::= { bufferControlEntry 4 } - - bufferControlCaptureSliceSize OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The maximum number of octets of each packet - that will be saved in this capture buffer. - For example, if a 1500 octet packet is received by - the probe and this object is set to 500, then only - 500 octets of the packet will be stored in the - associated capture buffer. If this variable is set - to 0, the capture buffer will save as many octets - as is possible. - - This object may not be modified if the associated - bufferControlStatus object is equal to valid(1)." - DEFVAL { 100 } - ::= { bufferControlEntry 5 } - - bufferControlDownloadSliceSize OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The maximum number of octets of each packet - in this capture buffer that will be returned in - an SNMP retrieval of that packet. For example, - - - if 500 octets of a packet have been stored in the - associated capture buffer, the associated - bufferControlDownloadOffset is 0, and this - object is set to 100, then the captureBufferPacket - object that contains the packet will contain only - the first 100 octets of the packet. - - A prudent manager will take into account possible - interoperability or fragmentation problems that may - occur if the download slice size is set too large. - In particular, conformant SNMP implementations are not - required to accept messages whose length exceeds 484 - octets, although they are encouraged to support larger - datagrams whenever feasible." - DEFVAL { 100 } - ::= { bufferControlEntry 6 } - - bufferControlDownloadOffset OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The offset of the first octet of each packet - in this capture buffer that will be returned in - an SNMP retrieval of that packet. For example, - if 500 octets of a packet have been stored in the - associated capture buffer and this object is set to - 100, then the captureBufferPacket object that - contains the packet will contain bytes starting - 100 octets into the packet." - DEFVAL { 0 } - ::= { bufferControlEntry 7 } - - bufferControlMaxOctetsRequested OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The requested maximum number of octets to be - saved in this captureBuffer, including any - implementation-specific overhead. If this variable - is set to -1, the capture buffer will save as many - octets as is possible. - - When this object is created or modified, the probe - should set bufferControlMaxOctetsGranted as closely - to this object as is possible for the particular probe - implementation and available resources. However, if - - - the object has the special value of -1, the probe - must set bufferControlMaxOctetsGranted to -1." - DEFVAL { -1 } - ::= { bufferControlEntry 8 } - - bufferControlMaxOctetsGranted OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The maximum number of octets that can be - saved in this captureBuffer, including overhead. - If this variable is -1, the capture buffer will save - as many octets as possible. - - When the bufferControlMaxOctetsRequested object is - created or modified, the probe should set this object - as closely to the requested value as is possible for - the particular probe implementation and available - resources. - However, if the request object has the special value - of -1, the probe must set this object to -1. - The probe must not lower this value except as a result - of a modification to the associated - bufferControlMaxOctetsRequested object. - - When this maximum number of octets is reached - and a new packet is to be added to this - capture buffer and the corresponding - bufferControlFullAction is set to wrapWhenFull(2), - enough of the oldest packets associated with this - capture buffer shall be deleted by the agent so - that the new packet can be added. If the - corresponding bufferControlFullAction is set to - lockWhenFull(1), the new packet shall be discarded. - In either case, the probe must set - bufferControlFullStatus to full(2). - - When the value of this object changes to a value less - than the current value, entries are deleted from - the captureBufferTable associated with this - bufferControlEntry. Enough of the - oldest of these captureBufferEntries shall be - deleted by the agent so that the number of octets - used remains less than or equal to the new value of - this object. - - When the value of this object changes to a value - - - greater than the current value, the number of - associated captureBufferEntries may be allowed to - grow." - ::= { bufferControlEntry 9 } - - bufferControlCapturedPackets OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of packets currently in this - captureBuffer." - ::= { bufferControlEntry 10 } - - bufferControlTurnOnTime OBJECT-TYPE - SYNTAX TimeTicks - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The value of sysUpTime when this capture buffer was - first turned on." - ::= { bufferControlEntry 11 } - - bufferControlOwner OBJECT-TYPE - SYNTAX OwnerString - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The entity that configured this entry and is - therefore using the resources assigned to it." - ::= { bufferControlEntry 12 } - - bufferControlStatus OBJECT-TYPE - SYNTAX EntryStatus - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The status of this buffer Control Entry." - ::= { bufferControlEntry 13 } - - captureBufferTable OBJECT-TYPE - SYNTAX SEQUENCE OF CaptureBufferEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A list of packets captured off of a channel." - ::= { capture 2 } - - - - captureBufferEntry OBJECT-TYPE - SYNTAX CaptureBufferEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A packet captured off of an attached network. As an - example, an instance of the captureBufferPacketData - object might be named captureBufferPacketData.3.1783" - INDEX { captureBufferControlIndex, captureBufferIndex } - ::= { captureBufferTable 1 } - - CaptureBufferEntry ::= SEQUENCE { - captureBufferControlIndex INTEGER (1..65535), - captureBufferIndex INTEGER (1..2147483647), - captureBufferPacketID INTEGER, - captureBufferPacketData OCTET STRING, - captureBufferPacketLength INTEGER, - captureBufferPacketTime INTEGER, - captureBufferPacketStatus INTEGER - } - - captureBufferControlIndex OBJECT-TYPE - SYNTAX INTEGER (1..65535) - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The index of the bufferControlEntry with which - this packet is associated." - ::= { captureBufferEntry 1 } - - captureBufferIndex OBJECT-TYPE - SYNTAX INTEGER (1..2147483647) - ACCESS read-only - STATUS mandatory - DESCRIPTION - "An index that uniquely identifies an entry - in the captureBuffer table associated with a - particular bufferControlEntry. This index will - start at 1 and increase by one for each new packet - added with the same captureBufferControlIndex. - - Should this value reach 2147483647, the next packet - added with the same captureBufferControlIndex shall - cause this value to wrap around to 1." - ::= { captureBufferEntry 2 } - - captureBufferPacketID OBJECT-TYPE - SYNTAX INTEGER - - - ACCESS read-only - STATUS mandatory - DESCRIPTION - "An index that describes the order of packets - that are received on a particular interface. - The packetID of a packet captured on an - interface is defined to be greater than the - packetID's of all packets captured previously on - the same interface. As the captureBufferPacketID - object has a maximum positive value of 2^31 - 1, - any captureBufferPacketID object shall have the - value of the associated packet's packetID mod 2^31." - ::= { captureBufferEntry 3 } - - captureBufferPacketData OBJECT-TYPE - SYNTAX OCTET STRING - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The data inside the packet, starting at the - beginning of the packet plus any offset specified in - the associated bufferControlDownloadOffset, - including any link level headers. The length of the - data in this object is the minimum of the length of - the captured packet minus the offset, the length of - the associated bufferControlCaptureSliceSize minus - the offset, and the associated - bufferControlDownloadSliceSize. If this minimum is - less than zero, this object shall have a length of - zero." - ::= { captureBufferEntry 4 } - - captureBufferPacketLength OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The actual length (off the wire) of the packet stored - in this entry, including FCS octets." - ::= { captureBufferEntry 5 } - - captureBufferPacketTime OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The number of milliseconds that had passed since - this capture buffer was first turned on when this - - - packet was captured." - ::= { captureBufferEntry 6 } - - captureBufferPacketStatus OBJECT-TYPE - SYNTAX INTEGER - ACCESS read-only - STATUS mandatory - DESCRIPTION - "A value which indicates the error status of this - packet. - - The value of this object is defined in the same way as - filterPktStatus. The value is a sum. This sum - initially takes the value zero. Then, for each - error, E, that has been discovered in this packet, - 2 raised to a value representing E is added to the - sum. - - The errors defined for a packet captured off of an - Ethernet interface are as follows: - - bit # Error - 0 Packet is longer than 1518 octets - 1 Packet is shorter than 64 octets - 2 Packet experienced a CRC or Alignment - error - 3 First packet in this capture buffer after - it was detected that some packets were - not processed correctly. - 4 Packet's order in buffer is only - approximate (May only be set for packets - sent from the probe) - - For example, an Ethernet fragment would have a - value of 6 (2^1 + 2^2). - - As this MIB is expanded to new media types, this - object will have other media-specific errors defined." - ::= { captureBufferEntry 7 } - - - -- The Event Group - - -- Implementation of the Event group is optional. - -- - -- The Event group controls the generation and notification - -- of events from this device. Each entry in the eventTable - -- describes the parameters of the event that can be - - - -- triggered. Each event entry is fired by an associated - -- condition located elsewhere in the MIB. An event entry - -- may also be associated- with a function elsewhere in the - -- MIB that will be executed when the event is generated. For - -- example, a channel may be turned on or off by the firing - -- of an event. - -- - -- Each eventEntry may optionally specify that a log entry - -- be created on its behalf whenever the event occurs. - -- Each entry may also specify that notification should - -- occur by way of SNMP trap messages. In this case, the - -- community for the trap message is given in the associated - -- eventCommunity object. The enterprise and specific trap - -- fields of the trap are determined by the condition that - -- triggered the event. Two traps are defined: risingAlarm - -- and fallingAlarm. If the eventTable is triggered by a - -- condition specified elsewhere, the enterprise and - -- specific trap fields must be specified for traps - -- generated for that condition. - - eventTable OBJECT-TYPE - SYNTAX SEQUENCE OF EventEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A list of events to be generated." - ::= { event 1 } - - eventEntry OBJECT-TYPE - SYNTAX EventEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A set of parameters that describe an event to be - generated when certain conditions are met. As an - example, an instance of the eventLastTimeSent object - might be named eventLastTimeSent.6" - INDEX { eventIndex } - ::= { eventTable 1 } - - EventEntry ::= SEQUENCE { - eventIndex INTEGER (1..65535), - eventDescription DisplayString (SIZE (0..127)), - eventType INTEGER, - eventCommunity OCTET STRING (SIZE (0..127)), - eventLastTimeSent TimeTicks, - eventOwner OwnerString, - eventStatus EntryStatus - - - } - - eventIndex OBJECT-TYPE - SYNTAX INTEGER (1..65535) - ACCESS read-only - STATUS mandatory - DESCRIPTION - "An index that uniquely identifies an entry in the - event table. Each such entry defines one event that - is to be generated when the appropriate conditions - occur." - ::= { eventEntry 1 } - - eventDescription OBJECT-TYPE - SYNTAX DisplayString (SIZE (0..127)) - ACCESS read-write - STATUS mandatory - DESCRIPTION - "A comment describing this event entry." - ::= { eventEntry 2 } - - eventType OBJECT-TYPE - SYNTAX INTEGER { - none(1), - log(2), - snmp-trap(3), -- send an SNMP trap - log-and-trap(4) - } - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The type of notification that the probe will make - about this event. In the case of log, an entry is - made in the log table for each event. In the case of - snmp-trap, an SNMP trap is sent to one or more - management stations." - ::= { eventEntry 3 } - - eventCommunity OBJECT-TYPE - SYNTAX OCTET STRING (SIZE (0..127)) - ACCESS read-write - STATUS mandatory - DESCRIPTION - "If an SNMP trap is to be sent, it will be sent to - the SNMP community specified by this octet string. - In the future this table will be extended to include - the party security mechanism. This object shall be - set to a string of length zero if it is intended that - - - that mechanism be used to specify the destination of - the trap." - ::= { eventEntry 4 } - - eventLastTimeSent OBJECT-TYPE - SYNTAX TimeTicks - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The value of sysUpTime at the time this event - entry last generated an event. If this entry has - not generated any events, this value will be - zero." - ::= { eventEntry 5 } - - eventOwner OBJECT-TYPE - SYNTAX OwnerString - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The entity that configured this entry and is - therefore using the resources assigned to it. - - If this object contains a string starting with - 'monitor' and has associated entries in the log - table, all connected management stations should - retrieve those log entries, as they may have - significance to all management stations connected to - this device" - ::= { eventEntry 6 } - - eventStatus OBJECT-TYPE - SYNTAX EntryStatus - ACCESS read-write - STATUS mandatory - DESCRIPTION - "The status of this event entry. - - If this object is not equal to valid(1), all - associated log entries shall be deleted by the - agent." - ::= { eventEntry 7 } - - -- - logTable OBJECT-TYPE - SYNTAX SEQUENCE OF LogEntry - ACCESS not-accessible - STATUS mandatory - - - DESCRIPTION - "A list of events that have been logged." - ::= { event 2 } - - logEntry OBJECT-TYPE - SYNTAX LogEntry - ACCESS not-accessible - STATUS mandatory - DESCRIPTION - "A set of data describing an event that has been - logged. For example, an instance of the - logDescription object might be named - logDescription.6.47" - INDEX { logEventIndex, logIndex } - ::= { logTable 1 } - - LogEntry ::= SEQUENCE { - logEventIndex INTEGER (1..65535), - logIndex INTEGER (1..2147483647), - logTime TimeTicks, - logDescription DisplayString (SIZE (0..255)) - } - - logEventIndex OBJECT-TYPE - SYNTAX INTEGER (1..65535) - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The event entry that generated this log - entry. The log identified by a particular - value of this index is associated with the same - eventEntry as identified by the same value - of eventIndex." - ::= { logEntry 1 } - - logIndex OBJECT-TYPE - SYNTAX INTEGER (1..2147483647) - ACCESS read-only - STATUS mandatory - DESCRIPTION - "An index that uniquely identifies an entry - in the log table amongst those generated by the - same eventEntries. These indexes are - assigned beginning with 1 and increase by one - with each new log entry. The association - between values of logIndex and logEntries - is fixed for the lifetime of each logEntry. - The agent may choose to delete the oldest - - - instances of logEntry as required because of - lack of memory. It is an implementation-specific - matter as to when this deletion may occur." - ::= { logEntry 2 } - - logTime OBJECT-TYPE - SYNTAX TimeTicks - ACCESS read-only - STATUS mandatory - DESCRIPTION - "The value of sysUpTime when this log entry was - created." - ::= { logEntry 3 } - - logDescription OBJECT-TYPE - SYNTAX DisplayString (SIZE (0..255)) - ACCESS read-only - STATUS mandatory - DESCRIPTION - "An implementation dependent description of the - event that activated this log entry." - ::= { logEntry 4 } - - -- These definitions use the TRAP-TYPE macro as - -- defined in RFC 1215 [10] - - -- Remote Network Monitoring Traps - - risingAlarm TRAP-TYPE - ENTERPRISE rmon - VARIABLES { alarmIndex, alarmVariable, alarmSampleType, - alarmValue, alarmRisingThreshold } - DESCRIPTION - "The SNMP trap that is generated when an alarm - entry crosses its rising threshold and generates - an event that is configured for sending SNMP - traps." - ::= 1 - - fallingAlarm TRAP-TYPE - ENTERPRISE rmon - VARIABLES { alarmIndex, alarmVariable, alarmSampleType, - alarmValue, alarmFallingThreshold } - DESCRIPTION - "The SNMP trap that is generated when an alarm - entry crosses its falling threshold and generates - an event that is configured for sending SNMP - traps." - - - ::= 2 - - END +RMON-MIB DEFINITIONS ::= BEGIN + IMPORTS + MODULE-IDENTITY, OBJECT-TYPE, OBJECT-IDENTITY, + NOTIFICATION-TYPE, mib-2, Counter32, + Integer32, TimeTicks FROM SNMPv2-SMI + + TEXTUAL-CONVENTION, DisplayString FROM SNMPv2-TC + + MODULE-COMPLIANCE, OBJECT-GROUP, + NOTIFICATION-GROUP FROM SNMPv2-CONF; + + +-- Remote Network Monitoring MIB + +rmonMibModule MODULE-IDENTITY + LAST-UPDATED "200005110000Z" -- 11 May, 2000 + ORGANIZATION "IETF RMON MIB Working Group" + CONTACT-INFO + "Steve Waldbusser + Phone: +1-650-948-6500 + Fax: +1-650-745-0671 + Email: [email protected]" + DESCRIPTION + "Remote network monitoring devices, often called + monitors or probes, are instruments that exist for + the purpose of managing a network. This MIB defines + objects for managing remote network monitoring devices." + + REVISION "200005110000Z" -- 11 May, 2000 + DESCRIPTION + "Reformatted into SMIv2 format. + + This version published as RFC 2819." + + REVISION "199502010000Z" -- 1 Feb, 1995 + DESCRIPTION + "Bug fixes, clarifications and minor changes based on + implementation experience, published as RFC1757 [18]. + + Two changes were made to object definitions: + + 1) A new status bit has been defined for the + captureBufferPacketStatus object, indicating that the + packet order within the capture buffer may not be identical to + the packet order as received off the wire. This bit may only + be used for packets transmitted by the probe. Older NMS + applications can safely ignore this status bit, which might be + used by newer agents. + + 2) The packetMatch trap has been removed. This trap was never + actually 'approved' and was not added to this document along + with the risingAlarm and fallingAlarm traps. The packetMatch + trap could not be throttled, which could cause disruption of + normal network traffic under some circumstances. An NMS should + configure a risingAlarm threshold on the appropriate + channelMatches instance if a trap is desired for a packetMatch + event. Note that logging of packetMatch events is still + supported--only trap generation for such events has been + removed. + + In addition, several clarifications to individual object + definitions have been added to assist agent and NMS + implementors: + + - global definition of 'good packets' and 'bad packets' + + - more detailed text governing conceptual row creation and + modification + + - instructions for probes relating to interface changes and + disruptions + + - clarification of some ethernet counter definitions + + - recommended formula for calculating network utilization + + - clarification of channel and captureBuffer behavior for some + unusual conditions + + - examples of proper instance naming for each table" + + REVISION "199111010000Z" -- 1 Nov, 1991 + DESCRIPTION + "The original version of this MIB, published as RFC1271." + ::= { rmonConformance 8 } + + rmon OBJECT IDENTIFIER ::= { mib-2 16 } + + + -- textual conventions + +OwnerString ::= TEXTUAL-CONVENTION + STATUS current + + DESCRIPTION + "This data type is used to model an administratively + assigned name of the owner of a resource. Implementations + must accept values composed of well-formed NVT ASCII + sequences. In addition, implementations should accept + values composed of well-formed UTF-8 sequences. + + It is suggested that this name contain one or more of + the following: IP address, management station name, + network manager's name, location, or phone number. + In some cases the agent itself will be the owner of + an entry. In these cases, this string shall be set + to a string starting with 'monitor'. + + SNMP access control is articulated entirely in terms + of the contents of MIB views; access to a particular + SNMP object instance depends only upon its presence + or absence in a particular MIB view and never upon + its value or the value of related object instances. + Thus, objects of this type afford resolution of + resource contention only among cooperating + managers; they realize no access control function + with respect to uncooperative parties." + SYNTAX OCTET STRING (SIZE (0..127)) + +EntryStatus ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "The status of a table entry. + + Setting this object to the value invalid(4) has the + effect of invalidating the corresponding entry. + That is, it effectively disassociates the mapping + identified with said entry. + It is an implementation-specific matter as to whether + the agent removes an invalidated entry from the table. + Accordingly, management stations must be prepared to + receive tabular information from agents that corresponds + to entries currently not in use. Proper + interpretation of such entries requires examination + of the relevant EntryStatus object. + + An existing instance of this object cannot be set to + createRequest(2). This object may only be set to + createRequest(2) when this instance is created. When + this object is created, the agent may wish to create + supplemental object instances with default values + to complete a conceptual row in this table. Because the + creation of these default objects is entirely at the option + of the agent, the manager must not assume that any will be + created, but may make use of any that are created. + Immediately after completing the create operation, the agent + must set this object to underCreation(3). + + When in the underCreation(3) state, an entry is allowed to + exist in a possibly incomplete, possibly inconsistent state, + usually to allow it to be modified in multiple PDUs. When in + this state, an entry is not fully active. + Entries shall exist in the underCreation(3) state until + the management station is finished configuring the entry + and sets this object to valid(1) or aborts, setting this + object to invalid(4). If the agent determines that an + entry has been in the underCreation(3) state for an + abnormally long time, it may decide that the management + station has crashed. If the agent makes this decision, + it may set this object to invalid(4) to reclaim the + entry. A prudent agent will understand that the + management station may need to wait for human input + and will allow for that possibility in its + determination of this abnormally long period. + + An entry in the valid(1) state is fully configured and + consistent and fully represents the configuration or + operation such a row is intended to represent. For + example, it could be a statistical function that is + configured and active, or a filter that is available + in the list of filters processed by the packet capture + process. + + A manager is restricted to changing the state of an entry in + the following ways: + + To: valid createRequest underCreation invalid + From: + valid OK NO OK OK + createRequest N/A N/A N/A N/A + underCreation OK NO OK OK + invalid NO NO NO OK + nonExistent NO OK NO OK + + In the table above, it is not applicable to move the state + from the createRequest state to any other state because the + manager will never find the variable in that state. The + nonExistent state is not a value of the enumeration, rather + it means that the entryStatus variable does not exist at all. + + An agent may allow an entryStatus variable to change state in + additional ways, so long as the semantics of the states are + followed. This allowance is made to ease the implementation of + the agent and is made despite the fact that managers should + never exercise these additional state transitions." + SYNTAX INTEGER { + valid(1), + createRequest(2), + underCreation(3), + invalid(4) + } + + statistics OBJECT IDENTIFIER ::= { rmon 1 } + history OBJECT IDENTIFIER ::= { rmon 2 } + alarm OBJECT IDENTIFIER ::= { rmon 3 } + hosts OBJECT IDENTIFIER ::= { rmon 4 } + hostTopN OBJECT IDENTIFIER ::= { rmon 5 } + matrix OBJECT IDENTIFIER ::= { rmon 6 } + filter OBJECT IDENTIFIER ::= { rmon 7 } + capture OBJECT IDENTIFIER ::= { rmon 8 } + event OBJECT IDENTIFIER ::= { rmon 9 } + rmonConformance OBJECT IDENTIFIER ::= { rmon 20 } + +-- The Ethernet Statistics Group +-- +-- Implementation of the Ethernet Statistics group is optional. +-- Consult the MODULE-COMPLIANCE macro for the authoritative +-- conformance information for this MIB. +-- +-- The ethernet statistics group contains statistics measured by the +-- probe for each monitored interface on this device. These +-- statistics take the form of free running counters that start from +-- zero when a valid entry is created. +-- +-- This group currently has statistics defined only for +-- Ethernet interfaces. Each etherStatsEntry contains statistics +-- for one Ethernet interface. The probe must create one +-- etherStats entry for each monitored Ethernet interface +-- on the device. + +etherStatsTable OBJECT-TYPE + SYNTAX SEQUENCE OF EtherStatsEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of Ethernet statistics entries." + ::= { statistics 1 } + +etherStatsEntry OBJECT-TYPE + SYNTAX EtherStatsEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A collection of statistics kept for a particular + Ethernet interface. As an example, an instance of the + etherStatsPkts object might be named etherStatsPkts.1" + INDEX { etherStatsIndex } + ::= { etherStatsTable 1 } + +EtherStatsEntry ::= SEQUENCE { + etherStatsIndex Integer32, + etherStatsDataSource OBJECT IDENTIFIER, + etherStatsDropEvents Counter32, + etherStatsOctets Counter32, + etherStatsPkts Counter32, + etherStatsBroadcastPkts Counter32, + etherStatsMulticastPkts Counter32, + etherStatsCRCAlignErrors Counter32, + etherStatsUndersizePkts Counter32, + etherStatsOversizePkts Counter32, + etherStatsFragments Counter32, + etherStatsJabbers Counter32, + etherStatsCollisions Counter32, + etherStatsPkts64Octets Counter32, + etherStatsPkts65to127Octets Counter32, + etherStatsPkts128to255Octets Counter32, + etherStatsPkts256to511Octets Counter32, + etherStatsPkts512to1023Octets Counter32, + etherStatsPkts1024to1518Octets Counter32, + etherStatsOwner OwnerString, + etherStatsStatus EntryStatus +} + +etherStatsIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of this object uniquely identifies this + etherStats entry." + ::= { etherStatsEntry 1 } + +etherStatsDataSource OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS read-create + STATUS current + + DESCRIPTION + "This object identifies the source of the data that + this etherStats entry is configured to analyze. This + source can be any ethernet interface on this device. + In order to identify a particular interface, this object + shall identify the instance of the ifIndex object, + defined in RFC 2233 [17], for the desired interface. + For example, if an entry were to receive data from + interface #1, this object would be set to ifIndex.1. + + The statistics in this group reflect all packets + on the local network segment attached to the identified + interface. + + An agent may or may not be able to tell if fundamental + changes to the media of the interface have occurred and + necessitate an invalidation of this entry. For example, a + hot-pluggable ethernet card could be pulled out and replaced + by a token-ring card. In such a case, if the agent has such + knowledge of the change, it is recommended that it + invalidate this entry. + + This object may not be modified if the associated + etherStatsStatus object is equal to valid(1)." + ::= { etherStatsEntry 2 } + +etherStatsDropEvents OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of events in which packets + were dropped by the probe due to lack of resources. + Note that this number is not necessarily the number of + packets dropped; it is just the number of times this + condition has been detected." + ::= { etherStatsEntry 3 } + +etherStatsOctets OBJECT-TYPE + SYNTAX Counter32 + UNITS "Octets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of octets of data (including + those in bad packets) received on the + network (excluding framing bits but including + FCS octets). + + This object can be used as a reasonable estimate of + 10-Megabit ethernet utilization. If greater precision is + desired, the etherStatsPkts and etherStatsOctets objects + should be sampled before and after a common interval. The + differences in the sampled values are Pkts and Octets, + respectively, and the number of seconds in the interval is + Interval. These values are used to calculate the Utilization + as follows: + + Pkts * (9.6 + 6.4) + (Octets * .8) + Utilization = ------------------------------------- + Interval * 10,000 + + The result of this equation is the value Utilization which + is the percent utilization of the ethernet segment on a + scale of 0 to 100 percent." + ::= { etherStatsEntry 4 } + +etherStatsPkts OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of packets (including bad packets, + broadcast packets, and multicast packets) received." + ::= { etherStatsEntry 5 } + +etherStatsBroadcastPkts OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of good packets received that were + directed to the broadcast address. Note that this + does not include multicast packets." + ::= { etherStatsEntry 6 } + +etherStatsMulticastPkts OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of good packets received that were + directed to a multicast address. Note that this number + does not include packets directed to the broadcast + address." + ::= { etherStatsEntry 7 } + +etherStatsCRCAlignErrors OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of packets received that + had a length (excluding framing bits, but + including FCS octets) of between 64 and 1518 + octets, inclusive, but had either a bad + Frame Check Sequence (FCS) with an integral + number of octets (FCS Error) or a bad FCS with + a non-integral number of octets (Alignment Error)." + ::= { etherStatsEntry 8 } + +etherStatsUndersizePkts OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of packets received that were + less than 64 octets long (excluding framing bits, + but including FCS octets) and were otherwise well + formed." + ::= { etherStatsEntry 9 } + +etherStatsOversizePkts OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of packets received that were + longer than 1518 octets (excluding framing bits, + but including FCS octets) and were otherwise + well formed." + ::= { etherStatsEntry 10 } + +etherStatsFragments OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of packets received that were less than + 64 octets in length (excluding framing bits but including + FCS octets) and had either a bad Frame Check Sequence + (FCS) with an integral number of octets (FCS Error) or a + bad FCS with a non-integral number of octets (Alignment + Error). + + Note that it is entirely normal for etherStatsFragments to + increment. This is because it counts both runts (which are + normal occurrences due to collisions) and noise hits." + ::= { etherStatsEntry 11 } + +etherStatsJabbers OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of packets received that were + longer than 1518 octets (excluding framing bits, + but including FCS octets), and had either a bad + Frame Check Sequence (FCS) with an integral number + of octets (FCS Error) or a bad FCS with a non-integral + number of octets (Alignment Error). + + Note that this definition of jabber is different + than the definition in IEEE-802.3 section 8.2.1.5 + (10BASE5) and section 10.3.1.4 (10BASE2). These + documents define jabber as the condition where any + packet exceeds 20 ms. The allowed range to detect + jabber is between 20 ms and 150 ms." + ::= { etherStatsEntry 12 } + +etherStatsCollisions OBJECT-TYPE + SYNTAX Counter32 + UNITS "Collisions" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The best estimate of the total number of collisions + on this Ethernet segment. + + The value returned will depend on the location of the + RMON probe. Section 8.2.1.3 (10BASE-5) and section + 10.3.1.3 (10BASE-2) of IEEE standard 802.3 states that a + station must detect a collision, in the receive mode, if + three or more stations are transmitting simultaneously. A + repeater port must detect a collision when two or more + stations are transmitting simultaneously. Thus a probe + placed on a repeater port could record more collisions + than a probe connected to a station on the same segment + would. + + Probe location plays a much smaller role when considering + 10BASE-T. 14.2.1.4 (10BASE-T) of IEEE standard 802.3 + defines a collision as the simultaneous presence of signals + on the DO and RD circuits (transmitting and receiving + at the same time). A 10BASE-T station can only detect + collisions when it is transmitting. Thus probes placed on + a station and a repeater, should report the same number of + collisions. + + Note also that an RMON probe inside a repeater should + ideally report collisions between the repeater and one or + more other hosts (transmit collisions as defined by IEEE + 802.3k) plus receiver collisions observed on any coax + segments to which the repeater is connected." + ::= { etherStatsEntry 13 } + +etherStatsPkts64Octets OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of packets (including bad + packets) received that were 64 octets in length + (excluding framing bits but including FCS octets)." + ::= { etherStatsEntry 14 } + +etherStatsPkts65to127Octets OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of packets (including bad + packets) received that were between + 65 and 127 octets in length inclusive + (excluding framing bits but including FCS octets)." + ::= { etherStatsEntry 15 } + +etherStatsPkts128to255Octets OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + + STATUS current + DESCRIPTION + "The total number of packets (including bad + packets) received that were between + 128 and 255 octets in length inclusive + (excluding framing bits but including FCS octets)." + ::= { etherStatsEntry 16 } + +etherStatsPkts256to511Octets OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of packets (including bad + packets) received that were between + 256 and 511 octets in length inclusive + (excluding framing bits but including FCS octets)." + ::= { etherStatsEntry 17 } + +etherStatsPkts512to1023Octets OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of packets (including bad + packets) received that were between + 512 and 1023 octets in length inclusive + (excluding framing bits but including FCS octets)." + ::= { etherStatsEntry 18 } + +etherStatsPkts1024to1518Octets OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of packets (including bad + packets) received that were between + 1024 and 1518 octets in length inclusive + (excluding framing bits but including FCS octets)." + ::= { etherStatsEntry 19 } + +etherStatsOwner OBJECT-TYPE + SYNTAX OwnerString + MAX-ACCESS read-create + STATUS current + + DESCRIPTION + "The entity that configured this entry and is therefore + using the resources assigned to it." + ::= { etherStatsEntry 20 } + +etherStatsStatus OBJECT-TYPE + SYNTAX EntryStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this etherStats entry." + ::= { etherStatsEntry 21 } + +-- The History Control Group + +-- Implementation of the History Control group is optional. +-- Consult the MODULE-COMPLIANCE macro for the authoritative +-- conformance information for this MIB. +-- +-- The history control group controls the periodic statistical +-- sampling of data from various types of networks. The +-- historyControlTable stores configuration entries that each +-- define an interface, polling period, and other parameters. +-- Once samples are taken, their data is stored in an entry +-- in a media-specific table. Each such entry defines one +-- sample, and is associated with the historyControlEntry that +-- caused the sample to be taken. Each counter in the +-- etherHistoryEntry counts the same event as its similarly-named +-- counterpart in the etherStatsEntry, except that each value here +-- is a cumulative sum during a sampling period. +-- +-- If the probe keeps track of the time of day, it should start +-- the first sample of the history at a time such that +-- when the next hour of the day begins, a sample is +-- started at that instant. This tends to make more +-- user-friendly reports, and enables comparison of reports +-- from different probes that have relatively accurate time +-- of day. +-- +-- The probe is encouraged to add two history control entries +-- per monitored interface upon initialization that describe a short +-- term and a long term polling period. Suggested parameters are 30 +-- seconds for the short term polling period and 30 minutes for +-- the long term period. + +historyControlTable OBJECT-TYPE + SYNTAX SEQUENCE OF HistoryControlEntry + MAX-ACCESS not-accessible + + STATUS current + DESCRIPTION + "A list of history control entries." + ::= { history 1 } + +historyControlEntry OBJECT-TYPE + SYNTAX HistoryControlEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of parameters that set up a periodic sampling of + statistics. As an example, an instance of the + historyControlInterval object might be named + historyControlInterval.2" + INDEX { historyControlIndex } + ::= { historyControlTable 1 } + +HistoryControlEntry ::= SEQUENCE { + historyControlIndex Integer32, + historyControlDataSource OBJECT IDENTIFIER, + historyControlBucketsRequested Integer32, + historyControlBucketsGranted Integer32, + historyControlInterval Integer32, + historyControlOwner OwnerString, + historyControlStatus EntryStatus +} + +historyControlIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "An index that uniquely identifies an entry in the + historyControl table. Each such entry defines a + set of samples at a particular interval for an + interface on the device." + ::= { historyControlEntry 1 } + +historyControlDataSource OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "This object identifies the source of the data for + which historical data was collected and + placed in a media-specific table on behalf of this + historyControlEntry. This source can be any + interface on this device. In order to identify + a particular interface, this object shall identify + the instance of the ifIndex object, defined + in RFC 2233 [17], for the desired interface. + For example, if an entry were to receive data from + interface #1, this object would be set to ifIndex.1. + + The statistics in this group reflect all packets + on the local network segment attached to the identified + interface. + + An agent may or may not be able to tell if fundamental + changes to the media of the interface have occurred and + necessitate an invalidation of this entry. For example, a + hot-pluggable ethernet card could be pulled out and replaced + by a token-ring card. In such a case, if the agent has such + knowledge of the change, it is recommended that it + invalidate this entry. + + This object may not be modified if the associated + historyControlStatus object is equal to valid(1)." + ::= { historyControlEntry 2 } + +historyControlBucketsRequested OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The requested number of discrete time intervals + over which data is to be saved in the part of the + media-specific table associated with this + historyControlEntry. + + When this object is created or modified, the probe + should set historyControlBucketsGranted as closely to + this object as is possible for the particular probe + implementation and available resources." + DEFVAL { 50 } + ::= { historyControlEntry 3 } + +historyControlBucketsGranted OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of discrete sampling intervals + over which data shall be saved in the part of + the media-specific table associated with this + historyControlEntry. + + When the associated historyControlBucketsRequested + object is created or modified, the probe + should set this object as closely to the requested + value as is possible for the particular + probe implementation and available resources. The + probe must not lower this value except as a result + of a modification to the associated + historyControlBucketsRequested object. + + There will be times when the actual number of + buckets associated with this entry is less than + the value of this object. In this case, at the + end of each sampling interval, a new bucket will + be added to the media-specific table. + + When the number of buckets reaches the value of + this object and a new bucket is to be added to the + media-specific table, the oldest bucket associated + with this historyControlEntry shall be deleted by + the agent so that the new bucket can be added. + + When the value of this object changes to a value less + than the current value, entries are deleted + from the media-specific table associated with this + historyControlEntry. Enough of the oldest of these + entries shall be deleted by the agent so that their + number remains less than or equal to the new value of + this object. + + When the value of this object changes to a value greater + than the current value, the number of associated media- + specific entries may be allowed to grow." + ::= { historyControlEntry 4 } + +historyControlInterval OBJECT-TYPE + SYNTAX Integer32 (1..3600) + UNITS "Seconds" + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The interval in seconds over which the data is + sampled for each bucket in the part of the + media-specific table associated with this + historyControlEntry. This interval can + be set to any number of seconds between 1 and + 3600 (1 hour). + + Because the counters in a bucket may overflow at their + maximum value with no indication, a prudent manager will + take into account the possibility of overflow in any of + the associated counters. It is important to consider the + minimum time in which any counter could overflow on a + particular media type and set the historyControlInterval + object to a value less than this interval. This is + typically most important for the 'octets' counter in any + media-specific table. For example, on an Ethernet + network, the etherHistoryOctets counter could overflow + in about one hour at the Ethernet's maximum + utilization. + + This object may not be modified if the associated + historyControlStatus object is equal to valid(1)." + DEFVAL { 1800 } + ::= { historyControlEntry 5 } + +historyControlOwner OBJECT-TYPE + SYNTAX OwnerString + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The entity that configured this entry and is therefore + using the resources assigned to it." + ::= { historyControlEntry 6 } + +historyControlStatus OBJECT-TYPE + SYNTAX EntryStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this historyControl entry. + + Each instance of the media-specific table associated + with this historyControlEntry will be deleted by the agent + if this historyControlEntry is not equal to valid(1)." + ::= { historyControlEntry 7 } + +-- The Ethernet History Group + +-- Implementation of the Ethernet History group is optional. +-- Consult the MODULE-COMPLIANCE macro for the authoritative +-- conformance information for this MIB. +-- +-- The Ethernet History group records periodic statistical samples +-- from a network and stores them for later retrieval. +-- Once samples are taken, their data is stored in an entry +-- in a media-specific table. Each such entry defines one +-- sample, and is associated with the historyControlEntry that +-- caused the sample to be taken. This group defines the +-- etherHistoryTable, for Ethernet networks. +-- + +etherHistoryTable OBJECT-TYPE + SYNTAX SEQUENCE OF EtherHistoryEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of Ethernet history entries." + ::= { history 2 } + +etherHistoryEntry OBJECT-TYPE + SYNTAX EtherHistoryEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "An historical sample of Ethernet statistics on a particular + Ethernet interface. This sample is associated with the + historyControlEntry which set up the parameters for + a regular collection of these samples. As an example, an + instance of the etherHistoryPkts object might be named + etherHistoryPkts.2.89" + INDEX { etherHistoryIndex , etherHistorySampleIndex } + ::= { etherHistoryTable 1 } + +EtherHistoryEntry ::= SEQUENCE { + etherHistoryIndex Integer32, + etherHistorySampleIndex Integer32, + etherHistoryIntervalStart TimeTicks, + etherHistoryDropEvents Counter32, + etherHistoryOctets Counter32, + etherHistoryPkts Counter32, + etherHistoryBroadcastPkts Counter32, + etherHistoryMulticastPkts Counter32, + etherHistoryCRCAlignErrors Counter32, + etherHistoryUndersizePkts Counter32, + etherHistoryOversizePkts Counter32, + etherHistoryFragments Counter32, + etherHistoryJabbers Counter32, + etherHistoryCollisions Counter32, + etherHistoryUtilization Integer32 +} + +etherHistoryIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The history of which this entry is a part. The + history identified by a particular value of this + index is the same history as identified + by the same value of historyControlIndex." + ::= { etherHistoryEntry 1 } + +etherHistorySampleIndex OBJECT-TYPE + SYNTAX Integer32 (1..2147483647) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "An index that uniquely identifies the particular + sample this entry represents among all samples + associated with the same historyControlEntry. + This index starts at 1 and increases by one + as each new sample is taken." + ::= { etherHistoryEntry 2 } + +etherHistoryIntervalStart OBJECT-TYPE + SYNTAX TimeTicks + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime at the start of the interval + over which this sample was measured. If the probe + keeps track of the time of day, it should start + the first sample of the history at a time such that + when the next hour of the day begins, a sample is + started at that instant. Note that following this + rule may require the probe to delay collecting the + first sample of the history, as each sample must be + of the same interval. Also note that the sample which + is currently being collected is not accessible in this + table until the end of its interval." + ::= { etherHistoryEntry 3 } + +etherHistoryDropEvents OBJECT-TYPE + SYNTAX Counter32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of events in which packets + were dropped by the probe due to lack of resources + during this sampling interval. Note that this number + is not necessarily the number of packets dropped, it + is just the number of times this condition has been + detected." + ::= { etherHistoryEntry 4 } + +etherHistoryOctets OBJECT-TYPE + SYNTAX Counter32 + UNITS "Octets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of octets of data (including + those in bad packets) received on the + network (excluding framing bits but including + FCS octets)." + ::= { etherHistoryEntry 5 } + +etherHistoryPkts OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of packets (including bad packets) + received during this sampling interval." + ::= { etherHistoryEntry 6 } + +etherHistoryBroadcastPkts OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of good packets received during this + sampling interval that were directed to the + broadcast address." + ::= { etherHistoryEntry 7 } + +etherHistoryMulticastPkts OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of good packets received during this + sampling interval that were directed to a + multicast address. Note that this number does not + include packets addressed to the broadcast address." + ::= { etherHistoryEntry 8 } + +etherHistoryCRCAlignErrors OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of packets received during this + sampling interval that had a length (excluding + framing bits but including FCS octets) between + 64 and 1518 octets, inclusive, but had either a bad Frame + Check Sequence (FCS) with an integral number of octets + (FCS Error) or a bad FCS with a non-integral number + of octets (Alignment Error)." + ::= { etherHistoryEntry 9 } + +etherHistoryUndersizePkts OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of packets received during this + sampling interval that were less than 64 octets + long (excluding framing bits but including FCS + octets) and were otherwise well formed." + ::= { etherHistoryEntry 10 } + +etherHistoryOversizePkts OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of packets received during this + sampling interval that were longer than 1518 + octets (excluding framing bits but including + FCS octets) but were otherwise well formed." + ::= { etherHistoryEntry 11 } + +etherHistoryFragments OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The total number of packets received during this + sampling interval that were less than 64 octets in + length (excluding framing bits but including FCS + octets) had either a bad Frame Check Sequence (FCS) + with an integral number of octets (FCS Error) or a bad + FCS with a non-integral number of octets (Alignment + Error). + + Note that it is entirely normal for etherHistoryFragments to + increment. This is because it counts both runts (which are + normal occurrences due to collisions) and noise hits." + ::= { etherHistoryEntry 12 } + +etherHistoryJabbers OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of packets received during this + sampling interval that were longer than 1518 octets + (excluding framing bits but including FCS octets), + and had either a bad Frame Check Sequence (FCS) + with an integral number of octets (FCS Error) or + a bad FCS with a non-integral number of octets + (Alignment Error). + + Note that this definition of jabber is different + than the definition in IEEE-802.3 section 8.2.1.5 + (10BASE5) and section 10.3.1.4 (10BASE2). These + documents define jabber as the condition where any + packet exceeds 20 ms. The allowed range to detect + jabber is between 20 ms and 150 ms." + ::= { etherHistoryEntry 13 } + +etherHistoryCollisions OBJECT-TYPE + SYNTAX Counter32 + UNITS "Collisions" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The best estimate of the total number of collisions + on this Ethernet segment during this sampling + interval. + + The value returned will depend on the location of the + RMON probe. Section 8.2.1.3 (10BASE-5) and section + 10.3.1.3 (10BASE-2) of IEEE standard 802.3 states that a + station must detect a collision, in the receive mode, if + three or more stations are transmitting simultaneously. A + repeater port must detect a collision when two or more + stations are transmitting simultaneously. Thus a probe + placed on a repeater port could record more collisions + than a probe connected to a station on the same segment + would. + + Probe location plays a much smaller role when considering + 10BASE-T. 14.2.1.4 (10BASE-T) of IEEE standard 802.3 + defines a collision as the simultaneous presence of signals + on the DO and RD circuits (transmitting and receiving + at the same time). A 10BASE-T station can only detect + collisions when it is transmitting. Thus probes placed on + a station and a repeater, should report the same number of + collisions. + + Note also that an RMON probe inside a repeater should + ideally report collisions between the repeater and one or + more other hosts (transmit collisions as defined by IEEE + 802.3k) plus receiver collisions observed on any coax + segments to which the repeater is connected." + ::= { etherHistoryEntry 14 } + +etherHistoryUtilization OBJECT-TYPE + SYNTAX Integer32 (0..10000) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The best estimate of the mean physical layer + network utilization on this interface during this + sampling interval, in hundredths of a percent." + ::= { etherHistoryEntry 15 } + +-- The Alarm Group + +-- Implementation of the Alarm group is optional. The Alarm Group +-- requires the implementation of the Event group. +-- Consult the MODULE-COMPLIANCE macro for the authoritative +-- conformance information for this MIB. +-- +-- The Alarm group periodically takes statistical samples from +-- variables in the probe and compares them to thresholds that have +-- been configured. The alarm table stores configuration +-- entries that each define a variable, polling period, and +-- threshold parameters. If a sample is found to cross the +-- threshold values, an event is generated. Only variables that +-- resolve to an ASN.1 primitive type of INTEGER (INTEGER, Integer32, +-- Counter32, Counter64, Gauge32, or TimeTicks) may be monitored in +-- this way. +-- +-- This function has a hysteresis mechanism to limit the generation +-- of events. This mechanism generates one event as a threshold +-- is crossed in the appropriate direction. No more events are +-- generated for that threshold until the opposite threshold is +-- crossed. +-- +-- In the case of a sampling a deltaValue, a probe may implement +-- this mechanism with more precision if it takes a delta sample +-- twice per period, each time comparing the sum of the latest two +-- samples to the threshold. This allows the detection of threshold +-- crossings that span the sampling boundary. Note that this does +-- not require any special configuration of the threshold value. +-- It is suggested that probes implement this more precise algorithm. + +alarmTable OBJECT-TYPE + SYNTAX SEQUENCE OF AlarmEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of alarm entries." + ::= { alarm 1 } + +alarmEntry OBJECT-TYPE + SYNTAX AlarmEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of parameters that set up a periodic checking + for alarm conditions. For example, an instance of the + alarmValue object might be named alarmValue.8" + INDEX { alarmIndex } + ::= { alarmTable 1 } + +AlarmEntry ::= SEQUENCE { + alarmIndex Integer32, + alarmInterval Integer32, + alarmVariable OBJECT IDENTIFIER, + alarmSampleType INTEGER, + alarmValue Integer32, + alarmStartupAlarm INTEGER, + alarmRisingThreshold Integer32, + alarmFallingThreshold Integer32, + alarmRisingEventIndex Integer32, + alarmFallingEventIndex Integer32, + alarmOwner OwnerString, + alarmStatus EntryStatus +} + +alarmIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "An index that uniquely identifies an entry in the + alarm table. Each such entry defines a + diagnostic sample at a particular interval + for an object on the device." + ::= { alarmEntry 1 } + +alarmInterval OBJECT-TYPE + SYNTAX Integer32 + UNITS "Seconds" + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The interval in seconds over which the data is + sampled and compared with the rising and falling + thresholds. When setting this variable, care + should be taken in the case of deltaValue + sampling - the interval should be set short enough + that the sampled variable is very unlikely to + increase or decrease by more than 2^31 - 1 during + a single sampling interval. + + This object may not be modified if the associated + alarmStatus object is equal to valid(1)." + ::= { alarmEntry 2 } + +alarmVariable OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The object identifier of the particular variable to be + sampled. Only variables that resolve to an ASN.1 primitive + type of INTEGER (INTEGER, Integer32, Counter32, Counter64, + Gauge, or TimeTicks) may be sampled. + + Because SNMP access control is articulated entirely + in terms of the contents of MIB views, no access + control mechanism exists that can restrict the value of + this object to identify only those objects that exist + in a particular MIB view. Because there is thus no + acceptable means of restricting the read access that + could be obtained through the alarm mechanism, the + probe must only grant write access to this object in + those views that have read access to all objects on + the probe. + + During a set operation, if the supplied variable name is + not available in the selected MIB view, a badValue error + must be returned. If at any time the variable name of + an established alarmEntry is no longer available in the + selected MIB view, the probe must change the status of + this alarmEntry to invalid(4). + + This object may not be modified if the associated + alarmStatus object is equal to valid(1)." + ::= { alarmEntry 3 } + +alarmSampleType OBJECT-TYPE + SYNTAX INTEGER { + absoluteValue(1), + deltaValue(2) + } + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The method of sampling the selected variable and + calculating the value to be compared against the + thresholds. If the value of this object is + absoluteValue(1), the value of the selected variable + will be compared directly with the thresholds at the + end of the sampling interval. If the value of this + object is deltaValue(2), the value of the selected + variable at the last sample will be subtracted from + the current value, and the difference compared with + the thresholds. + + This object may not be modified if the associated + alarmStatus object is equal to valid(1)." + ::= { alarmEntry 4 } + +alarmValue OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of the statistic during the last sampling + period. For example, if the sample type is deltaValue, + this value will be the difference between the samples + at the beginning and end of the period. If the sample + type is absoluteValue, this value will be the sampled + value at the end of the period. + This is the value that is compared with the rising and + falling thresholds. + + The value during the current sampling period is not + made available until the period is completed and will + remain available until the next period completes." + ::= { alarmEntry 5 } + +alarmStartupAlarm OBJECT-TYPE + SYNTAX INTEGER { + risingAlarm(1), + fallingAlarm(2), + risingOrFallingAlarm(3) + } + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The alarm that may be sent when this entry is first + set to valid. If the first sample after this entry + becomes valid is greater than or equal to the + risingThreshold and alarmStartupAlarm is equal to + risingAlarm(1) or risingOrFallingAlarm(3), then a single + rising alarm will be generated. If the first sample + after this entry becomes valid is less than or equal + to the fallingThreshold and alarmStartupAlarm is equal + to fallingAlarm(2) or risingOrFallingAlarm(3), then a + single falling alarm will be generated. + + This object may not be modified if the associated + alarmStatus object is equal to valid(1)." + ::= { alarmEntry 6 } + +alarmRisingThreshold OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "A threshold for the sampled statistic. When the current + sampled value is greater than or equal to this threshold, + and the value at the last sampling interval was less than + this threshold, a single event will be generated. + A single event will also be generated if the first + sample after this entry becomes valid is greater than or + equal to this threshold and the associated + alarmStartupAlarm is equal to risingAlarm(1) or + risingOrFallingAlarm(3). + + After a rising event is generated, another such event + will not be generated until the sampled value + falls below this threshold and reaches the + alarmFallingThreshold. + + This object may not be modified if the associated + alarmStatus object is equal to valid(1)." + ::= { alarmEntry 7 } + +alarmFallingThreshold OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "A threshold for the sampled statistic. When the current + sampled value is less than or equal to this threshold, + and the value at the last sampling interval was greater than + this threshold, a single event will be generated. + A single event will also be generated if the first + sample after this entry becomes valid is less than or + equal to this threshold and the associated + alarmStartupAlarm is equal to fallingAlarm(2) or + risingOrFallingAlarm(3). + + After a falling event is generated, another such event + will not be generated until the sampled value + rises above this threshold and reaches the + alarmRisingThreshold. + + This object may not be modified if the associated + alarmStatus object is equal to valid(1)." + ::= { alarmEntry 8 } + +alarmRisingEventIndex OBJECT-TYPE + SYNTAX Integer32 (0..65535) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The index of the eventEntry that is + used when a rising threshold is crossed. The + eventEntry identified by a particular value of + this index is the same as identified by the same value + of the eventIndex object. If there is no + corresponding entry in the eventTable, then + no association exists. In particular, if this value + is zero, no associated event will be generated, as + zero is not a valid event index. + + This object may not be modified if the associated + alarmStatus object is equal to valid(1)." + ::= { alarmEntry 9 } + +alarmFallingEventIndex OBJECT-TYPE + SYNTAX Integer32 (0..65535) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The index of the eventEntry that is + used when a falling threshold is crossed. The + eventEntry identified by a particular value of + this index is the same as identified by the same value + of the eventIndex object. If there is no + corresponding entry in the eventTable, then + no association exists. In particular, if this value + is zero, no associated event will be generated, as + zero is not a valid event index. + + This object may not be modified if the associated + alarmStatus object is equal to valid(1)." + ::= { alarmEntry 10 } + +alarmOwner OBJECT-TYPE + SYNTAX OwnerString + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The entity that configured this entry and is therefore + using the resources assigned to it." + ::= { alarmEntry 11 } + +alarmStatus OBJECT-TYPE + SYNTAX EntryStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this alarm entry." + ::= { alarmEntry 12 } + +-- The Host Group + +-- Implementation of the Host group is optional. +-- Consult the MODULE-COMPLIANCE macro for the authoritative +-- conformance information for this MIB. +-- +-- The host group discovers new hosts on the network by +-- keeping a list of source and destination MAC Addresses seen +-- in good packets. For each of these addresses, the host group +-- keeps a set of statistics. The hostControlTable controls +-- which interfaces this function is performed on, and contains +-- some information about the process. On behalf of each +-- hostControlEntry, data is collected on an interface and placed +-- in both the hostTable and the hostTimeTable. If the +-- monitoring device finds itself short of resources, it may +-- delete entries as needed. It is suggested that the device +-- delete the least recently used entries first. + +-- The hostTable contains entries for each address discovered on +-- a particular interface. Each entry contains statistical +-- data about that host. This table is indexed by the +-- MAC address of the host, through which a random access +-- may be achieved. + +-- The hostTimeTable contains data in the same format as the +-- hostTable, and must contain the same set of hosts, but is +-- indexed using hostTimeCreationOrder rather than hostAddress. +-- The hostTimeCreationOrder is an integer which reflects +-- the relative order in which a particular entry was discovered +-- and thus inserted into the table. As this order, and thus +-- the index, is among those entries currently in the table, +-- the index for a particular entry may change if an +-- (earlier) entry is deleted. Thus the association between +-- hostTimeCreationOrder and hostTimeEntry may be broken at +-- any time. + +-- The hostTimeTable has two important uses. The first is the +-- fast download of this potentially large table. Because the +-- index of this table runs from 1 to the size of the table, +-- inclusive, its values are predictable. This allows very +-- efficient packing of variables into SNMP PDU's and allows +-- a table transfer to have multiple packets outstanding. +-- These benefits increase transfer rates tremendously. + +-- The second use of the hostTimeTable is the efficient discovery +-- by the management station of new entries added to the table. +-- After the management station has downloaded the entire table, +-- it knows that new entries will be added immediately after the +-- end of the current table. It can thus detect new entries there +-- and retrieve them easily. + +-- Because the association between hostTimeCreationOrder and +-- hostTimeEntry may be broken at any time, the management +-- station must monitor the related hostControlLastDeleteTime +-- object. When the management station thus detects a deletion, +-- it must assume that any such associations have been broken, +-- and invalidate any it has stored locally. This includes +-- restarting any download of the hostTimeTable that may have been +-- in progress, as well as rediscovering the end of the +-- hostTimeTable so that it may detect new entries. If the +-- management station does not detect the broken association, +-- it may continue to refer to a particular host by its +-- creationOrder while unwittingly retrieving the data associated +-- with another host entirely. If this happens while downloading +-- the host table, the management station may fail to download +-- all of the entries in the table. + + +hostControlTable OBJECT-TYPE + SYNTAX SEQUENCE OF HostControlEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of host table control entries." + ::= { hosts 1 } + +hostControlEntry OBJECT-TYPE + SYNTAX HostControlEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of parameters that set up the discovery of hosts + on a particular interface and the collection of statistics + about these hosts. For example, an instance of the + hostControlTableSize object might be named + hostControlTableSize.1" + INDEX { hostControlIndex } + ::= { hostControlTable 1 } + +HostControlEntry ::= SEQUENCE { + + hostControlIndex Integer32, + hostControlDataSource OBJECT IDENTIFIER, + hostControlTableSize Integer32, + hostControlLastDeleteTime TimeTicks, + hostControlOwner OwnerString, + hostControlStatus EntryStatus +} + +hostControlIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "An index that uniquely identifies an entry in the + hostControl table. Each such entry defines + a function that discovers hosts on a particular interface + and places statistics about them in the hostTable and + the hostTimeTable on behalf of this hostControlEntry." + ::= { hostControlEntry 1 } + +hostControlDataSource OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "This object identifies the source of the data for + this instance of the host function. This source + can be any interface on this device. In order + to identify a particular interface, this object shall + identify the instance of the ifIndex object, defined + in RFC 2233 [17], for the desired interface. + For example, if an entry were to receive data from + interface #1, this object would be set to ifIndex.1. + + The statistics in this group reflect all packets + on the local network segment attached to the identified + interface. + + An agent may or may not be able to tell if fundamental + changes to the media of the interface have occurred and + necessitate an invalidation of this entry. For example, a + hot-pluggable ethernet card could be pulled out and replaced + by a token-ring card. In such a case, if the agent has such + knowledge of the change, it is recommended that it + invalidate this entry. + + This object may not be modified if the associated + hostControlStatus object is equal to valid(1)." + ::= { hostControlEntry 2 } + +hostControlTableSize OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of hostEntries in the hostTable and the + hostTimeTable associated with this hostControlEntry." + ::= { hostControlEntry 3 } + +hostControlLastDeleteTime OBJECT-TYPE + SYNTAX TimeTicks + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime when the last entry + was deleted from the portion of the hostTable + associated with this hostControlEntry. If no + deletions have occurred, this value shall be zero." + ::= { hostControlEntry 4 } + +hostControlOwner OBJECT-TYPE + SYNTAX OwnerString + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The entity that configured this entry and is therefore + using the resources assigned to it." + ::= { hostControlEntry 5 } + +hostControlStatus OBJECT-TYPE + SYNTAX EntryStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this hostControl entry. + + If this object is not equal to valid(1), all associated + entries in the hostTable, hostTimeTable, and the + hostTopNTable shall be deleted by the agent." + ::= { hostControlEntry 6 } + +hostTable OBJECT-TYPE + SYNTAX SEQUENCE OF HostEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of host entries." + ::= { hosts 2 } + +hostEntry OBJECT-TYPE + SYNTAX HostEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A collection of statistics for a particular host that has + been discovered on an interface of this device. For example, + an instance of the hostOutBroadcastPkts object might be + named hostOutBroadcastPkts.1.6.8.0.32.27.3.176" + INDEX { hostIndex, hostAddress } + ::= { hostTable 1 } + +HostEntry ::= SEQUENCE { + hostAddress OCTET STRING, + hostCreationOrder Integer32, + hostIndex Integer32, + hostInPkts Counter32, + hostOutPkts Counter32, + hostInOctets Counter32, + hostOutOctets Counter32, + hostOutErrors Counter32, + hostOutBroadcastPkts Counter32, + hostOutMulticastPkts Counter32 +} + +hostAddress OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The physical address of this host." + ::= { hostEntry 1 } + +hostCreationOrder OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "An index that defines the relative ordering of + the creation time of hosts captured for a + particular hostControlEntry. This index shall + be between 1 and N, where N is the value of + the associated hostControlTableSize. The ordering + of the indexes is based on the order of each entry's + insertion into the table, in which entries added earlier + have a lower index value than entries added later. + + It is important to note that the order for a + particular entry may change as an (earlier) entry + is deleted from the table. Because this order may + change, management stations should make use of the + hostControlLastDeleteTime variable in the + hostControlEntry associated with the relevant + portion of the hostTable. By observing + this variable, the management station may detect + the circumstances where a previous association + between a value of hostCreationOrder + and a hostEntry may no longer hold." + ::= { hostEntry 2 } + +hostIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The set of collected host statistics of which + this entry is a part. The set of hosts + identified by a particular value of this + index is associated with the hostControlEntry + as identified by the same value of hostControlIndex." + ::= { hostEntry 3 } + +hostInPkts OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of good packets transmitted to this + address since it was added to the hostTable." + ::= { hostEntry 4 } + +hostOutPkts OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of packets, including bad packets, transmitted + by this address since it was added to the hostTable." + ::= { hostEntry 5 } + +hostInOctets OBJECT-TYPE + SYNTAX Counter32 + UNITS "Octets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of octets transmitted to this address since + it was added to the hostTable (excluding framing + bits but including FCS octets), except for those + octets in bad packets." + ::= { hostEntry 6 } + +hostOutOctets OBJECT-TYPE + SYNTAX Counter32 + UNITS "Octets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of octets transmitted by this address since + it was added to the hostTable (excluding framing + bits but including FCS octets), including those + octets in bad packets." + ::= { hostEntry 7 } + +hostOutErrors OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of bad packets transmitted by this address + since this host was added to the hostTable." + ::= { hostEntry 8 } + +hostOutBroadcastPkts OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of good packets transmitted by this + address that were directed to the broadcast address + since this host was added to the hostTable." + ::= { hostEntry 9 } + +hostOutMulticastPkts OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of good packets transmitted by this + address that were directed to a multicast address + since this host was added to the hostTable. + Note that this number does not include packets + directed to the broadcast address." + ::= { hostEntry 10 } + +-- host Time Table + +hostTimeTable OBJECT-TYPE + SYNTAX SEQUENCE OF HostTimeEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of time-ordered host table entries." + ::= { hosts 3 } + +hostTimeEntry OBJECT-TYPE + SYNTAX HostTimeEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A collection of statistics for a particular host that has + been discovered on an interface of this device. This + collection includes the relative ordering of the creation + time of this object. For example, an instance of the + hostTimeOutBroadcastPkts object might be named + hostTimeOutBroadcastPkts.1.687" + INDEX { hostTimeIndex, hostTimeCreationOrder } + ::= { hostTimeTable 1 } + +HostTimeEntry ::= SEQUENCE { + hostTimeAddress OCTET STRING, + hostTimeCreationOrder Integer32, + hostTimeIndex Integer32, + hostTimeInPkts Counter32, + hostTimeOutPkts Counter32, + hostTimeInOctets Counter32, + hostTimeOutOctets Counter32, + hostTimeOutErrors Counter32, + hostTimeOutBroadcastPkts Counter32, + hostTimeOutMulticastPkts Counter32 +} + +hostTimeAddress OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The physical address of this host." + ::= { hostTimeEntry 1 } + +hostTimeCreationOrder OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "An index that uniquely identifies an entry in + the hostTime table among those entries associated + with the same hostControlEntry. This index shall + be between 1 and N, where N is the value of + the associated hostControlTableSize. The ordering + of the indexes is based on the order of each entry's + insertion into the table, in which entries added earlier + have a lower index value than entries added later. + Thus the management station has the ability to + learn of new entries added to this table without + downloading the entire table. + + It is important to note that the index for a + particular entry may change as an (earlier) entry + is deleted from the table. Because this order may + change, management stations should make use of the + hostControlLastDeleteTime variable in the + hostControlEntry associated with the relevant + portion of the hostTimeTable. By observing + this variable, the management station may detect + the circumstances where a download of the table + may have missed entries, and where a previous + association between a value of hostTimeCreationOrder + and a hostTimeEntry may no longer hold." + ::= { hostTimeEntry 2 } + +hostTimeIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The set of collected host statistics of which + this entry is a part. The set of hosts + identified by a particular value of this + index is associated with the hostControlEntry + as identified by the same value of hostControlIndex." + ::= { hostTimeEntry 3 } + +hostTimeInPkts OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of good packets transmitted to this + address since it was added to the hostTimeTable." + ::= { hostTimeEntry 4 } + +hostTimeOutPkts OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of packets, including bad packets, transmitted + by this address since it was added to the hostTimeTable." + ::= { hostTimeEntry 5 } + +hostTimeInOctets OBJECT-TYPE + SYNTAX Counter32 + UNITS "Octets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of octets transmitted to this address since + it was added to the hostTimeTable (excluding framing + bits but including FCS octets), except for those + octets in bad packets." + ::= { hostTimeEntry 6 } + +hostTimeOutOctets OBJECT-TYPE + SYNTAX Counter32 + UNITS "Octets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of octets transmitted by this address since + it was added to the hostTimeTable (excluding framing + bits but including FCS octets), including those + octets in bad packets." + ::= { hostTimeEntry 7 } + +hostTimeOutErrors OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of bad packets transmitted by this address + since this host was added to the hostTimeTable." + ::= { hostTimeEntry 8 } + +hostTimeOutBroadcastPkts OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of good packets transmitted by this + address that were directed to the broadcast address + since this host was added to the hostTimeTable." + ::= { hostTimeEntry 9 } + +hostTimeOutMulticastPkts OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of good packets transmitted by this + address that were directed to a multicast address + since this host was added to the hostTimeTable. + Note that this number does not include packets directed + to the broadcast address." + ::= { hostTimeEntry 10 } + +-- The Host Top "N" Group + +-- Implementation of the Host Top N group is optional. The Host Top N +-- group requires the implementation of the host group. +-- Consult the MODULE-COMPLIANCE macro for the authoritative +-- conformance information for this MIB. +-- +-- The Host Top N group is used to prepare reports that describe +-- the hosts that top a list ordered by one of their statistics. +-- The available statistics are samples of one of their +-- base statistics, over an interval specified by the management +-- station. Thus, these statistics are rate based. The management +-- station also selects how many such hosts are reported. + +-- The hostTopNControlTable is used to initiate the generation of +-- such a report. The management station may select the parameters +-- of such a report, such as which interface, which statistic, +-- how many hosts, and the start and stop times of the sampling. +-- When the report is prepared, entries are created in the +-- hostTopNTable associated with the relevant hostTopNControlEntry. +-- These entries are static for each report after it has been +-- prepared. + +hostTopNControlTable OBJECT-TYPE + SYNTAX SEQUENCE OF HostTopNControlEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of top N host control entries." + ::= { hostTopN 1 } + +hostTopNControlEntry OBJECT-TYPE + SYNTAX HostTopNControlEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A set of parameters that control the creation of a report + of the top N hosts according to several metrics. For + example, an instance of the hostTopNDuration object might + be named hostTopNDuration.3" + INDEX { hostTopNControlIndex } + ::= { hostTopNControlTable 1 } + +HostTopNControlEntry ::= SEQUENCE { + hostTopNControlIndex Integer32, + hostTopNHostIndex Integer32, + hostTopNRateBase INTEGER, + hostTopNTimeRemaining Integer32, + hostTopNDuration Integer32, + hostTopNRequestedSize Integer32, + hostTopNGrantedSize Integer32, + hostTopNStartTime TimeTicks, + hostTopNOwner OwnerString, + hostTopNStatus EntryStatus +} + +hostTopNControlIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "An index that uniquely identifies an entry + in the hostTopNControl table. Each such + entry defines one top N report prepared for + one interface." + ::= { hostTopNControlEntry 1 } + +hostTopNHostIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The host table for which a top N report will be prepared + on behalf of this entry. The host table identified by a + particular value of this index is associated with the same + host table as identified by the same value of + hostIndex. + + This object may not be modified if the associated + hostTopNStatus object is equal to valid(1)." + ::= { hostTopNControlEntry 2 } + +hostTopNRateBase OBJECT-TYPE + SYNTAX INTEGER { + hostTopNInPkts(1), + hostTopNOutPkts(2), + hostTopNInOctets(3), + hostTopNOutOctets(4), + hostTopNOutErrors(5), + hostTopNOutBroadcastPkts(6), + hostTopNOutMulticastPkts(7) + } + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The variable for each host that the hostTopNRate + variable is based upon. + + This object may not be modified if the associated + hostTopNStatus object is equal to valid(1)." + ::= { hostTopNControlEntry 3 } + +hostTopNTimeRemaining OBJECT-TYPE + SYNTAX Integer32 + UNITS "Seconds" + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The number of seconds left in the report currently being + collected. When this object is modified by the management + station, a new collection is started, possibly aborting + a currently running report. The new value is used + as the requested duration of this report, which is + loaded into the associated hostTopNDuration object. + + When this object is set to a non-zero value, any + associated hostTopNEntries shall be made + inaccessible by the monitor. While the value of this + object is non-zero, it decrements by one per second until + it reaches zero. During this time, all associated + hostTopNEntries shall remain inaccessible. At the time + that this object decrements to zero, the report is made + accessible in the hostTopNTable. Thus, the hostTopN + table needs to be created only at the end of the collection + interval." + DEFVAL { 0 } + ::= { hostTopNControlEntry 4 } + +hostTopNDuration OBJECT-TYPE + SYNTAX Integer32 + UNITS "Seconds" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of seconds that this report has collected + during the last sampling interval, or if this + report is currently being collected, the number + of seconds that this report is being collected + during this sampling interval. + + When the associated hostTopNTimeRemaining object is set, + this object shall be set by the probe to the same value + and shall not be modified until the next time + the hostTopNTimeRemaining is set. + + This value shall be zero if no reports have been + requested for this hostTopNControlEntry." + DEFVAL { 0 } + ::= { hostTopNControlEntry 5 } + +hostTopNRequestedSize OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The maximum number of hosts requested for the top N + table. + + When this object is created or modified, the probe + should set hostTopNGrantedSize as closely to this + object as is possible for the particular probe + implementation and available resources." + DEFVAL { 10 } + ::= { hostTopNControlEntry 6 } + +hostTopNGrantedSize OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The maximum number of hosts in the top N table. + + When the associated hostTopNRequestedSize object is + created or modified, the probe should set this + object as closely to the requested value as is possible + for the particular implementation and available + resources. The probe must not lower this value except + as a result of a set to the associated + hostTopNRequestedSize object. + + Hosts with the highest value of hostTopNRate shall be + placed in this table in decreasing order of this rate + until there is no more room or until there are no more + hosts." + ::= { hostTopNControlEntry 7 } + +hostTopNStartTime OBJECT-TYPE + SYNTAX TimeTicks + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime when this top N report was + last started. In other words, this is the time that + the associated hostTopNTimeRemaining object was + modified to start the requested report." + ::= { hostTopNControlEntry 8 } + +hostTopNOwner OBJECT-TYPE + SYNTAX OwnerString + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The entity that configured this entry and is therefore + using the resources assigned to it." + ::= { hostTopNControlEntry 9 } + +hostTopNStatus OBJECT-TYPE + SYNTAX EntryStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this hostTopNControl entry. + + If this object is not equal to valid(1), all associated + hostTopNEntries shall be deleted by the agent." + ::= { hostTopNControlEntry 10 } + +hostTopNTable OBJECT-TYPE + SYNTAX SEQUENCE OF HostTopNEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of top N host entries." + ::= { hostTopN 2 } + +hostTopNEntry OBJECT-TYPE + SYNTAX HostTopNEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A set of statistics for a host that is part of a top N + report. For example, an instance of the hostTopNRate + object might be named hostTopNRate.3.10" + INDEX { hostTopNReport, hostTopNIndex } + ::= { hostTopNTable 1 } + +HostTopNEntry ::= SEQUENCE { + hostTopNReport Integer32, + hostTopNIndex Integer32, + hostTopNAddress OCTET STRING, + hostTopNRate Integer32 +} + +hostTopNReport OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "This object identifies the top N report of which + this entry is a part. The set of hosts + identified by a particular value of this + object is part of the same report as identified + by the same value of the hostTopNControlIndex object." + ::= { hostTopNEntry 1 } + +hostTopNIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "An index that uniquely identifies an entry in + the hostTopN table among those in the same report. + This index is between 1 and N, where N is the + number of entries in this table. Increasing values + of hostTopNIndex shall be assigned to entries with + decreasing values of hostTopNRate until index N + is assigned to the entry with the lowest value of + hostTopNRate or there are no more hostTopNEntries." + ::= { hostTopNEntry 2 } + +hostTopNAddress OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The physical address of this host." + ::= { hostTopNEntry 3 } + +hostTopNRate OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The amount of change in the selected variable + during this sampling interval. The selected + variable is this host's instance of the object + selected by hostTopNRateBase." + ::= { hostTopNEntry 4 } + +-- The Matrix Group + +-- Implementation of the Matrix group is optional. +-- Consult the MODULE-COMPLIANCE macro for the authoritative +-- conformance information for this MIB. +-- +-- The Matrix group consists of the matrixControlTable, matrixSDTable +-- and the matrixDSTable. These tables store statistics for a +-- particular conversation between two addresses. As the device +-- detects a new conversation, including those to a non-unicast +-- address, it creates a new entry in both of the matrix tables. +-- It must only create new entries based on information +-- received in good packets. If the monitoring device finds +-- itself short of resources, it may delete entries as needed. +-- It is suggested that the device delete the least recently used +-- entries first. + +matrixControlTable OBJECT-TYPE + SYNTAX SEQUENCE OF MatrixControlEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of information entries for the + traffic matrix on each interface." + ::= { matrix 1 } + +matrixControlEntry OBJECT-TYPE + SYNTAX MatrixControlEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "Information about a traffic matrix on a particular + interface. For example, an instance of the + matrixControlLastDeleteTime object might be named + matrixControlLastDeleteTime.1" + INDEX { matrixControlIndex } + ::= { matrixControlTable 1 } + +MatrixControlEntry ::= SEQUENCE { + matrixControlIndex Integer32, + matrixControlDataSource OBJECT IDENTIFIER, + matrixControlTableSize Integer32, + matrixControlLastDeleteTime TimeTicks, + matrixControlOwner OwnerString, + matrixControlStatus EntryStatus +} + +matrixControlIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "An index that uniquely identifies an entry in the + matrixControl table. Each such entry defines + a function that discovers conversations on a particular + interface and places statistics about them in the + matrixSDTable and the matrixDSTable on behalf of this + matrixControlEntry." + ::= { matrixControlEntry 1 } + +matrixControlDataSource OBJECT-TYPE + SYNTAX OBJECT IDENTIFIER + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "This object identifies the source of + the data from which this entry creates a traffic matrix. + This source can be any interface on this device. In + order to identify a particular interface, this object + shall identify the instance of the ifIndex object, + defined in RFC 2233 [17], for the desired + interface. For example, if an entry were to receive data + from interface #1, this object would be set to ifIndex.1. + + The statistics in this group reflect all packets + on the local network segment attached to the identified + interface. + + An agent may or may not be able to tell if fundamental + changes to the media of the interface have occurred and + necessitate an invalidation of this entry. For example, a + hot-pluggable ethernet card could be pulled out and replaced + by a token-ring card. In such a case, if the agent has such + knowledge of the change, it is recommended that it + invalidate this entry. + + This object may not be modified if the associated + matrixControlStatus object is equal to valid(1)." + ::= { matrixControlEntry 2 } + +matrixControlTableSize OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of matrixSDEntries in the matrixSDTable + for this interface. This must also be the value of + the number of entries in the matrixDSTable for this + interface." + ::= { matrixControlEntry 3 } + +matrixControlLastDeleteTime OBJECT-TYPE + SYNTAX TimeTicks + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime when the last entry + was deleted from the portion of the matrixSDTable + or matrixDSTable associated with this matrixControlEntry. + If no deletions have occurred, this value shall be + zero." + ::= { matrixControlEntry 4 } + +matrixControlOwner OBJECT-TYPE + SYNTAX OwnerString + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The entity that configured this entry and is therefore + using the resources assigned to it." + ::= { matrixControlEntry 5 } + +matrixControlStatus OBJECT-TYPE + SYNTAX EntryStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this matrixControl entry. + If this object is not equal to valid(1), all associated + entries in the matrixSDTable and the matrixDSTable + shall be deleted by the agent." + ::= { matrixControlEntry 6 } + +matrixSDTable OBJECT-TYPE + SYNTAX SEQUENCE OF MatrixSDEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of traffic matrix entries indexed by + source and destination MAC address." + ::= { matrix 2 } + +matrixSDEntry OBJECT-TYPE + SYNTAX MatrixSDEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A collection of statistics for communications between + two addresses on a particular interface. For example, + an instance of the matrixSDPkts object might be named + matrixSDPkts.1.6.8.0.32.27.3.176.6.8.0.32.10.8.113" + INDEX { matrixSDIndex, + matrixSDSourceAddress, matrixSDDestAddress } + ::= { matrixSDTable 1 } + +MatrixSDEntry ::= SEQUENCE { + matrixSDSourceAddress OCTET STRING, + matrixSDDestAddress OCTET STRING, + matrixSDIndex Integer32, + matrixSDPkts Counter32, + matrixSDOctets Counter32, + matrixSDErrors Counter32 +} + +matrixSDSourceAddress OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The source physical address." + ::= { matrixSDEntry 1 } + +matrixSDDestAddress OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The destination physical address." + ::= { matrixSDEntry 2 } + +matrixSDIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The set of collected matrix statistics of which + this entry is a part. The set of matrix statistics + identified by a particular value of this index + is associated with the same matrixControlEntry + as identified by the same value of matrixControlIndex." + ::= { matrixSDEntry 3 } + +matrixSDPkts OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of packets transmitted from the source + address to the destination address (this number includes + bad packets)." + ::= { matrixSDEntry 4 } + +matrixSDOctets OBJECT-TYPE + SYNTAX Counter32 + UNITS "Octets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of octets (excluding framing bits but + including FCS octets) contained in all packets + transmitted from the source address to the + destination address." + ::= { matrixSDEntry 5 } + +matrixSDErrors OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of bad packets transmitted from + the source address to the destination address." + ::= { matrixSDEntry 6 } + +-- Traffic matrix tables from destination to source + +matrixDSTable OBJECT-TYPE + SYNTAX SEQUENCE OF MatrixDSEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of traffic matrix entries indexed by + destination and source MAC address." + ::= { matrix 3 } + +matrixDSEntry OBJECT-TYPE + SYNTAX MatrixDSEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A collection of statistics for communications between + two addresses on a particular interface. For example, + an instance of the matrixSDPkts object might be named + matrixSDPkts.1.6.8.0.32.10.8.113.6.8.0.32.27.3.176" + INDEX { matrixDSIndex, + matrixDSDestAddress, matrixDSSourceAddress } + ::= { matrixDSTable 1 } + +MatrixDSEntry ::= SEQUENCE { + matrixDSSourceAddress OCTET STRING, + matrixDSDestAddress OCTET STRING, + matrixDSIndex Integer32, + matrixDSPkts Counter32, + matrixDSOctets Counter32, + matrixDSErrors Counter32 +} + +matrixDSSourceAddress OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The source physical address." + ::= { matrixDSEntry 1 } + +matrixDSDestAddress OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The destination physical address." + ::= { matrixDSEntry 2 } + +matrixDSIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The set of collected matrix statistics of which + this entry is a part. The set of matrix statistics + identified by a particular value of this index + is associated with the same matrixControlEntry + as identified by the same value of matrixControlIndex." + ::= { matrixDSEntry 3 } + +matrixDSPkts OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of packets transmitted from the source + address to the destination address (this number includes + bad packets)." + ::= { matrixDSEntry 4 } + +matrixDSOctets OBJECT-TYPE + SYNTAX Counter32 + UNITS "Octets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of octets (excluding framing bits + but including FCS octets) contained in all packets + transmitted from the source address to the + destination address." + ::= { matrixDSEntry 5 } + +matrixDSErrors OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of bad packets transmitted from + the source address to the destination address." + ::= { matrixDSEntry 6 } + +-- The Filter Group + +-- Implementation of the Filter group is optional. +-- Consult the MODULE-COMPLIANCE macro for the authoritative +-- conformance information for this MIB. +-- +-- The Filter group allows packets to be captured with an +-- arbitrary filter expression. A logical data and +-- event stream or "channel" is formed by the packets +-- that match the filter expression. +-- +-- This filter mechanism allows the creation of an arbitrary +-- logical expression with which to filter packets. Each +-- filter associated with a channel is OR'ed with the others. +-- Within a filter, any bits checked in the data and status are +-- AND'ed with respect to other bits in the same filter. The +-- NotMask also allows for checking for inequality. Finally, +-- the channelAcceptType object allows for inversion of the +-- whole equation. +-- +-- If a management station wishes to receive a trap to alert it +-- that new packets have been captured and are available for +-- download, it is recommended that it set up an alarm entry that +-- monitors the value of the relevant channelMatches instance. +-- +-- The channel can be turned on or off, and can also +-- generate events when packets pass through it. + +filterTable OBJECT-TYPE + SYNTAX SEQUENCE OF FilterEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of packet filter entries." + ::= { filter 1 } + +filterEntry OBJECT-TYPE + SYNTAX FilterEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A set of parameters for a packet filter applied on a + particular interface. As an example, an instance of the + filterPktData object might be named filterPktData.12" + INDEX { filterIndex } + ::= { filterTable 1 } + +FilterEntry ::= SEQUENCE { + filterIndex Integer32, + filterChannelIndex Integer32, + filterPktDataOffset Integer32, + filterPktData OCTET STRING, + filterPktDataMask OCTET STRING, + filterPktDataNotMask OCTET STRING, + filterPktStatus Integer32, + filterPktStatusMask Integer32, + filterPktStatusNotMask Integer32, + filterOwner OwnerString, + filterStatus EntryStatus +} + +filterIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "An index that uniquely identifies an entry + in the filter table. Each such entry defines + one filter that is to be applied to every packet + received on an interface." + ::= { filterEntry 1 } + +filterChannelIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "This object identifies the channel of which this filter + is a part. The filters identified by a particular value + of this object are associated with the same channel as + identified by the same value of the channelIndex object." + ::= { filterEntry 2 } + +filterPktDataOffset OBJECT-TYPE + SYNTAX Integer32 + UNITS "Octets" + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The offset from the beginning of each packet where + a match of packet data will be attempted. This offset + is measured from the point in the physical layer + packet after the framing bits, if any. For example, + in an Ethernet frame, this point is at the beginning of + the destination MAC address. + + This object may not be modified if the associated + filterStatus object is equal to valid(1)." + DEFVAL { 0 } + + ::= { filterEntry 3 } + +filterPktData OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The data that is to be matched with the input packet. + For each packet received, this filter and the accompanying + filterPktDataMask and filterPktDataNotMask will be + adjusted for the offset. The only bits relevant to this + match algorithm are those that have the corresponding + filterPktDataMask bit equal to one. The following three + rules are then applied to every packet: + + (1) If the packet is too short and does not have data + corresponding to part of the filterPktData, the packet + will fail this data match. + + (2) For each relevant bit from the packet with the + corresponding filterPktDataNotMask bit set to zero, if + the bit from the packet is not equal to the corresponding + bit from the filterPktData, then the packet will fail + this data match. + + (3) If for every relevant bit from the packet with the + corresponding filterPktDataNotMask bit set to one, the + bit from the packet is equal to the corresponding bit + from the filterPktData, then the packet will fail this + data match. + + Any packets that have not failed any of the three matches + above have passed this data match. In particular, a zero + length filter will match any packet. + + This object may not be modified if the associated + filterStatus object is equal to valid(1)." + ::= { filterEntry 4 } + +filterPktDataMask OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The mask that is applied to the match process. + After adjusting this mask for the offset, only those + bits in the received packet that correspond to bits set + in this mask are relevant for further processing by the + match algorithm. The offset is applied to filterPktDataMask + in the same way it is applied to the filter. For the + purposes of the matching algorithm, if the associated + filterPktData object is longer than this mask, this mask is + conceptually extended with '1' bits until it reaches the + length of the filterPktData object. + + This object may not be modified if the associated + filterStatus object is equal to valid(1)." + ::= { filterEntry 5 } + +filterPktDataNotMask OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The inversion mask that is applied to the match + process. After adjusting this mask for the offset, + those relevant bits in the received packet that correspond + to bits cleared in this mask must all be equal to their + corresponding bits in the filterPktData object for the packet + to be accepted. In addition, at least one of those relevant + bits in the received packet that correspond to bits set in + this mask must be different to its corresponding bit in the + filterPktData object. + + For the purposes of the matching algorithm, if the associated + filterPktData object is longer than this mask, this mask is + conceptually extended with '0' bits until it reaches the + length of the filterPktData object. + + This object may not be modified if the associated + filterStatus object is equal to valid(1)." + ::= { filterEntry 6 } + +filterPktStatus OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status that is to be matched with the input packet. + The only bits relevant to this match algorithm are those that + have the corresponding filterPktStatusMask bit equal to one. + The following two rules are then applied to every packet: + + (1) For each relevant bit from the packet status with the + corresponding filterPktStatusNotMask bit set to zero, if + the bit from the packet status is not equal to the + corresponding bit from the filterPktStatus, then the + packet will fail this status match. + + (2) If for every relevant bit from the packet status with the + corresponding filterPktStatusNotMask bit set to one, the + bit from the packet status is equal to the corresponding + bit from the filterPktStatus, then the packet will fail + this status match. + + Any packets that have not failed either of the two matches + above have passed this status match. In particular, a zero + length status filter will match any packet's status. + + The value of the packet status is a sum. This sum + initially takes the value zero. Then, for each + error, E, that has been discovered in this packet, + 2 raised to a value representing E is added to the sum. + The errors and the bits that represent them are dependent + on the media type of the interface that this channel + is receiving packets from. + + The errors defined for a packet captured off of an + Ethernet interface are as follows: + + bit # Error + 0 Packet is longer than 1518 octets + 1 Packet is shorter than 64 octets + 2 Packet experienced a CRC or Alignment error + + For example, an Ethernet fragment would have a + value of 6 (2^1 + 2^2). + + As this MIB is expanded to new media types, this object + will have other media-specific errors defined. + + For the purposes of this status matching algorithm, if the + packet status is longer than this filterPktStatus object, + this object is conceptually extended with '0' bits until it + reaches the size of the packet status. + + This object may not be modified if the associated + filterStatus object is equal to valid(1)." + ::= { filterEntry 7 } + +filterPktStatusMask OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The mask that is applied to the status match process. + Only those bits in the received packet that correspond to + bits set in this mask are relevant for further processing + by the status match algorithm. For the purposes + of the matching algorithm, if the associated filterPktStatus + object is longer than this mask, this mask is conceptually + extended with '1' bits until it reaches the size of the + filterPktStatus. In addition, if a packet status is longer + than this mask, this mask is conceptually extended with '0' + bits until it reaches the size of the packet status. + + This object may not be modified if the associated + filterStatus object is equal to valid(1)." + ::= { filterEntry 8 } + +filterPktStatusNotMask OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The inversion mask that is applied to the status match + process. Those relevant bits in the received packet status + that correspond to bits cleared in this mask must all be + equal to their corresponding bits in the filterPktStatus + object for the packet to be accepted. In addition, at least + one of those relevant bits in the received packet status + that correspond to bits set in this mask must be different + to its corresponding bit in the filterPktStatus object for + the packet to be accepted. + + For the purposes of the matching algorithm, if the associated + filterPktStatus object or a packet status is longer than this + mask, this mask is conceptually extended with '0' bits until + it reaches the longer of the lengths of the filterPktStatus + object and the packet status. + + This object may not be modified if the associated + filterStatus object is equal to valid(1)." + ::= { filterEntry 9 } + +filterOwner OBJECT-TYPE + SYNTAX OwnerString + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The entity that configured this entry and is therefore + using the resources assigned to it." + ::= { filterEntry 10 } + +filterStatus OBJECT-TYPE + SYNTAX EntryStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this filter entry." + ::= { filterEntry 11 } + +channelTable OBJECT-TYPE + SYNTAX SEQUENCE OF ChannelEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of packet channel entries." + ::= { filter 2 } + +channelEntry OBJECT-TYPE + SYNTAX ChannelEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A set of parameters for a packet channel applied on a + particular interface. As an example, an instance of the + channelMatches object might be named channelMatches.3" + INDEX { channelIndex } + ::= { channelTable 1 } + +ChannelEntry ::= SEQUENCE { + channelIndex Integer32, + channelIfIndex Integer32, + channelAcceptType INTEGER, + channelDataControl INTEGER, + channelTurnOnEventIndex Integer32, + channelTurnOffEventIndex Integer32, + channelEventIndex Integer32, + channelEventStatus INTEGER, + channelMatches Counter32, + channelDescription DisplayString, + channelOwner OwnerString, + channelStatus EntryStatus +} + +channelIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "An index that uniquely identifies an entry in the channel + table. Each such entry defines one channel, a logical + data and event stream. + + It is suggested that before creating a channel, an + application should scan all instances of the + filterChannelIndex object to make sure that there are no + pre-existing filters that would be inadvertently be linked + to the channel." + ::= { channelEntry 1 } + +channelIfIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The value of this object uniquely identifies the + interface on this remote network monitoring device to which + the associated filters are applied to allow data into this + channel. The interface identified by a particular value + of this object is the same interface as identified by the + same value of the ifIndex object, defined in RFC 2233 [17]. + + The filters in this group are applied to all packets on + the local network segment attached to the identified + interface. + + An agent may or may not be able to tell if fundamental + changes to the media of the interface have occurred and + necessitate an invalidation of this entry. For example, a + hot-pluggable ethernet card could be pulled out and replaced + by a token-ring card. In such a case, if the agent has such + knowledge of the change, it is recommended that it + invalidate this entry. + + This object may not be modified if the associated + channelStatus object is equal to valid(1)." + ::= { channelEntry 2 } + +channelAcceptType OBJECT-TYPE + SYNTAX INTEGER { + acceptMatched(1), + acceptFailed(2) + } + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "This object controls the action of the filters + associated with this channel. If this object is equal + to acceptMatched(1), packets will be accepted to this + channel if they are accepted by both the packet data and + packet status matches of an associated filter. If + this object is equal to acceptFailed(2), packets will + be accepted to this channel only if they fail either + the packet data match or the packet status match of + each of the associated filters. + + In particular, a channel with no associated filters will + match no packets if set to acceptMatched(1) case and will + match all packets in the acceptFailed(2) case. + + This object may not be modified if the associated + channelStatus object is equal to valid(1)." + ::= { channelEntry 3 } + +channelDataControl OBJECT-TYPE + SYNTAX INTEGER { + on(1), + off(2) + } + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "This object controls the flow of data through this channel. + If this object is on(1), data, status and events flow + through this channel. If this object is off(2), data, + status and events will not flow through this channel." + DEFVAL { off } + ::= { channelEntry 4 } + +channelTurnOnEventIndex OBJECT-TYPE + SYNTAX Integer32 (0..65535) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The value of this object identifies the event + that is configured to turn the associated + channelDataControl from off to on when the event is + generated. The event identified by a particular value + of this object is the same event as identified by the + same value of the eventIndex object. If there is no + corresponding entry in the eventTable, then no + association exists. In fact, if no event is intended + for this channel, channelTurnOnEventIndex must be + set to zero, a non-existent event index. + + This object may not be modified if the associated + channelStatus object is equal to valid(1)." + ::= { channelEntry 5 } + +channelTurnOffEventIndex OBJECT-TYPE + SYNTAX Integer32 (0..65535) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The value of this object identifies the event + that is configured to turn the associated + channelDataControl from on to off when the event is + generated. The event identified by a particular value + of this object is the same event as identified by the + same value of the eventIndex object. If there is no + corresponding entry in the eventTable, then no + association exists. In fact, if no event is intended + for this channel, channelTurnOffEventIndex must be + set to zero, a non-existent event index. + + This object may not be modified if the associated + channelStatus object is equal to valid(1)." + ::= { channelEntry 6 } + +channelEventIndex OBJECT-TYPE + SYNTAX Integer32 (0..65535) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The value of this object identifies the event + that is configured to be generated when the + associated channelDataControl is on and a packet + is matched. The event identified by a particular value + of this object is the same event as identified by the + same value of the eventIndex object. If there is no + corresponding entry in the eventTable, then no + association exists. In fact, if no event is intended + for this channel, channelEventIndex must be + set to zero, a non-existent event index. + + This object may not be modified if the associated + channelStatus object is equal to valid(1)." + ::= { channelEntry 7 } + +channelEventStatus OBJECT-TYPE + SYNTAX INTEGER { + eventReady(1), + eventFired(2), + eventAlwaysReady(3) + } + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The event status of this channel. + + If this channel is configured to generate events + when packets are matched, a means of controlling + the flow of those events is often needed. When + this object is equal to eventReady(1), a single + event may be generated, after which this object + will be set by the probe to eventFired(2). While + in the eventFired(2) state, no events will be + generated until the object is modified to + eventReady(1) (or eventAlwaysReady(3)). The + management station can thus easily respond to a + notification of an event by re-enabling this object. + + If the management station wishes to disable this + flow control and allow events to be generated + at will, this object may be set to + eventAlwaysReady(3). Disabling the flow control + is discouraged as it can result in high network + traffic or other performance problems." + DEFVAL { eventReady } + ::= { channelEntry 8 } + +channelMatches OBJECT-TYPE + SYNTAX Counter32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of times this channel has matched a packet. + Note that this object is updated even when + channelDataControl is set to off." + ::= { channelEntry 9 } + +channelDescription OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..127)) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "A comment describing this channel." + ::= { channelEntry 10 } + +channelOwner OBJECT-TYPE + SYNTAX OwnerString + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The entity that configured this entry and is therefore + using the resources assigned to it." + ::= { channelEntry 11 } + +channelStatus OBJECT-TYPE + SYNTAX EntryStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this channel entry." + ::= { channelEntry 12 } + +-- The Packet Capture Group + +-- Implementation of the Packet Capture group is optional. The Packet +-- Capture Group requires implementation of the Filter Group. +-- Consult the MODULE-COMPLIANCE macro for the authoritative +-- conformance information for this MIB. +-- +-- The Packet Capture group allows packets to be captured +-- upon a filter match. The bufferControlTable controls +-- the captured packets output from a channel that is +-- associated with it. The captured packets are placed +-- in entries in the captureBufferTable. These entries are +-- associated with the bufferControlEntry on whose behalf they +-- were stored. + +bufferControlTable OBJECT-TYPE + SYNTAX SEQUENCE OF BufferControlEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of buffers control entries." + ::= { capture 1 } + +bufferControlEntry OBJECT-TYPE + SYNTAX BufferControlEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A set of parameters that control the collection of a stream + of packets that have matched filters. As an example, an + instance of the bufferControlCaptureSliceSize object might + be named bufferControlCaptureSliceSize.3" + + INDEX { bufferControlIndex } + ::= { bufferControlTable 1 } + +BufferControlEntry ::= SEQUENCE { + bufferControlIndex Integer32, + bufferControlChannelIndex Integer32, + bufferControlFullStatus INTEGER, + bufferControlFullAction INTEGER, + bufferControlCaptureSliceSize Integer32, + bufferControlDownloadSliceSize Integer32, + bufferControlDownloadOffset Integer32, + bufferControlMaxOctetsRequested Integer32, + bufferControlMaxOctetsGranted Integer32, + bufferControlCapturedPackets Integer32, + bufferControlTurnOnTime TimeTicks, + bufferControlOwner OwnerString, + bufferControlStatus EntryStatus +} + +bufferControlIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "An index that uniquely identifies an entry + in the bufferControl table. The value of this + index shall never be zero. Each such + entry defines one set of packets that is + captured and controlled by one or more filters." + ::= { bufferControlEntry 1 } + +bufferControlChannelIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "An index that identifies the channel that is the + source of packets for this bufferControl table. + The channel identified by a particular value of this + index is the same as identified by the same value of + the channelIndex object. + + This object may not be modified if the associated + bufferControlStatus object is equal to valid(1)." + ::= { bufferControlEntry 2 } + +bufferControlFullStatus OBJECT-TYPE + SYNTAX INTEGER { + spaceAvailable(1), + full(2) + } + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "This object shows whether the buffer has room to + accept new packets or if it is full. + + If the status is spaceAvailable(1), the buffer is + accepting new packets normally. If the status is + full(2) and the associated bufferControlFullAction + object is wrapWhenFull, the buffer is accepting new + packets by deleting enough of the oldest packets + to make room for new ones as they arrive. Otherwise, + if the status is full(2) and the + bufferControlFullAction object is lockWhenFull, + then the buffer has stopped collecting packets. + + When this object is set to full(2) the probe must + not later set it to spaceAvailable(1) except in the + case of a significant gain in resources such as + an increase of bufferControlOctetsGranted. In + particular, the wrap-mode action of deleting old + packets to make room for newly arrived packets + must not affect the value of this object." + ::= { bufferControlEntry 3 } + +bufferControlFullAction OBJECT-TYPE + SYNTAX INTEGER { + lockWhenFull(1), + wrapWhenFull(2) -- FIFO + } + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "Controls the action of the buffer when it + reaches the full status. When in the lockWhenFull(1) + state and a packet is added to the buffer that + fills the buffer, the bufferControlFullStatus will + be set to full(2) and this buffer will stop capturing + packets." + ::= { bufferControlEntry 4 } + +bufferControlCaptureSliceSize OBJECT-TYPE + SYNTAX Integer32 + UNITS "Octets" + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The maximum number of octets of each packet + that will be saved in this capture buffer. + For example, if a 1500 octet packet is received by + the probe and this object is set to 500, then only + 500 octets of the packet will be stored in the + associated capture buffer. If this variable is set + to 0, the capture buffer will save as many octets + as is possible. + + This object may not be modified if the associated + bufferControlStatus object is equal to valid(1)." + DEFVAL { 100 } + ::= { bufferControlEntry 5 } + +bufferControlDownloadSliceSize OBJECT-TYPE + SYNTAX Integer32 + UNITS "Octets" + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The maximum number of octets of each packet + in this capture buffer that will be returned in + an SNMP retrieval of that packet. For example, + if 500 octets of a packet have been stored in the + associated capture buffer, the associated + bufferControlDownloadOffset is 0, and this + object is set to 100, then the captureBufferPacket + object that contains the packet will contain only + the first 100 octets of the packet. + + A prudent manager will take into account possible + interoperability or fragmentation problems that may + occur if the download slice size is set too large. + In particular, conformant SNMP implementations are not + required to accept messages whose length exceeds 484 + octets, although they are encouraged to support larger + datagrams whenever feasible." + DEFVAL { 100 } + ::= { bufferControlEntry 6 } + +bufferControlDownloadOffset OBJECT-TYPE + SYNTAX Integer32 + UNITS "Octets" + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The offset of the first octet of each packet + in this capture buffer that will be returned in + an SNMP retrieval of that packet. For example, + if 500 octets of a packet have been stored in the + associated capture buffer and this object is set to + 100, then the captureBufferPacket object that + contains the packet will contain bytes starting + 100 octets into the packet." + DEFVAL { 0 } + ::= { bufferControlEntry 7 } + +bufferControlMaxOctetsRequested OBJECT-TYPE + SYNTAX Integer32 + UNITS "Octets" + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The requested maximum number of octets to be + saved in this captureBuffer, including any + implementation-specific overhead. If this variable + is set to -1, the capture buffer will save as many + octets as is possible. + + When this object is created or modified, the probe + should set bufferControlMaxOctetsGranted as closely + to this object as is possible for the particular probe + implementation and available resources. However, if + the object has the special value of -1, the probe + must set bufferControlMaxOctetsGranted to -1." + DEFVAL { -1 } + ::= { bufferControlEntry 8 } + +bufferControlMaxOctetsGranted OBJECT-TYPE + SYNTAX Integer32 + UNITS "Octets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The maximum number of octets that can be + saved in this captureBuffer, including overhead. + If this variable is -1, the capture buffer will save + as many octets as possible. + + When the bufferControlMaxOctetsRequested object is + created or modified, the probe should set this object + as closely to the requested value as is possible for the + particular probe implementation and available resources. + However, if the request object has the special value + of -1, the probe must set this object to -1. + + The probe must not lower this value except as a result of + a modification to the associated + bufferControlMaxOctetsRequested object. + + When this maximum number of octets is reached + and a new packet is to be added to this + capture buffer and the corresponding + bufferControlFullAction is set to wrapWhenFull(2), + enough of the oldest packets associated with this + capture buffer shall be deleted by the agent so + that the new packet can be added. If the corresponding + bufferControlFullAction is set to lockWhenFull(1), + the new packet shall be discarded. In either case, + the probe must set bufferControlFullStatus to + full(2). + + When the value of this object changes to a value less + than the current value, entries are deleted from + the captureBufferTable associated with this + bufferControlEntry. Enough of the + oldest of these captureBufferEntries shall be + deleted by the agent so that the number of octets + used remains less than or equal to the new value of + this object. + + When the value of this object changes to a value greater + than the current value, the number of associated + captureBufferEntries may be allowed to grow." + ::= { bufferControlEntry 9 } + +bufferControlCapturedPackets OBJECT-TYPE + SYNTAX Integer32 + UNITS "Packets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of packets currently in this captureBuffer." + ::= { bufferControlEntry 10 } + +bufferControlTurnOnTime OBJECT-TYPE + SYNTAX TimeTicks + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime when this capture buffer was + first turned on." + ::= { bufferControlEntry 11 } + +bufferControlOwner OBJECT-TYPE + SYNTAX OwnerString + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The entity that configured this entry and is therefore + using the resources assigned to it." + ::= { bufferControlEntry 12 } + +bufferControlStatus OBJECT-TYPE + SYNTAX EntryStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this buffer Control Entry." + ::= { bufferControlEntry 13 } + +captureBufferTable OBJECT-TYPE + SYNTAX SEQUENCE OF CaptureBufferEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of packets captured off of a channel." + ::= { capture 2 } + +captureBufferEntry OBJECT-TYPE + SYNTAX CaptureBufferEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A packet captured off of an attached network. As an + example, an instance of the captureBufferPacketData + object might be named captureBufferPacketData.3.1783" + INDEX { captureBufferControlIndex, captureBufferIndex } + ::= { captureBufferTable 1 } + +CaptureBufferEntry ::= SEQUENCE { + captureBufferControlIndex Integer32, + captureBufferIndex Integer32, + captureBufferPacketID Integer32, + captureBufferPacketData OCTET STRING, + captureBufferPacketLength Integer32, + captureBufferPacketTime Integer32, + captureBufferPacketStatus Integer32 +} + +captureBufferControlIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The index of the bufferControlEntry with which + this packet is associated." + ::= { captureBufferEntry 1 } + +captureBufferIndex OBJECT-TYPE + SYNTAX Integer32 (1..2147483647) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "An index that uniquely identifies an entry + in the captureBuffer table associated with a + particular bufferControlEntry. This index will + start at 1 and increase by one for each new packet + added with the same captureBufferControlIndex. + + Should this value reach 2147483647, the next packet + added with the same captureBufferControlIndex shall + cause this value to wrap around to 1." + ::= { captureBufferEntry 2 } + +captureBufferPacketID OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "An index that describes the order of packets + that are received on a particular interface. + The packetID of a packet captured on an + interface is defined to be greater than the + packetID's of all packets captured previously on + the same interface. As the captureBufferPacketID + object has a maximum positive value of 2^31 - 1, + any captureBufferPacketID object shall have the + value of the associated packet's packetID mod 2^31." + ::= { captureBufferEntry 3 } + +captureBufferPacketData OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The data inside the packet, starting at the beginning + of the packet plus any offset specified in the + associated bufferControlDownloadOffset, including any + link level headers. The length of the data in this object + is the minimum of the length of the captured packet minus + the offset, the length of the associated + bufferControlCaptureSliceSize minus the offset, and the + associated bufferControlDownloadSliceSize. If this minimum + is less than zero, this object shall have a length of zero." + ::= { captureBufferEntry 4 } + +captureBufferPacketLength OBJECT-TYPE + SYNTAX Integer32 + UNITS "Octets" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The actual length (off the wire) of the packet stored + in this entry, including FCS octets." + ::= { captureBufferEntry 5 } + +captureBufferPacketTime OBJECT-TYPE + SYNTAX Integer32 + UNITS "Milliseconds" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The number of milliseconds that had passed since + this capture buffer was first turned on when this + packet was captured." + ::= { captureBufferEntry 6 } + +captureBufferPacketStatus OBJECT-TYPE + SYNTAX Integer32 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "A value which indicates the error status of this packet. + + The value of this object is defined in the same way as + filterPktStatus. The value is a sum. This sum + initially takes the value zero. Then, for each + error, E, that has been discovered in this packet, + 2 raised to a value representing E is added to the sum. + + The errors defined for a packet captured off of an + Ethernet interface are as follows: + + bit # Error + 0 Packet is longer than 1518 octets + 1 Packet is shorter than 64 octets + 2 Packet experienced a CRC or Alignment error + 3 First packet in this capture buffer after + it was detected that some packets were + not processed correctly. + 4 Packet's order in buffer is only approximate + (May only be set for packets sent from + the probe) + + For example, an Ethernet fragment would have a + value of 6 (2^1 + 2^2). + + As this MIB is expanded to new media types, this object + will have other media-specific errors defined." + ::= { captureBufferEntry 7 } + +-- The Event Group + +-- Implementation of the Event group is optional. +-- Consult the MODULE-COMPLIANCE macro for the authoritative +-- conformance information for this MIB. +-- +-- The Event group controls the generation and notification +-- of events from this device. Each entry in the eventTable +-- describes the parameters of the event that can be triggered. +-- Each event entry is fired by an associated condition located +-- elsewhere in the MIB. An event entry may also be associated +-- with a function elsewhere in the MIB that will be executed +-- when the event is generated. For example, a channel may +-- be turned on or off by the firing of an event. +-- +-- Each eventEntry may optionally specify that a log entry +-- be created on its behalf whenever the event occurs. +-- Each entry may also specify that notification should +-- occur by way of SNMP trap messages. In this case, the +-- community for the trap message is given in the associated +-- eventCommunity object. The enterprise and specific trap +-- fields of the trap are determined by the condition that +-- triggered the event. Two traps are defined: risingAlarm and +-- fallingAlarm. If the eventTable is triggered by a condition +-- specified elsewhere, the enterprise and specific trap fields +-- must be specified for traps generated for that condition. + +eventTable OBJECT-TYPE + SYNTAX SEQUENCE OF EventEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of events to be generated." + ::= { event 1 } + +eventEntry OBJECT-TYPE + SYNTAX EventEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A set of parameters that describe an event to be generated + when certain conditions are met. As an example, an instance + of the eventLastTimeSent object might be named + eventLastTimeSent.6" + INDEX { eventIndex } + ::= { eventTable 1 } + +EventEntry ::= SEQUENCE { + eventIndex Integer32, + eventDescription DisplayString, + eventType INTEGER, + eventCommunity OCTET STRING, + eventLastTimeSent TimeTicks, + eventOwner OwnerString, + eventStatus EntryStatus +} + +eventIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "An index that uniquely identifies an entry in the + event table. Each such entry defines one event that + is to be generated when the appropriate conditions + occur." + ::= { eventEntry 1 } + +eventDescription OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..127)) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "A comment describing this event entry." + ::= { eventEntry 2 } + +eventType OBJECT-TYPE + SYNTAX INTEGER { + none(1), + log(2), + snmptrap(3), -- send an SNMP trap + logandtrap(4) + } + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The type of notification that the probe will make + about this event. In the case of log, an entry is + made in the log table for each event. In the case of + snmp-trap, an SNMP trap is sent to one or more + management stations." + ::= { eventEntry 3 } + +eventCommunity OBJECT-TYPE + SYNTAX OCTET STRING (SIZE (0..127)) + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "If an SNMP trap is to be sent, it will be sent to + the SNMP community specified by this octet string." + ::= { eventEntry 4 } + +eventLastTimeSent OBJECT-TYPE + SYNTAX TimeTicks + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime at the time this event + entry last generated an event. If this entry has + not generated any events, this value will be + zero." + ::= { eventEntry 5 } + +eventOwner OBJECT-TYPE + SYNTAX OwnerString + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The entity that configured this entry and is therefore + using the resources assigned to it. + + If this object contains a string starting with 'monitor' + and has associated entries in the log table, all connected + management stations should retrieve those log entries, + as they may have significance to all management stations + connected to this device" + ::= { eventEntry 6 } + +eventStatus OBJECT-TYPE + SYNTAX EntryStatus + MAX-ACCESS read-create + STATUS current + DESCRIPTION + "The status of this event entry. + + If this object is not equal to valid(1), all associated + log entries shall be deleted by the agent." + ::= { eventEntry 7 } + +-- +logTable OBJECT-TYPE + SYNTAX SEQUENCE OF LogEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A list of events that have been logged." + ::= { event 2 } + +logEntry OBJECT-TYPE + SYNTAX LogEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A set of data describing an event that has been + logged. For example, an instance of the logDescription + object might be named logDescription.6.47" + INDEX { logEventIndex, logIndex } + ::= { logTable 1 } + +LogEntry ::= SEQUENCE { + logEventIndex Integer32, + logIndex Integer32, + logTime TimeTicks, + logDescription DisplayString +} + +logEventIndex OBJECT-TYPE + SYNTAX Integer32 (1..65535) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The event entry that generated this log + entry. The log identified by a particular + value of this index is associated with the same + eventEntry as identified by the same value + of eventIndex." + ::= { logEntry 1 } + +logIndex OBJECT-TYPE + SYNTAX Integer32 (1..2147483647) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "An index that uniquely identifies an entry + in the log table amongst those generated by the + same eventEntries. These indexes are + assigned beginning with 1 and increase by one + with each new log entry. The association + between values of logIndex and logEntries + is fixed for the lifetime of each logEntry. + The agent may choose to delete the oldest + instances of logEntry as required because of + lack of memory. It is an implementation-specific + matter as to when this deletion may occur." + ::= { logEntry 2 } + +logTime OBJECT-TYPE + SYNTAX TimeTicks + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "The value of sysUpTime when this log entry was created." + ::= { logEntry 3 } + +logDescription OBJECT-TYPE + SYNTAX DisplayString (SIZE (0..255)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "An implementation dependent description of the + event that activated this log entry." + ::= { logEntry 4 } + +-- Remote Network Monitoring Traps + +rmonEventsV2 OBJECT-IDENTITY + STATUS current + DESCRIPTION "Definition point for RMON notifications." + ::= { rmon 0 } + +risingAlarm NOTIFICATION-TYPE + OBJECTS { alarmIndex, alarmVariable, alarmSampleType, + alarmValue, alarmRisingThreshold } + STATUS current + DESCRIPTION + "The SNMP trap that is generated when an alarm + entry crosses its rising threshold and generates + an event that is configured for sending SNMP + traps." + ::= { rmonEventsV2 1 } + +fallingAlarm NOTIFICATION-TYPE + OBJECTS { alarmIndex, alarmVariable, alarmSampleType, + alarmValue, alarmFallingThreshold } + STATUS current + DESCRIPTION + "The SNMP trap that is generated when an alarm + entry crosses its falling threshold and generates + an event that is configured for sending SNMP + traps." + ::= { rmonEventsV2 2 } + +-- Conformance information + +rmonCompliances OBJECT IDENTIFIER ::= { rmonConformance 9 } +rmonGroups OBJECT IDENTIFIER ::= { rmonConformance 10 } + +-- Compliance Statements +rmonCompliance MODULE-COMPLIANCE + STATUS current + DESCRIPTION + "The requirements for conformance to the RMON MIB. At least + one of the groups in this module must be implemented to + conform to the RMON MIB. Implementations of this MIB + must also implement the system group of MIB-II [16] and the + IF-MIB [17]." + MODULE -- this module + + GROUP rmonEtherStatsGroup + DESCRIPTION + "The RMON Ethernet Statistics Group is optional." + + GROUP rmonHistoryControlGroup + DESCRIPTION + "The RMON History Control Group is optional." + + GROUP rmonEthernetHistoryGroup + DESCRIPTION + "The RMON Ethernet History Group is optional." + + GROUP rmonAlarmGroup + DESCRIPTION + "The RMON Alarm Group is optional." + + GROUP rmonHostGroup + DESCRIPTION + "The RMON Host Group is mandatory when the + rmonHostTopNGroup is implemented." + + GROUP rmonHostTopNGroup + DESCRIPTION + "The RMON Host Top N Group is optional." + + GROUP rmonMatrixGroup + DESCRIPTION + "The RMON Matrix Group is optional." + + GROUP rmonFilterGroup + DESCRIPTION + "The RMON Filter Group is mandatory when the + rmonPacketCaptureGroup is implemented." + + GROUP rmonPacketCaptureGroup + DESCRIPTION + "The RMON Packet Capture Group is optional." + + GROUP rmonEventGroup + DESCRIPTION + "The RMON Event Group is mandatory when the + rmonAlarmGroup is implemented." + ::= { rmonCompliances 1 } + + rmonEtherStatsGroup OBJECT-GROUP + OBJECTS { + etherStatsIndex, etherStatsDataSource, + etherStatsDropEvents, etherStatsOctets, etherStatsPkts, + etherStatsBroadcastPkts, etherStatsMulticastPkts, + etherStatsCRCAlignErrors, etherStatsUndersizePkts, + etherStatsOversizePkts, etherStatsFragments, + etherStatsJabbers, etherStatsCollisions, + etherStatsPkts64Octets, etherStatsPkts65to127Octets, + etherStatsPkts128to255Octets, + etherStatsPkts256to511Octets, + etherStatsPkts512to1023Octets, + etherStatsPkts1024to1518Octets, + etherStatsOwner, etherStatsStatus + } + STATUS current + DESCRIPTION + "The RMON Ethernet Statistics Group." + ::= { rmonGroups 1 } + + rmonHistoryControlGroup OBJECT-GROUP + OBJECTS { + historyControlIndex, historyControlDataSource, + historyControlBucketsRequested, + historyControlBucketsGranted, historyControlInterval, + historyControlOwner, historyControlStatus + } + STATUS current + DESCRIPTION + "The RMON History Control Group." + ::= { rmonGroups 2 } + + rmonEthernetHistoryGroup OBJECT-GROUP + OBJECTS { + etherHistoryIndex, etherHistorySampleIndex, + etherHistoryIntervalStart, etherHistoryDropEvents, + etherHistoryOctets, etherHistoryPkts, + etherHistoryBroadcastPkts, etherHistoryMulticastPkts, + etherHistoryCRCAlignErrors, etherHistoryUndersizePkts, + etherHistoryOversizePkts, etherHistoryFragments, + etherHistoryJabbers, etherHistoryCollisions, + etherHistoryUtilization + } + STATUS current + DESCRIPTION + "The RMON Ethernet History Group." + ::= { rmonGroups 3 } + + rmonAlarmGroup OBJECT-GROUP + OBJECTS { + alarmIndex, alarmInterval, alarmVariable, + alarmSampleType, alarmValue, alarmStartupAlarm, + alarmRisingThreshold, alarmFallingThreshold, + alarmRisingEventIndex, alarmFallingEventIndex, + alarmOwner, alarmStatus + } + STATUS current + DESCRIPTION + "The RMON Alarm Group." + ::= { rmonGroups 4 } + + rmonHostGroup OBJECT-GROUP + OBJECTS { + hostControlIndex, hostControlDataSource, + hostControlTableSize, hostControlLastDeleteTime, + hostControlOwner, hostControlStatus, + hostAddress, hostCreationOrder, hostIndex, + hostInPkts, hostOutPkts, hostInOctets, + hostOutOctets, hostOutErrors, hostOutBroadcastPkts, + hostOutMulticastPkts, hostTimeAddress, + hostTimeCreationOrder, hostTimeIndex, + hostTimeInPkts, hostTimeOutPkts, hostTimeInOctets, + hostTimeOutOctets, hostTimeOutErrors, + hostTimeOutBroadcastPkts, hostTimeOutMulticastPkts + } + STATUS current + DESCRIPTION + "The RMON Host Group." + ::= { rmonGroups 5 } + + rmonHostTopNGroup OBJECT-GROUP + OBJECTS { + hostTopNControlIndex, hostTopNHostIndex, + hostTopNRateBase, hostTopNTimeRemaining, + hostTopNDuration, hostTopNRequestedSize, + hostTopNGrantedSize, hostTopNStartTime, + hostTopNOwner, hostTopNStatus, + hostTopNReport, hostTopNIndex, + hostTopNAddress, hostTopNRate + } + STATUS current + DESCRIPTION + "The RMON Host Top 'N' Group." + ::= { rmonGroups 6 } + + rmonMatrixGroup OBJECT-GROUP + OBJECTS { + matrixControlIndex, matrixControlDataSource, + matrixControlTableSize, matrixControlLastDeleteTime, + matrixControlOwner, matrixControlStatus, + matrixSDSourceAddress, matrixSDDestAddress, + matrixSDIndex, matrixSDPkts, + matrixSDOctets, matrixSDErrors, + matrixDSSourceAddress, matrixDSDestAddress, + matrixDSIndex, matrixDSPkts, + matrixDSOctets, matrixDSErrors + } + STATUS current + DESCRIPTION + "The RMON Matrix Group." + ::= { rmonGroups 7 } + + rmonFilterGroup OBJECT-GROUP + OBJECTS { + filterIndex, filterChannelIndex, filterPktDataOffset, + filterPktData, filterPktDataMask, + filterPktDataNotMask, filterPktStatus, + filterPktStatusMask, filterPktStatusNotMask, + filterOwner, filterStatus, + channelIndex, channelIfIndex, channelAcceptType, + channelDataControl, channelTurnOnEventIndex, + channelTurnOffEventIndex, channelEventIndex, + channelEventStatus, channelMatches, + channelDescription, channelOwner, channelStatus + } + STATUS current + DESCRIPTION + "The RMON Filter Group." + ::= { rmonGroups 8 } + + rmonPacketCaptureGroup OBJECT-GROUP + OBJECTS { + bufferControlIndex, bufferControlChannelIndex, + bufferControlFullStatus, bufferControlFullAction, + bufferControlCaptureSliceSize, + bufferControlDownloadSliceSize, + bufferControlDownloadOffset, + bufferControlMaxOctetsRequested, + bufferControlMaxOctetsGranted, + bufferControlCapturedPackets, + bufferControlTurnOnTime, + bufferControlOwner, bufferControlStatus, + captureBufferControlIndex, captureBufferIndex, + captureBufferPacketID, captureBufferPacketData, + captureBufferPacketLength, captureBufferPacketTime, + captureBufferPacketStatus + } + STATUS current + DESCRIPTION + "The RMON Packet Capture Group." + ::= { rmonGroups 9 } + + rmonEventGroup OBJECT-GROUP + OBJECTS { + eventIndex, eventDescription, eventType, + eventCommunity, eventLastTimeSent, + eventOwner, eventStatus, + logEventIndex, logIndex, logTime, + logDescription + } + STATUS current + DESCRIPTION + "The RMON Event Group." + ::= { rmonGroups 10 } + + rmonNotificationGroup NOTIFICATION-GROUP + NOTIFICATIONS { risingAlarm, fallingAlarm } + STATUS current + DESCRIPTION + "The RMON Notification Group." + ::= { rmonGroups 11 } +END diff --git a/lib/snmp/vsn.mk b/lib/snmp/vsn.mk index fb1dcb6c41..36b9764bc8 100644 --- a/lib/snmp/vsn.mk +++ b/lib/snmp/vsn.mk @@ -18,6 +18,6 @@ # %CopyrightEnd% APPLICATION = snmp -SNMP_VSN = 4.21.7 +SNMP_VSN = 4.22 PRE_VSN = APP_VSN = "$(APPLICATION)-$(SNMP_VSN)$(PRE_VSN)" diff --git a/lib/ssh/src/ssh_sftpd.erl b/lib/ssh/src/ssh_sftpd.erl index 8cc414f83a..ec7b76b0b3 100644 --- a/lib/ssh/src/ssh_sftpd.erl +++ b/lib/ssh/src/ssh_sftpd.erl @@ -424,18 +424,18 @@ handle_op(?SSH_FXP_RENAME, ReqId, State0 end; handle_op(?SSH_FXP_SYMLINK, ReqId, - <<?UINT32(PLen), BPath:PLen/binary, ?UINT32(PLen2), - BPath2:PLen2/binary>>, + <<?UINT32(PLen), Link:PLen/binary, ?UINT32(PLen2), + Target:PLen2/binary>>, State0 = #state{file_handler = FileMod, file_state = FS0}) -> - Path = relate_file_name(BPath, State0), - Path2 = relate_file_name(BPath2, State0), - {Status, FS1} = FileMod:make_symlink(Path2, Path, FS0), + LinkPath = relate_file_name(Link, State0), + TargetPath = relate_file_name(Target, State0), + {Status, FS1} = FileMod:make_symlink(TargetPath, LinkPath, FS0), State1 = State0#state{file_state = FS1}, send_status(Status, ReqId, State1). new_handle([], H) -> H; -new_handle([{N, _} | Rest], H) when N > H -> +new_handle([{N, _,_} | Rest], H) when N =< H -> new_handle(Rest, N+1); new_handle([_ | Rest], H) -> new_handle(Rest, H). @@ -444,6 +444,8 @@ add_handle(State, XF, ReqId, Type, DirFileTuple) -> Handles = State#state.handles, Handle = new_handle(Handles, 0), ssh_xfer:xf_send_handle(XF, ReqId, integer_to_list(Handle)), + %% OBS: If you change handles-tuple also change new_handle! + %% Is this this the best way to implement new handle? State#state{handles = [{Handle, Type, DirFileTuple} | Handles]}. get_handle(Handles, BinHandle) -> diff --git a/lib/ssh/test/ssh_sftp_SUITE.erl b/lib/ssh/test/ssh_sftp_SUITE.erl index 7644db155d..d40b1d544d 100644 --- a/lib/ssh/test/ssh_sftp_SUITE.erl +++ b/lib/ssh/test/ssh_sftp_SUITE.erl @@ -76,42 +76,34 @@ end_per_suite(Config) -> %% variable, but should NOT alter/remove any existing entries. %% Description: Initiation before each test case %%-------------------------------------------------------------------- -init_per_testcase(_Case, Config) -> +init_per_testcase(Case, Config) -> prep(Config), TmpConfig0 = lists:keydelete(watchdog, 1, Config), TmpConfig = lists:keydelete(sftp, 1, TmpConfig0), Dog = test_server:timetrap(?default_timeout), - PrivDir = ?config(priv_dir, Config), - SysDir = ?config(data_dir, Config), - Host = ssh_test_lib:hostname(), - %% Run test against openssh server if available - Sftp = case (catch ssh_sftp:start_channel(Host, - [{user_interaction, false}, - {silently_accept_hosts, true}])) of - {ok, ChannelPid, Connection} -> - test_server:format("Running against openssh"), - {ChannelPid, Connection}; - _Error -> %% Start own sftp - test_server:format("Running against erlang ssh"), - {_Sftpd, Host1, Port} = - ssh_test_lib:daemon([{system_dir, SysDir}, - {user_dir, PrivDir}, - {user_passwords, - [{?USER, ?PASSWD}]}, - {failfun, - fun ssh_test_lib:failfun/2}]), - Result = (catch ssh_sftp:start_channel(Host1, Port, - [{user, ?USER}, - {password, ?PASSWD}, - {user_dir, PrivDir}, - {user_interaction, false}, - {silently_accept_hosts, true}])), - {ok, ChannelPid, Connection} = Result, - {ChannelPid, Connection} - end, - - [{sftp, Sftp}, {watchdog, Dog} | TmpConfig]. + case ?config(group, Config) of + erlang_server -> + {_,Host, Port} = ?config(sftpd, Config), + {ok, ChannelPid, Connection} = + ssh_sftp:start_channel(Host, Port, + [{user, ?USER}, + {password, ?PASSWD}, + {user_interaction, false}, + {silently_accept_hosts, true}]), + Sftp = {ChannelPid, Connection}, + [{sftp, Sftp}, {watchdog, Dog} | TmpConfig]; + openssh_server when Case == links -> + {skip, "known bug in openssh"}; + openssh_server -> + Host = ssh_test_lib:hostname(), + {ok, ChannelPid, Connection} = + ssh_sftp:start_channel(Host, + [{user_interaction, false}, + {silently_accept_hosts, true}]), + Sftp = {ChannelPid, Connection}, + [{sftp, Sftp}, {watchdog, Dog} | TmpConfig] + end. %%-------------------------------------------------------------------- %% Function: end_per_testcase(TestCase, Config) -> _ @@ -121,7 +113,15 @@ init_per_testcase(_Case, Config) -> %% A list of key/value pairs, holding the test case configuration. %% Description: Cleanup after each test case %%-------------------------------------------------------------------- -end_per_testcase(_Case, Config) -> +end_per_testcase(rename_file, Config) -> + PrivDir = ?config(priv_dir, Config), + NewFileName = filename:join(PrivDir, "test.txt"), + file:delete(NewFileName), + end_per_testcase(Config); +end_per_testcase(_, Config) -> + end_per_testcase(Config). + +end_per_testcase(Config) -> {Sftp, Connection} = ?config(sftp, Config), ssh_sftp:stop_channel(Sftp), ssh:close(Connection), @@ -138,19 +138,47 @@ end_per_testcase(_Case, Config) -> %% Description: Returns a list of all test cases in this test suite %%-------------------------------------------------------------------- all() -> - [open_close_file, open_close_dir, read_file, read_dir, - write_file, rename_file, mk_rm_dir, remove_file, links, - retrieve_attributes, set_attributes, async_read, - async_write, position, pos_read, pos_write]. + [{group, erlang_server}, + {group, openssh_server}]. groups() -> - []. - -init_per_group(_GroupName, Config) -> - Config. + [{erlang_server, [], [open_close_file, open_close_dir, read_file, read_dir, + write_file, rename_file, mk_rm_dir, remove_file, links, + retrieve_attributes, set_attributes, async_read, + async_write, position, pos_read, pos_write]}, + {openssh_server, [], [open_close_file, open_close_dir, read_file, read_dir, + write_file, rename_file, mk_rm_dir, remove_file, links, + retrieve_attributes, set_attributes, async_read, + async_write, position, pos_read, pos_write]}]. + +init_per_group(erlang_server, Config) -> + PrivDir = ?config(priv_dir, Config), + SysDir = ?config(data_dir, Config), + Sftpd = + ssh_test_lib:daemon([{system_dir, SysDir}, + {user_dir, PrivDir}, + {user_passwords, + [{?USER, ?PASSWD}]}, + {failfun, + fun ssh_test_lib:failfun/2}]), + [{group, erlang_server}, {sftpd, Sftpd} | Config]; + +init_per_group(openssh_server, Config) -> + Host = ssh_test_lib:hostname(), + case (catch ssh_sftp:start_channel(Host, + [{user_interaction, false}, + {silently_accept_hosts, true}])) of + {ok, _ChannelPid, Connection} -> + ssh:close(Connection), + [{group, openssh_server} | Config]; + _ -> + {skip, "No openssh server"} + end. -end_per_group(_GroupName, Config) -> - Config. +end_per_group(erlang_server, Config) -> + Config; +end_per_group(_, Config) -> + Config. %% Test cases starts here. @@ -332,7 +360,7 @@ links(Config) when is_list(Config) -> FileName = filename:join(PrivDir, "sftp.txt"), LinkFileName = filename:join(PrivDir, "link_test.txt"), - ok = ssh_sftp:make_symlink(Sftp, FileName, LinkFileName), + ok = ssh_sftp:make_symlink(Sftp, LinkFileName, FileName), {ok, FileName} = ssh_sftp:read_link(Sftp, LinkFileName), ok end. diff --git a/lib/ssh/test/ssh_sftpd_SUITE.erl b/lib/ssh/test/ssh_sftpd_SUITE.erl index de946d4c4c..695a7caa7d 100644 --- a/lib/ssh/test/ssh_sftpd_SUITE.erl +++ b/lib/ssh/test/ssh_sftpd_SUITE.erl @@ -545,56 +545,60 @@ set_attributes(doc) -> set_attributes(suite) -> []; set_attributes(Config) when is_list(Config) -> - PrivDir = ?config(priv_dir, Config), - FileName = filename:join(PrivDir, "test.txt"), - ReqId = 0, - {Cm, Channel} = ?config(sftp, Config), + case test_server:os_type() of + {win32, _} -> + {skip, "Known error bug in erts file:read_file_info"}; + _ -> + PrivDir = ?config(priv_dir, Config), + FileName = filename:join(PrivDir, "test.txt"), + ReqId = 0, + {Cm, Channel} = ?config(sftp, Config), - {ok, FileInfo} = file:read_file_info(FileName), + {ok, FileInfo} = file:read_file_info(FileName), - OrigPermissions = FileInfo#file_info.mode, - Permissions = 8#600, %% User read-write-only + OrigPermissions = FileInfo#file_info.mode, + Permissions = not_default_permissions(), - Flags = ?SSH_FILEXFER_ATTR_PERMISSIONS, + Flags = ?SSH_FILEXFER_ATTR_PERMISSIONS, - Atters = [?uint32(Flags), ?byte(?SSH_FILEXFER_TYPE_REGULAR), - ?uint32(Permissions)], + Atters = [?uint32(Flags), ?byte(?SSH_FILEXFER_TYPE_REGULAR), + ?uint32(Permissions)], - {ok, <<?SSH_FXP_STATUS, ?UINT32(ReqId), - ?UINT32(?SSH_FX_OK), _/binary>>, _} = - set_attributes_file(FileName, Atters, Cm, Channel, ReqId), - - {ok, NewFileInfo} = file:read_file_info(FileName), - NewPermissions = NewFileInfo#file_info.mode, - - %% Can not test that NewPermissions = Permissions as - %% on Unix platforms, other bits than those listed in the - %% API may be set. - test_server:format("Org: ~p New: ~p~n", [OrigPermissions, NewPermissions]), - true = OrigPermissions =/= NewPermissions, - - test_server:format("Try to open the file"), - NewReqId = 2, - {ok, <<?SSH_FXP_HANDLE, ?UINT32(NewReqId), Handle/binary>>, _} = - open_file(FileName, Cm, Channel, NewReqId, - ?ACE4_READ_DATA bor ?ACE4_WRITE_ATTRIBUTES, - ?SSH_FXF_OPEN_EXISTING), + {ok, <<?SSH_FXP_STATUS, ?UINT32(ReqId), + ?UINT32(?SSH_FX_OK), _/binary>>, _} = + set_attributes_file(FileName, Atters, Cm, Channel, ReqId), - NewAtters = [?uint32(Flags), ?byte(?SSH_FILEXFER_TYPE_REGULAR), - ?uint32(OrigPermissions)], + {ok, NewFileInfo} = file:read_file_info(FileName), + NewPermissions = NewFileInfo#file_info.mode, - NewReqId1 = 3, + %% Can not test that NewPermissions = Permissions as + %% on Unix platforms, other bits than those listed in the + %% API may be set. + test_server:format("Org: ~p New: ~p~n", [OrigPermissions, NewPermissions]), + true = OrigPermissions =/= NewPermissions, - test_server:format("Set original permissions on the now open file"), + test_server:format("Try to open the file"), + NewReqId = 2, + {ok, <<?SSH_FXP_HANDLE, ?UINT32(NewReqId), Handle/binary>>, _} = + open_file(FileName, Cm, Channel, NewReqId, + ?ACE4_READ_DATA bor ?ACE4_WRITE_ATTRIBUTES, + ?SSH_FXF_OPEN_EXISTING), - {ok, <<?SSH_FXP_STATUS, ?UINT32(NewReqId1), - ?UINT32(?SSH_FX_OK), _/binary>>, _} = - set_attributes_open_file(Handle, NewAtters, Cm, Channel, NewReqId1), + NewAtters = [?uint32(Flags), ?byte(?SSH_FILEXFER_TYPE_REGULAR), + ?uint32(OrigPermissions)], - {ok, NewFileInfo1} = file:read_file_info(FileName), - OrigPermissions = NewFileInfo1#file_info.mode, + NewReqId1 = 3, - ok. + test_server:format("Set original permissions on the now open file"), + + {ok, <<?SSH_FXP_STATUS, ?UINT32(NewReqId1), + ?UINT32(?SSH_FX_OK), _/binary>>, _} = + set_attributes_open_file(Handle, NewAtters, Cm, Channel, NewReqId1), + + {ok, NewFileInfo1} = file:read_file_info(FileName), + OrigPermissions = NewFileInfo1#file_info.mode, + ok + end. %%-------------------------------------------------------------------- ver3_rename_OTP_6352(doc) -> @@ -943,3 +947,6 @@ sshd_read_file(Config) when is_list(Config) -> {ok, Data} = file:read_file(FileName), ok. + +not_default_permissions() -> + 8#600. %% User read-write-only diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml index 50268ae206..4910a6f1b8 100644 --- a/lib/ssl/doc/src/ssl.xml +++ b/lib/ssl/doc/src/ssl.xml @@ -62,8 +62,8 @@ </c></p> <p>For valid options - see <seealso marker="kernel:inet">inet(3) </seealso> and - <seealso marker="kernel:gen_tcp">gen_tcp(3) </seealso>. + see <seealso marker="kernel:inet">inet(3)</seealso> and + <seealso marker="kernel:gen_tcp">gen_tcp(3)</seealso>. </p> <p> <c>ssloption() = {verify, verify_type()} | diff --git a/lib/stdlib/doc/src/digraph_utils.xml b/lib/stdlib/doc/src/digraph_utils.xml index e44632bfd2..ef6e1cb46f 100644 --- a/lib/stdlib/doc/src/digraph_utils.xml +++ b/lib/stdlib/doc/src/digraph_utils.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2000</year><year>2011</year> + <year>2000</year><year>2012</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -156,7 +156,7 @@ <p>Creates a digraph where the vertices are the <seealso marker="#strong_components">strongly connected components</seealso> of <c><anno>Digraph</anno></c> as returned by - <c>strong_components/1</c>. If X and Y are strongly + <c>strong_components/1</c>. If X and Y are two different strongly connected components, and there exist vertices x and y in X and Y respectively such that there is an edge <seealso marker="#emanate">emanating</seealso> from x diff --git a/lib/stdlib/doc/src/ets.xml b/lib/stdlib/doc/src/ets.xml index efd9514db6..0486090e92 100644 --- a/lib/stdlib/doc/src/ets.xml +++ b/lib/stdlib/doc/src/ets.xml @@ -671,7 +671,7 @@ ets:is_compiled_ms(Broken).</code> <c>duplicate_bag</c>, the function returns a list of arbitrary length.</p> <p>Note that the time order of object insertions is preserved; - The first object inserted with the given key will be first + the first object inserted with the given key will be first in the resulting list, and so on.</p> <p>Insert and look-up times in tables of type <c>set</c>, <c>bag</c> and <c>duplicate_bag</c> are constant, regardless diff --git a/lib/stdlib/doc/src/lists.xml b/lib/stdlib/doc/src/lists.xml index 7042c84437..96a0942710 100644 --- a/lib/stdlib/doc/src/lists.xml +++ b/lib/stdlib/doc/src/lists.xml @@ -663,7 +663,7 @@ splitwith(Pred, List) -> <desc> <p>Returns the sub-list of <c><anno>List1</anno></c> starting at position 1 and with (max) <c><anno>Len</anno></c> elements. It is not an error for - <c><anno>Len</anno></c> to exceed the length of the list -- in that case + <c><anno>Len</anno></c> to exceed the length of the list, in that case the whole list is returned.</p> </desc> </func> diff --git a/lib/stdlib/doc/src/supervisor.xml b/lib/stdlib/doc/src/supervisor.xml index d1e62230bc..9b41672bf1 100644 --- a/lib/stdlib/doc/src/supervisor.xml +++ b/lib/stdlib/doc/src/supervisor.xml @@ -55,7 +55,8 @@ monitoring its child processes. The basic idea of a supervisor is that it should keep its child processes alive by restarting them when necessary.</p> - <p>The children of a supervisor is defined as a list of <em>child specifications</em>. When the supervisor is started, the child + <p>The children of a supervisor is defined as a list of + <em>child specifications</em>. When the supervisor is started, the child processes are started in order from left to right according to this list. When the supervisor terminates, it first terminates its child processes in reversed start order, from right to left.</p> @@ -100,7 +101,8 @@ </item> </list> <p>To prevent a supervisor from getting into an infinite loop of - child process terminations and restarts, a <em>maximum restart frequency</em> is defined using two integer values <c>MaxR</c> + child process terminations and restarts, a <em>maximum restart frequency</em> + is defined using two integer values <c>MaxR</c> and <c>MaxT</c>. If more than <c>MaxR</c> restarts occur within <c>MaxT</c> seconds, the supervisor terminates all child processes and then itself. @@ -114,7 +116,7 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules} M = F = atom() A = [term()] Restart = permanent | transient | temporary - Shutdown = brutal_kill | int()>=0 | infinity + Shutdown = brutal_kill | int()>0 | infinity Type = worker | supervisor Modules = [Module] | dynamic Module = atom()</pre> @@ -197,7 +199,8 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules} the callback module, if the child process is a supervisor, gen_server or gen_fsm. If the child process is an event manager (gen_event) with a dynamic set of callback modules, - <c>Modules</c> should be <c>dynamic</c>. See <em>OTP Design Principles</em> for more information about release handling.</p> + <c>Modules</c> should be <c>dynamic</c>. See <em>OTP Design Principles</em> + for more information about release handling.</p> </item> <item> <p>Internally, the supervisor also keeps track of the pid @@ -399,10 +402,11 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules} <c>SupRef</c>.</p> <p>If successful, the function returns <c>ok</c>. If the child specification identified by <c><anno>Id</anno></c> exists but - the corresponding child process is running, the function - returns <c>{error,running}</c>. If the child specification - identified by <c><anno>Id</anno></c> does not exist, the function returns - <c>{error,not_found}</c>.</p> + the corresponding child process is running or about to be restarted, + the function returns <c>{error,running}</c> or + <c>{error,restarting}</c> respectively. If the child specification + identified by <c><anno>Id</anno></c> does not exist, the function + returns <c>{error,not_found}</c>.</p> </desc> </func> <func> @@ -442,7 +446,8 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules} </func> <func> <name name="which_children" arity="1"/> - <fsummary>Return information about all children specifications and child processes belonging to a supervisor.</fsummary> + <fsummary>Return information about all children specifications and + child processes belonging to a supervisor.</fsummary> <desc> <p>Returns a newly created list with information about all child specifications and child processes belonging to @@ -462,7 +467,8 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules} </item> <item> <p><c><anno>Child</anno></c> - the pid of the corresponding child - process, or <c>undefined</c> if there is no such process.</p> + process, the atom <c>restarting</c> if the process is about to be + restarted or <c>undefined</c> if there is no such process.</p> </item> <item> <p><c><anno>Type</anno></c> - as defined in the child specification.</p> @@ -475,7 +481,8 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules} </func> <func> <name name="count_children" arity="1"/> - <fsummary>Return counts for the number of childspecs, active children, supervisors and workers.</fsummary> + <fsummary>Return counts for the number of childspecs, active children, + supervisors and workers.</fsummary> <desc> <p>Returns a property list (see <c>proplists</c>) containing the counts for each of the following elements of the supervisor's @@ -525,7 +532,8 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules} <v>Args = term()</v> <v>Result = {ok,{{RestartStrategy,MaxR,MaxT},[ChildSpec]}} | ignore</v> <v> RestartStrategy = <seealso marker="#type-strategy">strategy()</seealso></v> - <v> MaxR = MaxT = integer()>=0</v> + <v> MaxR = integer()>=0</v> + <v> MaxT = integer()>0</v> <v> ChildSpec = <seealso marker="#type-child_spec">child_spec()</seealso></v> </type> <desc> diff --git a/lib/stdlib/src/digraph_utils.erl b/lib/stdlib/src/digraph_utils.erl index e221be15a1..807b5c12a1 100644 --- a/lib/stdlib/src/digraph_utils.erl +++ b/lib/stdlib/src/digraph_utils.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2011. All Rights Reserved. +%% Copyright Ericsson AB 1999-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -370,5 +370,5 @@ condense('$end_of_table', _T, _SC, _G, _SCG, _I2C) -> condense(I, T, SC, G, SCG, I2C) -> [{_,C}] = ets:lookup(I2C, I), digraph:add_vertex(SCG, C), - digraph:add_edge(SCG, SC, C), + [digraph:add_edge(SCG, SC, C) || C =/= SC], condense(ets:next(T, I), T, SC, G, SCG, I2C). diff --git a/lib/stdlib/src/supervisor.erl b/lib/stdlib/src/supervisor.erl index ac5b078c29..c10da1989c 100644 --- a/lib/stdlib/src/supervisor.erl +++ b/lib/stdlib/src/supervisor.erl @@ -28,8 +28,9 @@ check_childspecs/1]). %% Internal exports --export([init/1, handle_call/3, handle_info/2, terminate/2, code_change/3]). --export([handle_cast/2]). +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, + terminate/2, code_change/3]). +-export([try_again_restart/2]). %%-------------------------------------------------------------------------- @@ -37,7 +38,7 @@ %%-------------------------------------------------------------------------- --type child() :: 'undefined' | pid() | [pid()]. +-type child() :: 'undefined' | pid(). -type child_id() :: term(). -type mfargs() :: {M :: module(), F :: atom(), A :: [term()] | undefined}. -type modules() :: [module()] | 'dynamic'. @@ -62,8 +63,8 @@ %%-------------------------------------------------------------------------- -record(child, {% pid is undefined when child is not running - pid = undefined :: child(), - name, + pid = undefined :: child() | {restarting,pid()} | [pid()], + name :: child_id(), mfargs :: mfargs(), restart_type :: restart(), shutdown :: shutdown(), @@ -95,6 +96,8 @@ [ChildSpec :: child_spec()]}} | ignore. +-define(restarting(_Pid_), {restarting,_Pid_}). + %%% --------------------------------------------------- %%% This is a general process supervisor built upon gen_server.erl. %%% Servers/processes should/could also be built using gen_server.erl. @@ -139,7 +142,8 @@ start_child(Supervisor, ChildSpec) -> Result :: {'ok', Child :: child()} | {'ok', Child :: child(), Info :: term()} | {'error', Error}, - Error :: 'running' | 'not_found' | 'simple_one_for_one' | term(). + Error :: 'running' | 'restarting' | 'not_found' | 'simple_one_for_one' | + term(). restart_child(Supervisor, Name) -> call(Supervisor, {restart_child, Name}). @@ -147,7 +151,7 @@ restart_child(Supervisor, Name) -> SupRef :: sup_ref(), Id :: child_id(), Result :: 'ok' | {'error', Error}, - Error :: 'running' | 'not_found' | 'simple_one_for_one'. + Error :: 'running' | 'restarting' | 'not_found' | 'simple_one_for_one'. delete_child(Supervisor, Name) -> call(Supervisor, {delete_child, Name}). @@ -169,7 +173,7 @@ terminate_child(Supervisor, Name) -> -spec which_children(SupRef) -> [{Id,Child,Type,Modules}] when SupRef :: sup_ref(), Id :: child_id() | undefined, - Child :: child(), + Child :: child() | 'restarting', Type :: worker(), Modules :: modules(). which_children(Supervisor) -> @@ -198,6 +202,17 @@ check_childspecs(ChildSpecs) when is_list(ChildSpecs) -> end; check_childspecs(X) -> {error, {badarg, X}}. +%%%----------------------------------------------------------------- +%%% Called by timer:apply_after from restart/2 +-spec try_again_restart(SupRef, Child) -> ok when + SupRef :: sup_ref(), + Child :: child_id() | pid(). +try_again_restart(Supervisor, Child) -> + cast(Supervisor, {try_again_restart, Child}). + +cast(Supervisor, Req) -> + gen_server:cast(Supervisor, Req). + %%% --------------------------------------------------- %%% %%% Initialize the supervisor. @@ -384,6 +399,8 @@ handle_call({restart_child, Name}, _From, State) -> Error -> {reply, Error, State} end; + {value, #child{pid=?restarting(_)}} -> + {reply, {error, restarting}, State}; {value, _} -> {reply, {error, running}, State}; _ -> @@ -395,6 +412,8 @@ handle_call({delete_child, Name}, _From, State) -> {value, Child} when Child#child.pid =:= undefined -> NState = remove_child(Child, State), {reply, ok, NState}; + {value, #child{pid=?restarting(_)}} -> + {reply, {error, restarting}, State}; {value, _} -> {reply, {error, running}, State}; _ -> @@ -413,13 +432,17 @@ handle_call(which_children, _From, #state{children = [#child{restart_type = RTyp child_type = CT, modules = Mods}]} = State) when ?is_simple(State) -> - Reply = lists:map(fun({Pid, _}) -> {undefined, Pid, CT, Mods} end, + Reply = lists:map(fun({?restarting(_),_}) -> {undefined,restarting,CT,Mods}; + ({Pid, _}) -> {undefined, Pid, CT, Mods} end, ?DICT:to_list(dynamics_db(RType, State#state.dynamics))), {reply, Reply, State}; handle_call(which_children, _From, State) -> Resp = - lists:map(fun(#child{pid = Pid, name = Name, + lists:map(fun(#child{pid = ?restarting(_), name = Name, + child_type = ChildType, modules = Mods}) -> + {Name, restarting, ChildType, Mods}; + (#child{pid = Pid, name = Name, child_type = ChildType, modules = Mods}) -> {Name, Pid, ChildType, Mods} end, @@ -432,8 +455,11 @@ handle_call(count_children, _From, #state{children = [#child{restart_type = temp when ?is_simple(State) -> {Active, Count} = ?SETS:fold(fun(Pid, {Alive, Tot}) -> - if is_pid(Pid) -> {Alive+1, Tot +1}; - true -> {Alive, Tot + 1} end + case is_pid(Pid) andalso is_process_alive(Pid) of + true ->{Alive+1, Tot +1}; + false -> + {Alive, Tot + 1} + end end, {0, 0}, dynamics_db(temporary, State#state.dynamics)), Reply = case CT of supervisor -> [{specs, 1}, {active, Active}, @@ -448,8 +474,12 @@ handle_call(count_children, _From, #state{children = [#child{restart_type = RTy when ?is_simple(State) -> {Active, Count} = ?DICT:fold(fun(Pid, _Val, {Alive, Tot}) -> - if is_pid(Pid) -> {Alive+1, Tot +1}; - true -> {Alive, Tot + 1} end + case is_pid(Pid) andalso is_process_alive(Pid) of + true -> + {Alive+1, Tot +1}; + false -> + {Alive, Tot + 1} + end end, {0, 0}, dynamics_db(RType, State#state.dynamics)), Reply = case CT of supervisor -> [{specs, 1}, {active, Active}, @@ -486,14 +516,42 @@ count_child(#child{pid = Pid, child_type = supervisor}, end. -%%% Hopefully cause a function-clause as there is no API function -%%% that utilizes cast. --spec handle_cast('null', state()) -> {'noreply', state()}. +%%% If a restart attempt failed, this message is sent via +%%% timer:apply_after(0,...) in order to give gen_server the chance to +%%% check it's inbox before trying again. +-spec handle_cast({try_again_restart, child_id() | pid()}, state()) -> + {'noreply', state()} | {stop, shutdown, state()}. -handle_cast(null, State) -> - error_logger:error_msg("ERROR: Supervisor received cast-message 'null'~n", - []), - {noreply, State}. +handle_cast({try_again_restart,Pid}, #state{children=[Child]}=State) + when ?is_simple(State) -> + RT = Child#child.restart_type, + RPid = restarting(Pid), + case dynamic_child_args(RPid, dynamics_db(RT, State#state.dynamics)) of + {ok, Args} -> + {M, F, _} = Child#child.mfargs, + NChild = Child#child{pid = RPid, mfargs = {M, F, Args}}, + case restart(NChild,State) of + {ok, State1} -> + {noreply, State1}; + {shutdown, State1} -> + {stop, shutdown, State1} + end; + error -> + {noreply, State} + end; + +handle_cast({try_again_restart,Name}, State) -> + case lists:keyfind(Name,#child.name,State#state.children) of + Child = #child{pid=?restarting(_)} -> + case restart(Child,State) of + {ok, State1} -> + {noreply, State1}; + {shutdown, State1} -> + {stop, shutdown, State1} + end; + _ -> + {noreply,State} + end. %% %% Take care of terminated children. @@ -566,13 +624,12 @@ check_flags(What) -> {bad_flags, What}. update_childspec(State, StartSpec) when ?is_simple(State) -> - case check_startspec(StartSpec) of - {ok, [Child]} -> - {ok, State#state{children = [Child]}}; - Error -> - {error, Error} - end; - + case check_startspec(StartSpec) of + {ok, [Child]} -> + {ok, State#state{children = [Child]}}; + Error -> + {error, Error} + end; update_childspec(State, StartSpec) -> case check_startspec(StartSpec) of {ok, Children} -> @@ -592,7 +649,7 @@ update_childspec1([Child|OldC], Children, KeepOld) -> end; update_childspec1([], Children, KeepOld) -> %% Return them in (kept) reverse start order. - lists:reverse(Children ++ KeepOld). + lists:reverse(Children ++ KeepOld). update_chsp(OldCh, Children) -> case lists:map(fun(Ch) when OldCh#child.name =:= Ch#child.name -> @@ -624,7 +681,7 @@ handle_start_child(Child, State) -> {error, What} -> {{error, {What, Child}}, State} end; - {value, OldChild} when OldChild#child.pid =/= undefined -> + {value, OldChild} when is_pid(OldChild#child.pid) -> {{error, {already_started, OldChild#child.pid}}, State}; {value, _OldChild} -> {{error, already_present}, State} @@ -678,7 +735,21 @@ do_restart(temporary, Reason, Child, State) -> restart(Child, State) -> case add_restart(State) of {ok, NState} -> - restart(NState#state.strategy, Child, NState); + case restart(NState#state.strategy, Child, NState) of + {try_again,NState2} -> + %% Leaving control back to gen_server before + %% trying again. This way other incoming requsts + %% for the supervisor can be handled - e.g. a + %% shutdown request for the supervisor or the + %% child. + Id = if ?is_simple(State) -> Child#child.pid; + true -> Child#child.name + end, + timer:apply_after(0,?MODULE,try_again_restart,[self(),Id]), + {ok,NState2}; + Other -> + Other + end; {terminate, NState} -> report_error(shutdown, reached_max_restart_intensity, Child, State#state.name), @@ -686,9 +757,9 @@ restart(Child, State) -> end. restart(simple_one_for_one, Child, State) -> - #child{mfargs = {M, F, A}} = Child, - Dynamics = ?DICT:erase(Child#child.pid, dynamics_db(Child#child.restart_type, - State#state.dynamics)), + #child{pid = OldPid, mfargs = {M, F, A}} = Child, + Dynamics = ?DICT:erase(OldPid, dynamics_db(Child#child.restart_type, + State#state.dynamics)), case do_start_child_i(M, F, A) of {ok, Pid} -> NState = State#state{dynamics = ?DICT:store(Pid, A, Dynamics)}, @@ -697,10 +768,13 @@ restart(simple_one_for_one, Child, State) -> NState = State#state{dynamics = ?DICT:store(Pid, A, Dynamics)}, {ok, NState}; {error, Error} -> + NState = State#state{dynamics = ?DICT:store(restarting(OldPid), A, + Dynamics)}, report_error(start_error, Error, Child, State#state.name), - restart(Child, State) + {try_again, NState} end; restart(one_for_one, Child, State) -> + OldPid = Child#child.pid, case do_start_child(State#state.name, Child) of {ok, Pid} -> NState = replace_child(Child#child{pid = Pid}, State), @@ -709,8 +783,9 @@ restart(one_for_one, Child, State) -> NState = replace_child(Child#child{pid = Pid}, State), {ok, NState}; {error, Reason} -> + NState = replace_child(Child#child{pid = restarting(OldPid)}, State), report_error(start_error, Reason, Child, State#state.name), - restart(Child, State) + {try_again, NState} end; restart(rest_for_one, Child, State) -> {ChAfter, ChBefore} = split_child(Child#child.pid, State#state.children), @@ -719,7 +794,9 @@ restart(rest_for_one, Child, State) -> {ok, ChAfter3} -> {ok, State#state{children = ChAfter3 ++ ChBefore}}; {error, ChAfter3} -> - restart(Child, State#state{children = ChAfter3 ++ ChBefore}) + NChild = Child#child{pid=restarting(Child#child.pid)}, + NState = State#state{children = ChAfter3 ++ ChBefore}, + {try_again, replace_child(NChild,NState)} end; restart(one_for_all, Child, State) -> Children1 = del_child(Child#child.pid, State#state.children), @@ -728,9 +805,14 @@ restart(one_for_all, Child, State) -> {ok, NChs} -> {ok, State#state{children = NChs}}; {error, NChs} -> - restart(Child, State#state{children = NChs}) + NChild = Child#child{pid=restarting(Child#child.pid)}, + NState = State#state{children = NChs}, + {try_again, replace_child(NChild,NState)} end. +restarting(Pid) when is_pid(Pid) -> ?restarting(Pid); +restarting(RPid) -> RPid. + %%----------------------------------------------------------------- %% Func: terminate_children/2 %% Args: Children = [child_rec()] in termination order @@ -754,7 +836,7 @@ terminate_children([Child | Children], SupName, Res) -> terminate_children([], _SupName, Res) -> Res. -do_terminate(Child, SupName) when Child#child.pid =/= undefined -> +do_terminate(Child, SupName) when is_pid(Child#child.pid) -> case shutdown(Child#child.pid, Child#child.shutdown) of ok -> ok; @@ -765,7 +847,7 @@ do_terminate(Child, SupName) when Child#child.pid =/= undefined -> end, Child#child{pid = undefined}; do_terminate(Child, _SupName) -> - Child. + Child#child{pid = undefined}. %%----------------------------------------------------------------- %% Shutdowns a child. We must check the EXIT value @@ -866,7 +948,7 @@ terminate_dynamic_children(Child, Dynamics, SupName) -> TRef = erlang:start_timer(Time, self(), kill), wait_dynamic_children(Child, Pids, Sz, TRef, EStack0) end, - %% Unrool stacked errors and report them + %% Unroll stacked errors and report them ?DICT:fold(fun(Reason, Ls, _) -> report_error(shutdown_error, Reason, Child#child{pid=Ls}, SupName) @@ -885,7 +967,7 @@ monitor_dynamic_children(#child{restart_type=temporary}, Dynamics) -> end end, {?SETS:new(), ?DICT:new()}, Dynamics); monitor_dynamic_children(#child{restart_type=RType}, Dynamics) -> - ?DICT:fold(fun(P, _, {Pids, EStack}) -> + ?DICT:fold(fun(P, _, {Pids, EStack}) when is_pid(P) -> case monitor_child(P) of ok -> {?SETS:add_element(P, Pids), EStack}; @@ -893,7 +975,9 @@ monitor_dynamic_children(#child{restart_type=RType}, Dynamics) -> {Pids, EStack}; {error, Reason} -> {Pids, ?DICT:append(Reason, P, EStack)} - end + end; + (?restarting(_), _, {Pids, EStack}) -> + {Pids, EStack} end, {?SETS:new(), ?DICT:new()}, Dynamics). @@ -1020,13 +1104,20 @@ get_child(Name, State, _) -> lists:keysearch(Name, #child.name, State#state.children). get_dynamic_child(Pid, #state{children=[Child], dynamics=Dynamics}) -> - case is_dynamic_pid(Pid, dynamics_db(Child#child.restart_type, Dynamics)) of + DynamicsDb = dynamics_db(Child#child.restart_type, Dynamics), + case is_dynamic_pid(Pid, DynamicsDb) of true -> {value, Child#child{pid=Pid}}; false -> - case erlang:is_process_alive(Pid) of - true -> false; - false -> {value, Child} + RPid = restarting(Pid), + case is_dynamic_pid(RPid, DynamicsDb) of + true -> + {value, Child#child{pid=RPid}}; + false -> + case erlang:is_process_alive(Pid) of + true -> false; + false -> {value, Child} + end end end. @@ -1056,9 +1147,9 @@ remove_child(Child, State) -> %% Args: SupName = {local, atom()} | {global, atom()} | self %% Type = {Strategy, MaxIntensity, Period} %% Strategy = one_for_one | one_for_all | simple_one_for_one | -%% rest_for_one -%% MaxIntensity = integer() -%% Period = integer() +%% rest_for_one +%% MaxIntensity = integer() >= 0 +%% Period = integer() > 0 %% Mod :== atom() %% Args :== term() %% Purpose: Check that Type is of correct type (!) @@ -1109,7 +1200,7 @@ supname(N, _) -> N. %%% where Name is an atom %%% Func is {Mod, Fun, Args} == {atom(), atom(), list()} %%% RestartType is permanent | temporary | transient -%%% Shutdown = integer() | infinity | brutal_kill +%%% Shutdown = integer() > 0 | infinity | brutal_kill %%% ChildType = supervisor | worker %%% Modules = [atom()] | dynamic %%% Returns: {ok, [child_rec()]} | Error diff --git a/lib/stdlib/test/Makefile b/lib/stdlib/test/Makefile index b36265302c..4de6ea3ee7 100644 --- a/lib/stdlib/test/Makefile +++ b/lib/stdlib/test/Makefile @@ -67,6 +67,7 @@ MODULES= \ string_SUITE \ supervisor_1 \ supervisor_2 \ + supervisor_deadlock \ naughty_child \ shell_SUITE \ supervisor_SUITE \ diff --git a/lib/stdlib/test/digraph_utils_SUITE.erl b/lib/stdlib/test/digraph_utils_SUITE.erl index 12c486c25f..6b554c2fb7 100644 --- a/lib/stdlib/test/digraph_utils_SUITE.erl +++ b/lib/stdlib/test/digraph_utils_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2011. All Rights Reserved. +%% Copyright Ericsson AB 2000-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -211,8 +211,7 @@ condensation(Config) when is_list(Config) -> {lists:sort(V1), lists:sort(V2)} end, ?line Es = lists:map(Fun, digraph:edges(CG)), - ?line [{[b],[c]},{[b],[d]},{[e,f,g],[e,f,g]},{[h],[h]},{[i,j],[i,j]}] = - lists:sort(Es), + ?line [{[b],[c]},{[b],[d]}] = lists:sort(Es), ?line true = digraph:delete(CG), ?line true = digraph:delete(G), ok. diff --git a/lib/stdlib/test/qlc_SUITE.erl b/lib/stdlib/test/qlc_SUITE.erl index 50a76cdfb5..1e74ad7727 100644 --- a/lib/stdlib/test/qlc_SUITE.erl +++ b/lib/stdlib/test/qlc_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2004-2011. All Rights Reserved. +%% Copyright Ericsson AB 2004-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -7927,15 +7927,23 @@ run_test(Config, Extra, {cres, Body, Opts, ExpectedCompileReturn}) -> ok end, + wait_for_expected(R, Before, SourceFile, true), + code:purge(Mod); +run_test(Config, Extra, Body) -> + run_test(Config, Extra, {cres,Body,[]}). + +wait_for_expected(R, Before, SourceFile, Wait) -> Ms = erlang:process_info(self(),messages), After = {get(), pps(), ets:all(), Ms}, - code:purge(Mod), case {R, After} of - {ok, Before} -> ok; - _ -> expected({ok,Before}, {R,After}, SourceFile) - end; -run_test(Config, Extra, Body) -> - run_test(Config, Extra, {cres,Body,[]}). + {ok, Before} -> + ok; + _ when Wait -> + timer:sleep(1000), + wait_for_expected(R, Before, SourceFile, false); + _ -> + expected({ok,Before}, {R,After}, SourceFile) + end. unload_pt() -> erlang:garbage_collect(), % get rid of references to qlc_pt... diff --git a/lib/stdlib/test/supervisor_SUITE.erl b/lib/stdlib/test/supervisor_SUITE.erl index 71b76c093f..767ae3d62c 100644 --- a/lib/stdlib/test/supervisor_SUITE.erl +++ b/lib/stdlib/test/supervisor_SUITE.erl @@ -21,7 +21,7 @@ -module(supervisor_SUITE). -include_lib("common_test/include/ct.hrl"). --define(TIMEOUT, 1000). +-define(TIMEOUT, ?t:minutes(1)). %% Testserver specific export -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, @@ -62,7 +62,8 @@ do_not_save_start_parameters_for_temporary_children/1, do_not_save_child_specs_for_temporary_children/1, simple_one_for_one_scale_many_temporary_children/1, - simple_global_supervisor/1]). + simple_global_supervisor/1, hanging_restart_loop/1, + hanging_restart_loop_simple/1]). %%------------------------------------------------------------------------- @@ -82,7 +83,7 @@ all() -> count_children_memory, do_not_save_start_parameters_for_temporary_children, do_not_save_child_specs_for_temporary_children, simple_one_for_one_scale_many_temporary_children, temporary_bystander, - simple_global_supervisor]. + simple_global_supervisor, hanging_restart_loop, hanging_restart_loop_simple]. groups() -> [{sup_start, [], @@ -111,10 +112,8 @@ groups() -> {restart_rest_for_one, [], [rest_for_one, rest_for_one_escalation]}]. -init_per_suite(Config0) -> - Config = lists:keydelete(watchdog, 1, Config0), - Dog = test_server:timetrap(?TIMEOUT), - [{watchdog, Dog} | Config]. +init_per_suite(Config) -> + Config. end_per_suite(_Config) -> ok. @@ -129,18 +128,21 @@ init_per_testcase(count_children_memory, Config) -> try erlang:memory() of _ -> erts_debug:set_internal_state(available_internal_state, true), - Config + Dog = ?t:timetrap(?TIMEOUT), + [{watchdog,Dog}|Config] catch error:notsup -> {skip, "+Meamin used during test; erlang:memory/1 not available"} end; init_per_testcase(_Case, Config) -> - erlang:display(_Case), - Config. + Dog = ?t:timetrap(?TIMEOUT), + [{watchdog,Dog}|Config]. -end_per_testcase(count_children_memory, _Config) -> +end_per_testcase(count_children_memory, Config) -> catch erts_debug:set_internal_state(available_internal_state, false), + ?t:timetrap_cancel(?config(watchdog,Config)), ok; -end_per_testcase(_Case, _Config) -> +end_per_testcase(_Case, Config) -> + ?t:timetrap_cancel(?config(watchdog,Config)), ok. start_link(InitResult) -> @@ -1455,6 +1457,102 @@ gen_server9212() -> %%------------------------------------------------------------------------- +%% Test that child and supervisor can be shutdown while hanging in restart loop. +%% See OTP-9549. +hanging_restart_loop(Config) when is_list(Config) -> + process_flag(trap_exit, true), + {ok, Pid} = start_link({ok, {{one_for_one, 8, 10}, []}}), + Child1 = {child1, {supervisor_deadlock, start_child, []}, + permanent, brutal_kill, worker, []}, + + %% Ets table with state read by supervisor_deadlock.erl + ets:new(supervisor_deadlock,[set,named_table,public]), + ets:insert(supervisor_deadlock,{fail_start,false}), + + {ok, CPid1} = supervisor:start_child(sup_test, Child1), + link(CPid1), + + ets:insert(supervisor_deadlock,{fail_start,true}), + supervisor_deadlock:restart_child(), + timer:sleep(2000), % allow restart to happen before proceeding + + {error, already_present} = supervisor:start_child(sup_test, Child1), + {error, restarting} = supervisor:restart_child(sup_test, child1), + {error, restarting} = supervisor:delete_child(sup_test, child1), + [{child1,restarting,worker,[]}] = supervisor:which_children(sup_test), + [1,0,0,1] = get_child_counts(sup_test), + + ok = supervisor:terminate_child(sup_test, child1), + check_exit_reason(CPid1, error), + [{child1,undefined,worker,[]}] = supervisor:which_children(sup_test), + + ets:insert(supervisor_deadlock,{fail_start,false}), + {ok, CPid2} = supervisor:restart_child(sup_test, child1), + link(CPid2), + + ets:insert(supervisor_deadlock,{fail_start,true}), + supervisor_deadlock:restart_child(), + timer:sleep(2000), % allow restart to happen before proceeding + + %% Terminating supervisor. + %% OTP-9549 fixes so this does not give a timetrap timeout - + %% i.e. that supervisor does not hang in restart loop. + terminate(Pid,shutdown), + + %% Check that child died with reason from 'restart' request above + check_exit_reason(CPid2, error), + undefined = whereis(sup_test), + ok. + +%%------------------------------------------------------------------------- +%% Test that child and supervisor can be shutdown while hanging in +%% restart loop, simple_one_for_one. +%% See OTP-9549. +hanging_restart_loop_simple(Config) when is_list(Config) -> + process_flag(trap_exit, true), + Child1 = {child1, {supervisor_deadlock, start_child, []}, + permanent, brutal_kill, worker, []}, + {ok, Pid} = start_link({ok, {{simple_one_for_one, 8, 10}, [Child1]}}), + + %% Ets table with state read by supervisor_deadlock.erl + ets:new(supervisor_deadlock,[set,named_table,public]), + ets:insert(supervisor_deadlock,{fail_start,false}), + + {ok, CPid1} = supervisor:start_child(sup_test, []), + link(CPid1), + + ets:insert(supervisor_deadlock,{fail_start,true}), + supervisor_deadlock:restart_child(), + timer:sleep(2000), % allow restart to happen before proceeding + + {error, simple_one_for_one} = supervisor:restart_child(sup_test, child1), + {error, simple_one_for_one} = supervisor:delete_child(sup_test, child1), + [{undefined,restarting,worker,[]}] = supervisor:which_children(sup_test), + [1,0,0,1] = get_child_counts(sup_test), + + ok = supervisor:terminate_child(sup_test, CPid1), + check_exit_reason(CPid1, error), + [] = supervisor:which_children(sup_test), + + ets:insert(supervisor_deadlock,{fail_start,false}), + {ok, CPid2} = supervisor:start_child(sup_test, []), + link(CPid2), + + ets:insert(supervisor_deadlock,{fail_start,true}), + supervisor_deadlock:restart_child(), + timer:sleep(2000), % allow restart to happen before proceeding + + %% Terminating supervisor. + %% OTP-9549 fixes so this does not give a timetrap timeout - + %% i.e. that supervisor does not hang in restart loop. + terminate(Pid,shutdown), + + %% Check that child died with reason from 'restart' request above + check_exit_reason(CPid2, error), + undefined = whereis(sup_test), + ok. + +%%------------------------------------------------------------------------- terminate(Pid, Reason) when Reason =/= supervisor -> terminate(dummy, Pid, dummy, Reason). diff --git a/lib/stdlib/test/supervisor_deadlock.erl b/lib/stdlib/test/supervisor_deadlock.erl new file mode 100644 index 0000000000..288547a972 --- /dev/null +++ b/lib/stdlib/test/supervisor_deadlock.erl @@ -0,0 +1,45 @@ +-module(supervisor_deadlock). +-compile(export_all). + + +%%%----------------------------------------------------------------- +%%% gen_server callbacks +init([child]) -> + case ets:lookup(supervisor_deadlock,fail_start) of + [{fail_start, false}] -> + %% we must not fail on the first init, otherwise supervisor + %% terminates immediately + {ok, []}; + [{fail_start, true}] -> + %% Restart frequency is MaxR=8, MaxT=10, so this will + %% ensure that restart intensity is not reached -> restart + %% loop + timer:sleep(2000), % NOTE: this could be a gen_server call timeout + + {stop, error} + end. + +handle_call(_Req, _From, State) -> + {reply, ok, State}. + +%% Force a restart +handle_cast(restart, State) -> + {stop, error, State}. + +handle_info(_Msg, State) -> + {noreply, State}. + +terminate(_Reason, _State) -> + ok. + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + + +%%%----------------------------------------------------------------- +%%% Start child +start_child() -> + gen_server:start_link({local, ?MODULE}, ?MODULE, [child], []). + +restart_child() -> + gen_server:cast(supervisor_deadlock, restart). diff --git a/lib/test_server/src/test_server.erl b/lib/test_server/src/test_server.erl index 51754cb3b4..d7ce432786 100644 --- a/lib/test_server/src/test_server.erl +++ b/lib/test_server/src/test_server.erl @@ -44,7 +44,7 @@ -export([start_node/3, stop_node/1, wait_for_node/1, is_release_available/1]). -export([app_test/1, app_test/2]). -export([is_native/1]). --export([comment/1]). +-export([comment/1, make_priv_dir/0]). -export([os_type/0]). -export([run_on_shielded_node/2]). -export([is_cover/0,is_debug/0,is_commercial/0]). @@ -754,6 +754,25 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) -> {set_curr_conf,From,NewCurrConf} -> From ! {self(),set_curr_conf,ok}, run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,NewCurrConf); + {make_priv_dir,From} when CurrConf == undefined -> + From ! {self(),make_priv_dir,{error,no_priv_dir_in_config}}; + {make_priv_dir,From} -> + Result = + case proplists:get_value(priv_dir, element(2, CurrConf)) of + undefined -> + {error,no_priv_dir_in_config}; + PrivDir -> + case file:make_dir(PrivDir) of + ok -> + ok; + {error, eexist} -> + ok; + MkDirError -> + {error,{MkDirError,PrivDir}} + end + end, + From ! {self(),make_priv_dir,Result}, + run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf); {'EXIT',Pid,{Ref,Time,Value,Loc,Opts}} -> RetVal = {Time/1000000,Value,mod_loc(Loc),Opts,Comment}, run_test_case_msgloop(Ref,Pid,CaptureStdout,{true,RetVal},Comment,undefined); @@ -766,7 +785,7 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) -> %% timout during framework call spawn_fw_call(FwMod,FwFunc,CurrConf,Pid, {framework_error,{timetrap,TVal}}, - unknown,self(),Comment), + unknown,self()), run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate, Comment,undefined); Loc1 -> @@ -792,7 +811,7 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) -> %% and let the group leader go back to handle io. spawn_fw_call(Mod,Func,CurrConf,Pid, {timetrap_timeout,TVal}, - Loc1,self(),Comment), + Loc1,self()), undefined end, run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate, @@ -804,12 +823,12 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) -> %% timout during framework call spawn_fw_call(FwMod,FwFunc,CurrConf,Pid, {framework_error,{timetrap,TVal}}, - unknown,self(),Comment); + unknown,self()); Loc1 -> {Mod,_Func} = get_mf(Loc1), spawn_fw_call(Mod,InitOrEnd,CurrConf,Pid, {timetrap_timeout,TVal}, - Loc1,self(),Comment) + Loc1,self()) end, run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf); {testcase_aborted,AbortReason,AbortLoc} -> @@ -819,7 +838,7 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) -> %% abort during framework call spawn_fw_call(FwMod,FwFunc,CurrConf,Pid, {framework_error,ErrorMsg}, - unknown,self(),Comment), + unknown,self()), run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate, Comment,undefined); Loc1 -> @@ -842,7 +861,7 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) -> _ -> {Mod,Func} = get_mf(Loc1), spawn_fw_call(Mod,Func,CurrConf,Pid,ErrorMsg, - Loc1,self(),Comment), + Loc1,self()), undefined end, run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate, @@ -852,32 +871,55 @@ run_test_case_msgloop(Ref, Pid, CaptureStdout, Terminate, Comment, CurrConf) -> %% result of an exit(TestCase,kill) call, which is the %% only way to abort a testcase process that traps exits %% (see abort_current_testcase) - spawn_fw_call(undefined,undefined,CurrConf,Pid, + {Mod,Func} = case CurrConf of + {MF,_} -> MF; + _ -> {undefined,undefined} + end, + spawn_fw_call(Mod,Func,CurrConf,Pid, testcase_aborted_or_killed, - unknown,self(),Comment), + unknown,self()), run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf); {fw_error,{FwMod,FwFunc,FwError}} -> spawn_fw_call(FwMod,FwFunc,CurrConf,Pid,{framework_error,FwError}, - unknown,self(),Comment), + unknown,self()), run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf); _Other -> %% the testcase has terminated because of Reason (e.g. an exit %% because a linked process failed) - spawn_fw_call(undefined,undefined,CurrConf,Pid,Reason, - unknown,self(),Comment), + {Mod,Func} = case CurrConf of + {MF,_} -> MF; + _ -> {undefined,undefined} + end, + spawn_fw_call(Mod,Func,CurrConf,Pid,Reason,unknown,self()), run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf) end; {EndConfPid,{call_end_conf,Data,_Result}} -> case CurrConf of {EndConfPid,{Mod,Func},_Conf} -> {_Mod,_Func,TCPid,TCExitReason,Loc} = Data, - spawn_fw_call(Mod,Func,CurrConf,TCPid,TCExitReason,Loc,self(),Comment), + spawn_fw_call(Mod,Func,CurrConf,TCPid,TCExitReason,Loc,self()), run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,undefined); _ -> run_test_case_msgloop(Ref,Pid,CaptureStdout,Terminate,Comment,CurrConf) end; - {_FwCallPid,fw_notify_done,RetVal} -> + {_FwCallPid,fw_notify_done,{T,Value,Loc,Opts,AddToComment}} -> %% the framework has been notified, we're finished + RetVal = + case AddToComment of + undefined -> + {T,Value,Loc,Opts,Comment}; + _ -> + Comment1 = + if Comment == "" -> + AddToComment; + true -> + Comment ++ + test_server_ctrl:xhtml("<br>", + "<br />") ++ + AddToComment + end, + {T,Value,Loc,Opts,Comment1} + end, run_test_case_msgloop(Ref,Pid,CaptureStdout,{true,RetVal},Comment,undefined); {'EXIT',_FwCallPid,{fw_notify_done,Func,Error}} -> %% a framework function failed @@ -925,17 +967,20 @@ output(Msg,Sender) -> local_or_remote_apply({test_server_ctrl,output,[Msg,Sender]}). call_end_conf(Mod,Func,TCPid,TCExitReason,Loc,Conf,TVal) -> + %% Starter is also the group leader process Starter = self(), Data = {Mod,Func,TCPid,TCExitReason,Loc}, EndConfProc = fun() -> + group_leader(Starter, self()), Supervisor = self(), EndConfApply = fun() -> case catch apply(Mod,end_per_testcase,[Func,Conf]) of {'EXIT',Why} -> + timer:sleep(1), group_leader() ! {printout,12, - "ERROR! ~p:end_per_testcase(~p, ~p)" + "WARNING! ~p:end_per_testcase(~p, ~p)" " crashed!\n\tReason: ~p\n", [Mod,Func,Conf,Why]}; _ -> @@ -950,15 +995,23 @@ call_end_conf(Mod,Func,TCPid,TCExitReason,Loc,Conf,TVal) -> {'EXIT',Pid,Reason} -> Starter ! {self(),{call_end_conf,Data,{error,Reason}}} after TVal -> + exit(Pid, kill), + group_leader() ! {printout,12, + "WARNING! ~p:end_per_testcase(~p, ~p)" + " failed!\n\tReason: timetrap timeout" + " after ~w ms!\n", [Mod,Func,Conf,TVal]}, Starter ! {self(),{call_end_conf,Data,{error,timeout}}} end end, spawn_link(EndConfProc). spawn_fw_call(Mod,{init_per_testcase,Func},_,Pid,{timetrap_timeout,TVal}=Why, - Loc,SendTo,Comment) -> + Loc,SendTo) -> FwCall = fun() -> + %% set group leader so that printouts/comments + %% from the framework get printed in the logs + group_leader(SendTo, self()), Skip = {skip,{failed,{Mod,init_per_testcase,Why}}}, %% if init_per_testcase fails, the test case %% should be skipped @@ -970,12 +1023,12 @@ spawn_fw_call(Mod,{init_per_testcase,Func},_,Pid,{timetrap_timeout,TVal}=Why, end, %% finished, report back SendTo ! {self(),fw_notify_done, - {TVal/1000,Skip,Loc,[],Comment}} + {TVal/1000,Skip,Loc,[],undefined}} end, spawn_link(FwCall); spawn_fw_call(Mod,{end_per_testcase,Func},EndConf,Pid, - {timetrap_timeout,TVal}=Why,_Loc,SendTo,Comment) -> + {timetrap_timeout,TVal}=Why,_Loc,SendTo) -> %%! This is a temporary fix that keeps Test Server alive during %%! execution of a parallel test case group, when sometimes %%! this clause gets called with EndConf == undefined. See OTP-9594 @@ -987,6 +1040,9 @@ spawn_fw_call(Mod,{end_per_testcase,Func},EndConf,Pid, end, FwCall = fun() -> + %% set group leader so that printouts/comments + %% from the framework get printed in the logs + group_leader(SendTo, self()), {RetVal,Report} = case proplists:get_value(tc_status, EndConf1) of undefined -> @@ -998,6 +1054,10 @@ spawn_fw_call(Mod,{end_per_testcase,Func},EndConf,Pid, E = {failed,{Mod,end_per_testcase,Why}}, {Result,E} end, + group_leader() ! {printout,12, + "WARNING! ~p:end_per_testcase(~p, ~p)" + " failed!\n\tReason: timetrap timeout" + " after ~w ms!\n", [Mod,Func,EndConf,TVal]}, FailLoc = proplists:get_value(tc_fail_loc, EndConf1), case catch do_end_tc_call(Mod,Func, FailLoc, {Pid,Report,[EndConf1]}, Why) of @@ -1006,41 +1066,42 @@ spawn_fw_call(Mod,{end_per_testcase,Func},EndConf,Pid, _ -> ok end, - %% if end_per_testcase fails a warning should be - %% printed as comment - Comment1 = if Comment == "" -> - ""; - true -> - Comment ++ test_server_ctrl:xhtml("<br>", - "<br />") - end, - %% finished, report back + Warn = "<font color=\"red\">" + "WARNING: end_per_testcase timed out!</font>", + %% finished, report back (if end_per_testcase fails, a warning + %% should be printed as part of the comment) SendTo ! {self(),fw_notify_done, - {TVal/1000,RetVal,FailLoc,[], - [Comment1,"<font color=\"red\">" - "WARNING: end_per_testcase timed out!" - "</font>"]}} + {TVal/1000,RetVal,FailLoc,[],Warn}} end, spawn_link(FwCall); -spawn_fw_call(FwMod,FwFunc,_,_Pid,{framework_error,FwError},_,SendTo,_Comment) -> +spawn_fw_call(FwMod,FwFunc,_,_Pid,{framework_error,FwError},_,SendTo) -> FwCall = fun() -> + %% set group leader so that printouts/comments + %% from the framework get printed in the logs + group_leader(SendTo, self()), test_server_sup:framework_call(report, [framework_error, - {{FwMod,FwFunc},FwError}]), + {{FwMod,FwFunc}, + FwError}]), Comment = lists:flatten( io_lib:format("<font color=\"red\">" - "WARNING! ~w:~w failed!</font>", [FwMod,FwFunc])), + "WARNING! ~w:~w failed!</font>", + [FwMod,FwFunc])), %% finished, report back SendTo ! {self(),fw_notify_done, - {died,{error,{FwMod,FwFunc,FwError}},{FwMod,FwFunc},[],Comment}} + {died,{error,{FwMod,FwFunc,FwError}}, + {FwMod,FwFunc},[],Comment}} end, spawn_link(FwCall); -spawn_fw_call(Mod,Func,_,Pid,Error,Loc,SendTo,Comment) -> +spawn_fw_call(Mod,Func,_,Pid,Error,Loc,SendTo) -> FwCall = fun() -> + %% set group leader so that printouts/comments + %% from the framework get printed in the logs + group_leader(SendTo, self()), case catch fw_error_notify(Mod,Func,[], Error,Loc) of {'EXIT',FwErrorNotifyErr} -> @@ -1058,7 +1119,7 @@ spawn_fw_call(Mod,Func,_,Pid,Error,Loc,SendTo,Comment) -> ok end, %% finished, report back - SendTo ! {self(),fw_notify_done,{died,Error,Loc,Comment}} + SendTo ! {self(),fw_notify_done,{died,Error,Loc,[],undefined}} end, spawn_link(FwCall). @@ -1146,6 +1207,9 @@ run_test_case_eval(Mod, Func, Args0, Name, Ref, RunInit, exit({Ref,Time,Value,Loc,Opts}). run_test_case_eval1(Mod, Func, Args, Name, RunInit, TCCallback) -> + %% save current state in controller loop + sync_send(group_leader(),set_curr_conf,{{Mod,Func},hd(Args)}, + 5000, fun() -> exit(no_answer_from_group_leader) end), case RunInit of run_init -> put(test_server_init_or_end_conf,{init_per_testcase,Func}), @@ -1204,8 +1268,8 @@ run_test_case_eval1(Mod, Func, Args, Name, RunInit, TCCallback) -> %% call user callback function if defined EndConf1 = user_callback(TCCallback, Mod, Func, 'end', EndConf), %% update current state in controller loop - sync_send(group_leader(),set_curr_conf,EndConf1, - 5000, fun() -> exit(no_answer_from_group_leader) end), + sync_send(group_leader(),set_curr_conf,EndConf1, 5000, + fun() -> exit(no_answer_from_group_leader) end), {FWReturn1,TSReturn1,EndConf2} = case end_per_testcase(Mod, Func, EndConf1) of SaveCfg1={save_config,_} -> @@ -1530,8 +1594,18 @@ get_loc(Pid) -> lists:foreach(fun({Key,Val}) -> put(Key, Val) end, Dict), Stk = [rewrite_loc_item(Loc) || Loc <- Stk0], case get(test_server_loc) of - undefined -> put(test_server_loc, Stk); - _ -> ok + undefined -> + put(test_server_loc, Stk); + {Suite,Case} -> + %% location info unknown, check if {Suite,Case,Line} + %% is available in stacktrace. and if so, use stacktrace + %% instead of currect test_server_loc + case [match || {S,C,_L} <- Stk, S == Suite, C == Case] of + [match|_] -> put(test_server_loc, Stk); + _ -> ok + end; + _ -> + ok end, get_loc(). @@ -1561,13 +1635,20 @@ mod_loc(Loc) -> %% handle diff line num versions case Loc of [{{_M,_F},_L}|_] -> - [{?pl2a(M),F,L} || {{M,F},L} <- Loc]; + [begin if L /= 0 -> {?pl2a(M),F,L}; + true -> {?pl2a(M),F} end end || {{M,F},L} <- Loc]; [{_M,_F}|_] -> [{?pl2a(M),F} || {M,F} <- Loc]; + {{M,F},0} -> + [{?pl2a(M),F}]; {{M,F},L} -> [{?pl2a(M),F,L}]; {M,ForL} -> [{?pl2a(M),ForL}]; + {M,F,0} -> + [{M,F}]; + [{M,F,0}|Stack] -> + [{M,F}|Stack]; _ -> Loc end. @@ -2528,11 +2609,23 @@ read_comment() -> MsgLooper = group_leader(), MsgLooper ! {read_comment,self()}, receive - {MsgLooper,read_comment,Comment} -> - Comment + {MsgLooper,read_comment,Comment} -> Comment + after + 5000 -> "" + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% make_priv_dir() -> ok +%% +%% Order test server to create the private directory +%% for the current test case. +make_priv_dir() -> + MsgLooper = group_leader(), + group_leader() ! {make_priv_dir,self()}, + receive + {MsgLooper,make_priv_dir,Result} -> Result after - 5000 -> - "" + 5000 -> error end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/lib/test_server/src/test_server_ctrl.erl b/lib/test_server/src/test_server_ctrl.erl index 3432b3bc8e..79c45de071 100644 --- a/lib/test_server/src/test_server_ctrl.erl +++ b/lib/test_server/src/test_server_ctrl.erl @@ -164,6 +164,7 @@ -export([start_get_totals/1, stop_get_totals/0]). -export([get_levels/0, set_levels/3]). -export([multiply_timetraps/1, scale_timetraps/1, get_timetrap_parameters/0]). +-export([create_priv_dir/1]). -export([cover/2, cover/3, cover/7, cross_cover_analyse/1, cross_cover_analyse/2, trc/1, stop_trace/0]). -export([testcase_callback/1]). @@ -219,8 +220,8 @@ -define(user_skip_color, "#FF8000"). -record(state,{jobs=[],levels={1,19,10}, - multiply_timetraps=1,scale_timetraps=true, - finish=false, + multiply_timetraps=1, scale_timetraps=true, + create_priv_dir=auto_per_run, finish=false, target_info, trc=false, cover=false, wait_for_node=[], testcase_callback=undefined, idle_notify=[], get_totals=false, random_seed=undefined}). @@ -506,6 +507,9 @@ scale_timetraps(Bool) -> get_timetrap_parameters() -> controller_call(get_timetrap_parameters). +create_priv_dir(Value) -> + controller_call({create_priv_dir,Value}). + trc(TraceFile) -> controller_call({trace,TraceFile}, 2*?ACCEPT_TIMEOUT). @@ -646,8 +650,8 @@ init([Param]) -> contact_main_target(local) -> %% When used by a general framework, global registration of %% test_server should not be required. - case os:getenv("TEST_SERVER_FRAMEWORK") of - FW when FW =:= false; FW =:= "undefined" -> + case get_fw_mod(undefined) of + undefined -> %% Local target! The global test_server process implemented by %% test_server.erl will not be started, so we simulate it by %% globally registering this process instead. @@ -811,6 +815,7 @@ handle_call({add_job,Dir,Name,TopCase,Skip}, _From, State) -> [SpecName,{State#state.multiply_timetraps, State#state.scale_timetraps}], LogDir, Name, State#state.levels, + State#state.create_priv_dir, State#state.testcase_callback, ExtraTools1), NewJobs = [{Name,Pid}|State#state.jobs], {reply, ok, State#state{jobs=NewJobs}}; @@ -820,6 +825,7 @@ handle_call({add_job,Dir,Name,TopCase,Skip}, _From, State) -> [SpecList,{State#state.multiply_timetraps, State#state.scale_timetraps}], LogDir, Name, State#state.levels, + State#state.create_priv_dir, State#state.testcase_callback, ExtraTools1), NewJobs = [{Name,Pid}|State#state.jobs], {reply, ok, State#state{jobs=NewJobs}}; @@ -837,6 +843,7 @@ handle_call({add_job,Dir,Name,TopCase,Skip}, _From, State) -> {State#state.multiply_timetraps, State#state.scale_timetraps}], LogDir, Name, State#state.levels, + State#state.create_priv_dir, State#state.testcase_callback, ExtraTools1), NewJobs = [{Name,Pid}|State#state.jobs], {reply, ok, State#state{jobs=NewJobs}} @@ -1045,6 +1052,18 @@ handle_call({cover,App,Analyse}, _From, State) -> {reply,ok,State#state{cover={App,Analyse}}}; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% handle_call({create_priv_dir,Value}, _, State) -> ok | {error,Reason} +%% +%% Set create_priv_dir to either auto_per_run (create common priv dir once +%% per test run), manual_per_tc (the priv dir name will be unique for each +%% test case, but the user has to call test_server:make_priv_dir/0 to create +%% it), or auto_per_tc (unique priv dir created automatically for each test +%% case). + +handle_call({create_priv_dir,Value}, _From, State) -> + {reply,ok,State#state{create_priv_dir=Value}}; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% handle_call({testcase_callback,{Mod,Func}}, _, State) -> ok | {error,Reason} %% %% Add a callback function that will be called before and after every @@ -1301,7 +1320,12 @@ terminate(_Reason, State) -> end, kill_all_jobs(State#state.jobs), test_server_node:stop(State#state.target_info), - test_server_h:restore(), + case lists:keysearch(sasl, 1, application:which_applications()) of + {value,_} -> + test_server_h:restore(); + _ -> + ok + end, ok. kill_all_jobs([{_Name,JobPid}|Jobs]) -> @@ -1316,7 +1340,7 @@ kill_all_jobs([]) -> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% spawn_tester(Mod, Func, Args, Dir, Name, Levels, +%% spawn_tester(Mod, Func, Args, Dir, Name, Levels, CreatePrivDir, %% TestCaseCallback, ExtraTools) -> Pid %% Mod = atom() %% Func = atom() @@ -1324,6 +1348,7 @@ kill_all_jobs([]) -> %% Dir = string() %% Name = string() %% Levels = {integer(),integer(),integer()} +%% CreatePrivDir = auto_per_run | manual_per_tc | auto_per_tc %% TestCaseCallback = {CBMod,CBFunc} | undefined %% ExtraTools = [ExtraTool,...] %% ExtraTool = CoverInfo | TraceInfo | RandomSeed @@ -1334,14 +1359,15 @@ kill_all_jobs([]) -> %% When the named function is done executing, a summary of the results %% is printed to the log files. -spawn_tester(Mod, Func, Args, Dir, Name, Levels, TCCallback, ExtraTools) -> +spawn_tester(Mod, Func, Args, Dir, Name, Levels, + CreatePrivDir, TCCallback, ExtraTools) -> spawn_link( fun() -> init_tester(Mod, Func, Args, Dir, Name, Levels, - TCCallback, ExtraTools) + CreatePrivDir, TCCallback, ExtraTools) end). init_tester(Mod, Func, Args, Dir, Name, {SumLev,MajLev,MinLev}, - TCCallback, ExtraTools) -> + CreatePrivDir, TCCallback, ExtraTools) -> process_flag(trap_exit, true), put(test_server_name, Name), put(test_server_dir, Dir), @@ -1352,8 +1378,21 @@ init_tester(Mod, Func, Args, Dir, Name, {SumLev,MajLev,MinLev}, put(test_server_summary_level, SumLev), put(test_server_major_level, MajLev), put(test_server_minor_level, MinLev), + put(test_server_create_priv_dir, CreatePrivDir), put(test_server_random_seed, proplists:get_value(random_seed, ExtraTools)), put(test_server_testcase_callback, TCCallback), + case os:getenv("TEST_SERVER_FRAMEWORK") of + FW when FW =:= false; FW =:= "undefined" -> + put(test_server_framework, '$none'); + FW -> + put(test_server_framework_name, list_to_atom(FW)), + case os:getenv("TEST_SERVER_FRAMEWORK_NAME") of + FWName when FWName =:= false; FWName =:= "undefined" -> + put(test_server_framework_name, '$none'); + FWName -> + put(test_server_framework_name, list_to_atom(FWName)) + end + end, %% before first print, read and set logging options LogOpts = test_server_sup:framework_call(get_logopts, [], []), put(test_server_logopts, LogOpts), @@ -1385,7 +1424,7 @@ init_tester(Mod, Func, Args, Dir, Name, {SumLev,MajLev,MinLev}, end, OkN = get(test_server_ok), FailedN = get(test_server_failed), - print(html,"<tr><td></td><td><b>TOTAL</b></td><td></td><td></td>" + print(html,"<tr><td></td><td><b>TOTAL</b></td><td></td><td></td><td></td>" "<td>~.3fs</td><td><b>~s</b></td><td>~p Ok, ~p Failed~s of ~p</td></tr>\n", [Time,SuccessStr,OkN,FailedN,SkipStr,OkN+FailedN+SkippedN]). @@ -1673,11 +1712,7 @@ do_test_cases(TopCases, SkipCases, Config, TimetrapData) when is_list(TopCases), is_tuple(TimetrapData) -> {ok,TestDir} = start_log_file(), - FwMod = - case os:getenv("TEST_SERVER_FRAMEWORK") of - FW when FW =:= false; FW =:= "undefined" -> ?MODULE; - FW -> list_to_atom(FW) - end, + FwMod = get_fw_mod(?MODULE), case collect_all_cases(TopCases, SkipCases) of {error,Why} -> print(1, "Error starting: ~p", [Why]), @@ -1770,8 +1805,9 @@ do_test_cases(TopCases, SkipCases, "<p>~s</p>\n" ++ xhtml("<table bgcolor=\"white\" border=\"3\" cellpadding=\"5\">", "<table>") ++ - "<tr><th>Num</th><th>Module</th><th>Case</th><th>Log</th>" - "<th>Time</th><th>Result</th><th>Comment</th></tr>\n", + "<tr><th>Num</th><th>Module</th><th>Group</th>" ++ + "<th>Case</th><th>Log</th><th>Time</th><th>Result</th>" ++ + "<th>Comment</th></tr>\n", [print_if_known(N, {"<i>Executing <b>~p</b> test cases...</i>\n",[N]}, {"",[]})]), print(html, xhtml("<br>", "<br />")), @@ -1812,7 +1848,7 @@ do_test_cases(TopCase, SkipCases, Config, TimetrapSpec) -> %% Creates the log directories, the major log file and the html log file. %% The log files are initialized with some header information. %% -%% The name of the log directory will be <Name>.LOGS/run.<Date>/ where +%% The name of the log directory will be <Name>.logs/run.<Date>/ where %% Name is the test suite name and Date is the current date and time. start_log_file() -> @@ -2101,17 +2137,17 @@ add_init_and_end_per_suite([{make,_,_}=Case|Cases], LastMod, LastRef, FwMod) -> add_init_and_end_per_suite([{skip_case,{{Mod,all},_}}=Case|Cases], LastMod, LastRef, FwMod) when Mod =/= LastMod -> {PreCases, NextMod, NextRef} = - do_add_end_per_suite_and_skip(LastMod, LastRef, Mod), + do_add_end_per_suite_and_skip(LastMod, LastRef, Mod, FwMod), PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef, FwMod)]; add_init_and_end_per_suite([{skip_case,{{Mod,_},_}}=Case|Cases], LastMod, LastRef, FwMod) when Mod =/= LastMod -> {PreCases, NextMod, NextRef} = - do_add_init_and_end_per_suite(LastMod, LastRef, Mod), + do_add_init_and_end_per_suite(LastMod, LastRef, Mod, FwMod), PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef, FwMod)]; add_init_and_end_per_suite([{skip_case,{conf,_,{Mod,_},_}}=Case|Cases], LastMod, LastRef, FwMod) when Mod =/= LastMod -> {PreCases, NextMod, NextRef} = - do_add_init_and_end_per_suite(LastMod, LastRef, Mod), + do_add_init_and_end_per_suite(LastMod, LastRef, Mod, FwMod), PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef, FwMod)]; add_init_and_end_per_suite([{skip_case,_}=Case|Cases], LastMod, LastRef, FwMod) -> [Case|add_init_and_end_per_suite(Cases, LastMod, LastRef, FwMod)]; @@ -2123,7 +2159,7 @@ add_init_and_end_per_suite([{conf,Ref,Props,{FwMod,Func}}=Case|Cases], LastMod, case proplists:get_value(suite, Props) of Suite when Suite =/= undefined, Suite =/= LastMod -> {PreCases, NextMod, NextRef} = - do_add_init_and_end_per_suite(LastMod, LastRef, Suite), + do_add_init_and_end_per_suite(LastMod, LastRef, Suite, FwMod), Case1 = {conf,Ref,proplists:delete(suite,Props),{FwMod,Func}}, PreCases ++ [Case1|add_init_and_end_per_suite(Cases, NextMod, NextRef, FwMod)]; @@ -2133,19 +2169,19 @@ add_init_and_end_per_suite([{conf,Ref,Props,{FwMod,Func}}=Case|Cases], LastMod, add_init_and_end_per_suite([{conf,_,_,{Mod,_}}=Case|Cases], LastMod, LastRef, FwMod) when Mod =/= LastMod, Mod =/= FwMod -> {PreCases, NextMod, NextRef} = - do_add_init_and_end_per_suite(LastMod, LastRef, Mod), + do_add_init_and_end_per_suite(LastMod, LastRef, Mod, FwMod), PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef, FwMod)]; add_init_and_end_per_suite([{conf,_,_,_}=Case|Cases], LastMod, LastRef, FwMod) -> [Case|add_init_and_end_per_suite(Cases, LastMod, LastRef, FwMod)]; add_init_and_end_per_suite([{Mod,_}=Case|Cases], LastMod, LastRef, FwMod) when Mod =/= LastMod, Mod =/= FwMod -> {PreCases, NextMod, NextRef} = - do_add_init_and_end_per_suite(LastMod, LastRef, Mod), + do_add_init_and_end_per_suite(LastMod, LastRef, Mod, FwMod), PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef, FwMod)]; add_init_and_end_per_suite([{Mod,_,_}=Case|Cases], LastMod, LastRef, FwMod) when Mod =/= LastMod, Mod =/= FwMod -> {PreCases, NextMod, NextRef} = - do_add_init_and_end_per_suite(LastMod, LastRef, Mod), + do_add_init_and_end_per_suite(LastMod, LastRef, Mod, FwMod), PreCases ++ [Case|add_init_and_end_per_suite(Cases, NextMod, NextRef, FwMod)]; add_init_and_end_per_suite([Case|Cases], LastMod, LastRef, FwMod)-> [Case|add_init_and_end_per_suite(Cases, LastMod, LastRef, FwMod)]; @@ -2153,10 +2189,23 @@ add_init_and_end_per_suite([], _LastMod, undefined, _FwMod) -> []; add_init_and_end_per_suite([], _LastMod, skipped_suite, _FwMod) -> []; -add_init_and_end_per_suite([], LastMod, LastRef, _FwMod) -> - [{conf,LastRef,[],{LastMod,end_per_suite}}]. +add_init_and_end_per_suite([], LastMod, LastRef, FwMod) -> + %% we'll add end_per_suite here even if it's not exported + %% (and simply let the call fail if it's missing) + case erlang:function_exported(LastMod, end_per_suite, 1) of + true -> + [{conf,LastRef,[],{LastMod,end_per_suite}}]; + false -> + %% let's call a "fake" end_per_suite if it exists + case erlang:function_exported(FwMod, end_per_suite, 1) of + true -> + [{conf,LastRef,[{suite,LastMod}],{FwMod,end_per_suite}}]; + false -> + [{conf,LastRef,[],{LastMod,end_per_suite}}] + end + end. -do_add_init_and_end_per_suite(LastMod, LastRef, Mod) -> +do_add_init_and_end_per_suite(LastMod, LastRef, Mod, FwMod) -> case code:is_loaded(Mod) of false -> code:load_file(Mod); _ -> ok @@ -2167,7 +2216,16 @@ do_add_init_and_end_per_suite(LastMod, LastRef, Mod) -> Ref = make_ref(), {[{conf,Ref,[],{Mod,init_per_suite}}],Mod,Ref}; false -> - {[],Mod,undefined} + %% let's call a "fake" init_per_suite if it exists + case erlang:function_exported(FwMod, init_per_suite, 1) of + true -> + Ref = make_ref(), + {[{conf,Ref,[{suite,Mod}], + {FwMod,init_per_suite}}],Mod,Ref}; + false -> + {[],Mod,undefined} + end + end, Cases = if LastRef==undefined -> @@ -2175,20 +2233,44 @@ do_add_init_and_end_per_suite(LastMod, LastRef, Mod) -> LastRef==skipped_suite -> Init; true -> - %% Adding end_per_suite here without checking if the - %% function is actually exported. This is because a - %% conf case must have an end case - so if it doesn't - %% exist, it will only fail... - [{conf,LastRef,[],{LastMod,end_per_suite}}|Init] + %% we'll add end_per_suite here even if it's not exported + %% (and simply let the call fail if it's missing) + case erlang:function_exported(LastMod, end_per_suite, 1) of + true -> + [{conf,LastRef,[],{LastMod,end_per_suite}}|Init]; + false -> + %% let's call a "fake" end_per_suite if it exists + case erlang:function_exported(FwMod, end_per_suite, 1) of + true -> + [{conf,LastRef,[{suite,Mod}], + {FwMod,end_per_suite}}|Init]; + false -> + [{conf,LastRef,[],{LastMod,end_per_suite}}|Init] + end + end end, {Cases,NextMod,NextRef}. -do_add_end_per_suite_and_skip(LastMod, LastRef, Mod) -> +do_add_end_per_suite_and_skip(LastMod, LastRef, Mod, FwMod) -> case LastRef of No when No==undefined ; No==skipped_suite -> {[],Mod,skipped_suite}; _Ref -> - {[{conf,LastRef,[],{LastMod,end_per_suite}}],Mod,skipped_suite} + case erlang:function_exported(LastMod, end_per_suite, 1) of + true -> + {[{conf,LastRef,[],{LastMod,end_per_suite}}], + Mod,skipped_suite}; + false -> + case erlang:function_exported(FwMod, end_per_suite, 1) of + true -> + %% let's call "fake" end_per_suite if it exists + {[{conf,LastRef,[],{FwMod,end_per_suite}}], + Mod,skipped_suite}; + false -> + {[{conf,LastRef,[],{LastMod,end_per_suite}}], + Mod,skipped_suite} + end + end end. @@ -2748,7 +2830,15 @@ run_test_cases_loop([{conf,Ref,Props,{Mod,Func}}|_Cases]=Cs0, {skipped,TcSkip}, {failed,TcFail}]}] end, - TSDirs = [{priv_dir,get(test_server_priv_dir)},{data_dir,get_data_dir(Mod)}], + + case get(test_server_create_priv_dir) of + auto_per_run -> % use common priv_dir + TSDirs = [{priv_dir,get(test_server_priv_dir)}, + {data_dir,get_data_dir(Mod)}]; + _ -> + TSDirs = [{data_dir,get_data_dir(Mod)}] + end, + ActualCfg = if not StartConf -> update_config(hd(Config), TSDirs ++ CfgProps); @@ -2758,7 +2848,8 @@ run_test_cases_loop([{conf,Ref,Props,{Mod,Func}}|_Cases]=Cs0, end, Mode0), update_config(hd(Config), TSDirs ++ [{tc_group_path,GroupPath} | CfgProps]) - end, + end, + CurrMode = curr_mode(Ref, Mode0, Mode), ConfCaseResult = run_test_case(Ref, 0, Mod, Func, [ActualCfg], skip_init, target, TimetrapData, CurrMode), @@ -2910,8 +3001,13 @@ run_test_cases_loop([{conf,_Ref,_Props,_X}=Conf|_Cases0], run_test_cases_loop([{Mod,Case}|Cases], Config, TimetrapData, Mode, Status) -> ActualCfg = - update_config(hd(Config), [{priv_dir,get(test_server_priv_dir)}, - {data_dir,get_data_dir(Mod)}]), + case get(test_server_create_priv_dir) of + auto_per_run -> + update_config(hd(Config), [{priv_dir,get(test_server_priv_dir)}, + {data_dir,get_data_dir(Mod)}]); + _ -> + update_config(hd(Config), [{data_dir,get_data_dir(Mod)}]) + end, run_test_cases_loop([{Mod,Case,[ActualCfg]}|Cases], Config, TimetrapData, Mode, Status); @@ -3248,16 +3344,21 @@ skip_case1(Type, CaseNum, Mod, Func, Comment, Mode) -> print(major, "=started ~s", [lists:flatten(timestamp_get(""))]), print(major, "=result skipped: ~s", [Comment1]), print(2,"*** Skipping test case #~w ~p ***", [CaseNum,{Mod,Func}]), - TR = xhtml("<tr valign=\"top\">", ["<tr class=\"",odd_or_even(),"\">"]), + TR = xhtml("<tr valign=\"top\">", ["<tr class=\"",odd_or_even(),"\">"]), + GroupName = case get_name(Mode) of + undefined -> ""; + Name -> cast_to_list(Name) + end, print(html, TR ++ "<td>" ++ Col0 ++ "~s" ++ Col1 ++ "</td>" "<td>" ++ Col0 ++ "~p" ++ Col1 ++ "</td>" + "<td>" ++ Col0 ++ "~s" ++ Col1 ++ "</td>" "<td>" ++ Col0 ++ "~p" ++ Col1 ++ "</td>" "<td>" ++ Col0 ++ "< >" ++ Col1 ++ "</td>" "<td>" ++ Col0 ++ "0.000s" ++ Col1 ++ "</td>" "<td><font color=\"~s\">SKIPPED</font></td>" "<td>~s</td></tr>\n", - [num2str(CaseNum),Mod,Func,ResultCol,Comment1]), + [num2str(CaseNum),fw_name(Mod),GroupName,Func,ResultCol,Comment1]), if CaseNum > 0 -> {US,AS} = get(test_server_skipped), case Type of @@ -3627,9 +3728,14 @@ run_test_case1(Ref, Num, Mod, Func, Args, RunInit, Where, %% if this runs on a parallel test case process, %% copy the dictionary from the main process do_if_parallel(Main, fun() -> process_flag(trap_exit, true) end, ok), - CopyDict = fun() -> lists:foreach(fun({Key,Val}) -> put(Key, Val) end, State) end, + CopyDict = fun() -> lists:foreach(fun({Key,Val}) -> + put(Key, Val) + end, State) + end, do_if_parallel(Main, CopyDict, ok), - do_if_parallel(Main, fun() -> put(test_server_common_io_handler, {tc,Main}) end, ok), + do_if_parallel(Main, fun() -> + put(test_server_common_io_handler, {tc,Main}) + end, ok), %% if io is being buffered, send start io session message %% (no matter if case runs on parallel or main process) case get(test_server_common_io_handler) of @@ -3649,23 +3755,55 @@ run_test_case1(Ref, Num, Mod, Func, Args, RunInit, Where, MinorBase = filename:basename(MinorName), print(major, "=logfile ~s", [filename:basename(MinorName)]), - Args1 = [[{tc_logfile,MinorName} | proplists:delete(tc_logfile,hd(Args))]], - test_server_sup:framework_call(report, [tc_start,{{?pl2a(Mod),Func},MinorName}]), + UpdatedArgs = + %% maybe create unique private directory for test case or config func + case get(test_server_create_priv_dir) of + auto_per_run -> + update_config(hd(Args), [{tc_logfile,MinorName}]); + PrivDirMode -> + RunDir = filename:dirname(MinorName), + Ext = + if Num == 0 -> + {_,S,Us} = now(), + lists:flatten(io_lib:format(".~w.~w", [S,Us])); + true -> + %% create unique private directory for test case + RunDir = filename:dirname(MinorName), + lists:flatten(io_lib:format(".~w", [Num])) + end, + PrivDir = filename:join(RunDir, ?priv_dir) ++ Ext, + if PrivDirMode == auto_per_tc -> + ok = file:make_dir(PrivDir); + PrivDirMode == manual_per_tc -> + ok + end, + update_config(hd(Args), [{priv_dir,PrivDir++"/"}, + {tc_logfile,MinorName}]) + end, + + test_server_sup:framework_call(report, + [tc_start,{{?pl2a(Mod),Func},MinorName}]), print_props((RunInit==skip_init), get_props(Mode)), + GroupName = case get_name(Mode) of + undefined -> ""; + Name -> cast_to_list(Name) + end, print(major, "=started ~s", [lists:flatten(timestamp_get(""))]), {{Col0,Col1},Style} = get_font_style((RunInit==run_init), Mode), TR = xhtml("<tr valign=\"top\">", ["<tr class=\"",odd_or_even(),"\">"]), print(html, TR ++ "<td>" ++ Col0 ++ "~s" ++ Col1 ++ "</td>" "<td>" ++ Col0 ++ "~p" ++ Col1 ++ "</td>" + "<td>" ++ Col0 ++ "~s" ++ Col1 ++ "</td>" "<td><a href=\"~s\">~p</a></td>" "<td><a href=\"~s#top\"><</a> <a href=\"~s#end\">></a></td>", - [num2str(Num),Mod,MinorBase,Func,MinorBase,MinorBase]), + [num2str(Num),fw_name(Mod),GroupName,MinorBase,Func, + MinorBase,MinorBase]), do_if_parallel(Main, ok, fun erlang:yield/0), %% run the test case {Result,DetectedFail,ProcsBefore,ProcsAfter} = - run_test_case_apply(Num, Mod, Func, Args1, get_name(Mode), + run_test_case_apply(Num, Mod, Func, [UpdatedArgs], get_name(Mode), RunInit, Where, TimetrapData), {Time,RetVal,Loc,Opts,Comment} = case Result of @@ -4107,6 +4245,46 @@ progress(ok, _CaseNum, Mod, Func, _Loc, RetVal, Time, %%-------------------------------------------------------------------- %% various help functions +get_fw_mod(Mod) -> + case get(test_server_framework) of + undefined -> + case os:getenv("TEST_SERVER_FRAMEWORK") of + FW when FW =:= false; FW =:= "undefined" -> + Mod; + FW -> + list_to_atom(FW) + end; + '$none' -> Mod; + FW -> FW + end. + +fw_name(?MODULE) -> + test_server; +fw_name(Mod) -> + case get(test_server_framework_name) of + undefined -> + case get_fw_mod(undefined) of + undefined -> + Mod; + Mod -> + case os:getenv("TEST_SERVER_FRAMEWORK_NAME") of + FWName when FWName =:= false; FWName =:= "undefined" -> + Mod; + FWName -> + list_to_atom(FWName) + end; + _ -> + Mod + end; + '$none' -> + Mod; + FWName -> + case get_fw_mod(Mod) of + Mod -> FWName; + _ -> Mod + end + end. + if_auto_skip(Reason={failed,{_,init_per_testcase,_}}, True, _False) -> {Reason,True()}; if_auto_skip({_T,{skip,Reason={failed,{_,init_per_testcase,_}}},_Opts}, True, _False) -> @@ -4210,8 +4388,8 @@ get_font_style1(default) -> %% set to false. format_exception(Reason={_Error,Stack}) when is_list(Stack) -> - case os:getenv("TEST_SERVER_FRAMEWORK") of - FW when FW =:= false; FW =:= "undefined" -> + case get_fw_mod(undefined) of + undefined -> case application:get_env(test_server, format_exception) of {ok,false} -> {"~p",Reason}; @@ -4219,7 +4397,7 @@ format_exception(Reason={_Error,Stack}) when is_list(Stack) -> do_format_exception(Reason) end; FW -> - case application:get_env(list_to_atom(FW), format_exception) of + case application:get_env(FW, format_exception) of {ok,false} -> {"~p",Reason}; _ -> @@ -4815,8 +4993,8 @@ collect_case([Case | Cases], St, Acc) -> collect_case(Cases, NewSt, Acc ++ FlatCases). collect_case_invoke(Mod, Case, MFA, St) -> - case os:getenv("TEST_SERVER_FRAMEWORK") of - FW when FW =:= false; FW =:= "undefined" -> + case get_fw_mod(undefined) of + undefined -> case catch apply(Mod, Case, [suite]) of {'EXIT',_} -> {ok,[MFA],St}; @@ -4824,7 +5002,9 @@ collect_case_invoke(Mod, Case, MFA, St) -> collect_subcases(Mod, Case, MFA, St, Suite) end; _ -> - Suite = test_server_sup:framework_call(get_suite, [?pl2a(Mod),Case], []), + Suite = test_server_sup:framework_call(get_suite, + [?pl2a(Mod),Case], + []), collect_subcases(Mod, Case, MFA, St, Suite) end. diff --git a/lib/test_server/src/test_server_h.erl b/lib/test_server/src/test_server_h.erl index e423863b99..6707f98109 100644 --- a/lib/test_server/src/test_server_h.erl +++ b/lib/test_server/src/test_server_h.erl @@ -79,10 +79,21 @@ set_group_leader() -> handle_event({_Type, GL, _Msg}, State) when node(GL)/=node() -> {ok, State}; handle_event({Tag, _GL, {_Pid, Type, _Report}} = Event, State) -> - case report(Tag, Type) of - sasl -> - tag(State#state.testcase), - sasl_report_tty_h:handle_event(Event, State#state.sasl); + SASL = lists:keyfind(sasl, 1, application:which_applications()), + case report_receiver(Tag, Type) of + sasl when SASL /= false -> + {ok,ErrLogType} = application:get_env(sasl, errlog_type), + SReport = sasl_report:format_report(group_leader(), ErrLogType, + tag_event(Event)), + if is_list(SReport) -> + tag(State#state.testcase), + sasl_report_tty_h:handle_event(Event, + State#state.sasl); + true -> %% Report is an atom if no logging is to be done + ignore + end; + sasl -> %% SASL not running + ignore; kernel -> tag(State#state.testcase), error_logger_tty_h:handle_event(Event, State#state.kernel); @@ -111,19 +122,22 @@ terminate(_Reason, _State) -> code_change(_OldVsn, State, _Extra) -> {ok, State}. -report(error_report, supervisor_report) -> sasl; -report(error_report, crash_report) -> sasl; -report(info_report, progress) -> sasl; -report(error, _) -> kernel; -report(error_report, _) -> kernel; -report(warning_msg, _) -> kernel; -report(warning_report, _) -> kernel; -report(info, _) -> kernel; -report(info_msg, _) -> kernel; -report(info_report, _) -> kernel; -report(_, _) -> none. +report_receiver(error_report, supervisor_report) -> sasl; +report_receiver(error_report, crash_report) -> sasl; +report_receiver(info_report, progress) -> sasl; +report_receiver(error, _) -> kernel; +report_receiver(error_report, _) -> kernel; +report_receiver(warning_msg, _) -> kernel; +report_receiver(warning_report, _) -> kernel; +report_receiver(info, _) -> kernel; +report_receiver(info_msg, _) -> kernel; +report_receiver(info_report, _) -> kernel; +report_receiver(_, _) -> none. tag({M,F,A}) when is_atom(M), is_atom(F), is_integer(A) -> io:format(user, "~n=TESTCASE: ~p:~p/~p", [M,F,A]); tag(Testcase) -> io:format(user, "~n=TESTCASE: ~p", [Testcase]). + +tag_event(Event) -> + {calendar:local_time(), Event}. diff --git a/lib/test_server/src/ts.erl b/lib/test_server/src/ts.erl index 729a2b11fc..7e48a11f33 100644 --- a/lib/test_server/src/ts.erl +++ b/lib/test_server/src/ts.erl @@ -301,7 +301,15 @@ run(List, Opts) when is_list(List), is_list(Opts) -> run(Testspec, Config) when is_atom(Testspec), is_list(Config) -> Options=check_test_get_opts(Testspec, Config), File=atom_to_list(Testspec), - run_test(File, [{spec,[File++".spec"]}], Options); + Spec = case code:lib_dir(Testspec) of + {error, bad_name} when Testspec /= emulator, + Testspec /= system, + Testspec /= epmd -> + create_skip_spec(Testspec, tests(Testspec)); + _ -> + File++".spec" + end, + run_test(File, [{spec,[Spec]}], Options); %% Runs one module in a spec (interactive) run(Testspec, Mod) when is_atom(Testspec), is_atom(Mod) -> run_test({atom_to_list(Testspec), Mod}, @@ -332,6 +340,21 @@ run(Testspec, Mod, Case, Config) when is_atom(Testspec), Args = [{suite,atom_to_list(Mod)}, {testcase,atom_to_list(Case)}], run_test(atom_to_list(Testspec), Args, Options). +%% Create a spec to skip all SUITES, this is used when the application +%% to be tested is not part of the OTP release to be tested. +create_skip_spec(Testspec, SuitesToSkip) -> + {ok,Cwd} = file:get_cwd(), + TestspecString = atom_to_list(Testspec), + Specname = TestspecString++"_skip.spec", + {ok,D} = file:open(filename:join([filename:dirname(Cwd), + TestspecString++"_test",Specname]), + [write]), + TestDir = "\"../"++TestspecString++"_test\"", + io:format(D,"{suites, "++TestDir++", all}.~n",[]), + io:format(D,"{skip_suites, "++TestDir++", ~w, \"Skipped as application" + " is not in path!\"}.",[SuitesToSkip]), + Specname. + %% Check testspec to be valid and get possible Options %% from the config. check_test_get_opts(Testspec, Config) -> diff --git a/lib/test_server/vsn.mk b/lib/test_server/vsn.mk index 88e3856cf4..a1f4559083 100644 --- a/lib/test_server/vsn.mk +++ b/lib/test_server/vsn.mk @@ -1 +1 @@ -TEST_SERVER_VSN = 3.5 +TEST_SERVER_VSN = 3.5.1 diff --git a/lib/tools/test/xref_SUITE.erl b/lib/tools/test/xref_SUITE.erl index e0876381ca..78e49044a5 100644 --- a/lib/tools/test/xref_SUITE.erl +++ b/lib/tools/test/xref_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2011. All Rights Reserved. +%% Copyright Ericsson AB 2000-2012. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -2141,17 +2141,17 @@ basic(Conf) when is_list(Conf) -> ?line {ok, _} = eval("components (Mod) E", [[m1,m2,m3]], S), ?line {ok, _} = eval("components closure (Mod) E", [[m1,m2,m3]], S), ?line {ok, _} = eval("condensation (Mod) E", - [{[m1,m2,m3],[m1,m2,m3]},{[m1,m2,m3],[m17]}], S), + [{[m1,m2,m3],[m17]}], S), ?line {ok, _} = eval("condensation closure (Mod) E", - [{[m1,m2,m3],[m1,m2,m3]},{[m1,m2,m3],[m17]}], S), + [{[m1,m2,m3],[m17]}], S), ?line {ok, _} = eval("condensation closure closure closure (Mod) E", - [{[m1,m2,m3],[m1,m2,m3]},{[m1,m2,m3],[m17]}], S), + [{[m1,m2,m3],[m17]}], S), ?line {ok, _} = eval("weak condensation (Mod) E", [{[m1,m2,m3],[m1,m2,m3]},{[m1,m2,m3],[m17]},{[m17],[m17]}], S), ?line {ok, _} = eval("strict condensation (Mod) E", [{[m1,m2,m3],[m17]}], S), ?line {ok, _} = eval("range condensation (Mod) E", - [[m1,m2,m3],[m17]], S), + [[m17]], S), ?line {ok, _} = eval("domain condensation (Mod) E", [[m1,m2,m3]], S), diff --git a/lib/xmerl/include/xmerl_xlink.hrl b/lib/xmerl/include/xmerl_xlink.hrl deleted file mode 100644 index 375e244c23..0000000000 --- a/lib/xmerl/include/xmerl_xlink.hrl +++ /dev/null @@ -1,26 +0,0 @@ - - - -%% The following is a brief summary of the element types (columns) on -%% which the global attributes are allowed: -%% -%% simple extended locator arc resource title -%% type X X X X X X -%% href X X -%% role X X X X -%% title X X X X -%% show X X X -%% actuate X X X -%% from X -%% to X -%% --record(xlink, { - type, % simple | extended | locator | arc | resource | title - href, - role - title, - show, - actuate, - from, - to - }). diff --git a/lib/xmerl/src/Makefile b/lib/xmerl/src/Makefile index 7009b50f6c..5b77c9478b 100644 --- a/lib/xmerl/src/Makefile +++ b/lib/xmerl/src/Makefile @@ -94,7 +94,6 @@ MODULES = $(EDOC_MODULES) \ HRL_FILES = \ ../include/xmerl.hrl \ - ../include/xmerl_xlink.hrl \ ../include/xmerl_xpath.hrl \ ../include/xmerl_xsd.hrl diff --git a/lib/xmerl/src/xmerl_sax_parser.erl b/lib/xmerl/src/xmerl_sax_parser.erl index 45e2a928ac..1d795799ce 100644 --- a/lib/xmerl/src/xmerl_sax_parser.erl +++ b/lib/xmerl/src/xmerl_sax_parser.erl @@ -217,7 +217,7 @@ check_encoding_option(E) when E==utf8; E=={utf16,little}; E=={utf16,big}; check_encoding_option(utf16) -> {utf16,big}; check_encoding_option(E) -> - {error, io_lib:format("Charcter set ~p not supported", [E])}. + {error, io_lib:format("Character set ~p not supported", [E])}. %%---------------------------------------------------------------------- %% Function: detect_charset(Xml, State) @@ -279,6 +279,7 @@ convert_encoding(Enc) -> %% Just for 7,8 bit + utf8 case string:to_lower(Enc) of "utf-8" -> utf8; "us-ascii" -> utf8; + "latin1" -> latin1; "iso-8859-1" -> latin1; % Handle all iso-8859 as latin1 "iso-8859-2" -> latin1; "iso-8859-3" -> latin1; diff --git a/lib/xmerl/src/xmerl_sax_parser_base.erlsrc b/lib/xmerl/src/xmerl_sax_parser_base.erlsrc index c25cde0472..e988c49292 100644 --- a/lib/xmerl/src/xmerl_sax_parser_base.erlsrc +++ b/lib/xmerl/src/xmerl_sax_parser_base.erlsrc @@ -39,6 +39,9 @@ %% Internal exports %%---------------------------------------------------------------------- -export([ + cf/3, + cf/4, + cf/5 ]). %%---------------------------------------------------------------------- diff --git a/make/otp.mk.in b/make/otp.mk.in index 507f040729..b9ab9dd4b5 100644 --- a/make/otp.mk.in +++ b/make/otp.mk.in @@ -115,6 +115,12 @@ $(EBIN)/%.beam: $(EGEN)/%.erl $(EBIN)/%.beam: $(ESRC)/%.erl $(ERLC) $(ERL_COMPILE_FLAGS) -o$(EBIN) $< +ifeq ($(NATIVE_LIBS_ENABLED),yes) +# Special rule for the HIPE bootstrap w/ native libs +../boot_ebin/%.beam: $(ESRC)/%.erl + $(ERLC) $(ERL_COMPILE_FLAGS) -o../boot_ebin $< +endif + .erl.beam: $(ERLC) $(ERL_COMPILE_FLAGS) -o$(dir $@) $< diff --git a/system/doc/design_principles/sup_princ.xml b/system/doc/design_principles/sup_princ.xml index c473e257fa..353430752c 100644 --- a/system/doc/design_principles/sup_princ.xml +++ b/system/doc/design_principles/sup_princ.xml @@ -136,7 +136,7 @@ init(...) -> M = F = atom() A = [term()] Restart = permanent | transient | temporary - Shutdown = brutal_kill | integer()>=0 | infinity + Shutdown = brutal_kill | integer()>0 | infinity Type = worker | supervisor Modules = [Module] | dynamic Module = atom()]]></code> diff --git a/system/doc/efficiency_guide/profiling.xml b/system/doc/efficiency_guide/profiling.xml index 65ba4b3369..230aa3504b 100644 --- a/system/doc/efficiency_guide/profiling.xml +++ b/system/doc/efficiency_guide/profiling.xml @@ -116,7 +116,7 @@ minimize runtime performance impact. Using fprof is just a matter of calling a few library functions, see <seealso marker="tools:fprof">fprof</seealso> - manual page under the application tools.<c>fprof</c> was introduced in + manual page under the application tools.<c> fprof</c> was introduced in version R8 of Erlang/OTP. </p> </section> diff --git a/system/doc/tutorial/c_portdriver.xmlsrc b/system/doc/tutorial/c_portdriver.xmlsrc index f875fa80d2..e6887a25d1 100644 --- a/system/doc/tutorial/c_portdriver.xmlsrc +++ b/system/doc/tutorial/c_portdriver.xmlsrc @@ -68,8 +68,8 @@ start(SharedLib) -> case erl_ddll:load_driver(".", SharedLib) of ok -> ok; -\011{error, already_loaded} -> ok; -\011_ -> exit({error, could_not_load_driver}) + {error, already_loaded} -> ok; + _ -> exit({error, could_not_load_driver}) end, spawn(?MODULE, init, [SharedLib]). @@ -102,7 +102,7 @@ loop(Port) -> {call, Caller, Msg} -> Port ! {self(), {command, encode(Msg)}}, receive -\011 {Port, {data, Data}} -> + {Port, {data, Data}} -> Caller ! {complex, decode(Data)} end, loop(Port) |