from history import *
from history.record import *

import os
import unittest
import warnings 

warnings.simplefilter("ignore", Warning)

class TestCXCHistory(unittest.TestCase):

    # Content contains examples of:
    #    - ASCFITS compliant history record
    #    - ASCFITS compliant history record with stack
    #    - non-ASCFITS compliant history record
    #    - pixlib history record
    #    - comment record
    #    - blank comment record
    #    - completely blank line comment record
    content = ["HISTORY  TOOL  :dmcopy   2016-08-11T20:27:22                            ASC00041",
               "HISTORY  PARM  :infile=/export/proc/tmp.ascdsl3/prs_run/tmp//L3AMRF____5ASC00042",
               "HISTORY  CONT  :87231988n944/output/acisf05017_000N022_r0001b_rayevt3.fiASC00043",
               "HISTORY  CONT  :ts[sky=bounds(region(/export/proc/tmp.ascdsl3/prs_run/tmASC00044",
               "HISTORY  CONT  :p//L3AMRF____587231988n944/input/acisfJ0331514m274138_00ASC00045",
               "HISTORY  CONT  :1N021_r0001_srbreg3.fits[bkgreg]))][bin sky=1][opt type=ASC00046",
               "HISTORY  CONT  :i4]                                                     ASC00047",
               "HISTORY  PARM  :outfile=/export/proc/tmp.ascdsl3/prs_run/tmp//L3AMRF____ASC00048",
               "HISTORY  CONT  :587231988n944/output/acisf05017_000N022_r0001b_fbinpsf3.ASC00049",
               "HISTORY  CONT  :fits                                                    ASC00050",
               "HISTORY  PARM  :kernel=default                                          ASC00051",
               "HISTORY  PARM  :option=image                                            ASC00052",
               "HISTORY  PARM  :verbose=0                                               ASC00053",
               "HISTORY  PARM  :clobber=yes                                             ASC00054",
               "COMMENT  --------------------------- New Tool ----------------------------------",
               "HISTORY  TOOL  :dmcopy   2016-08-11T20:43:31                            ASC00055",
               "HISTORY  PARM  :infile=/export/proc/tmp.ascdsl3/prs_run/tmp//L3AMRF____5ASC00056",
               "HISTORY  CONT  :87231988n944/output/acisf05017_000N022_r0001b_fbinpsf3.fASC00057",
               "HISTORY  CONT  :its[events_image][PSF][subspace -time]                  ASC00058",
               "HISTORY  PARM  :outfile=/export/proc/tmp.ascdsl3/prs_run/tmp//L3AMRF____ASC00059",
               "HISTORY  CONT  :587231988n944/output/acisf05017_000N022_r0001b_psf3_tmp.ASC00060",
               "HISTORY  CONT  :fits                                                    ASC00061",
               "HISTORY  PARM  :kernel=default                                          ASC00062",
               "HISTORY  PARM  :option=                                                 ASC00063",
               "HISTORY  PARM  :verbose=0                                               ASC00064",
               "HISTORY  PARM  :clobber=yes                                             ASC00065",
               "COMMENT  ------------------------- Another Tool --------------------------------",
               "                                                                                ",
               "HISTORY  TOOL  :dmappend   2016-08-11T20:43:31                          ASC00066",
               "HISTORY  PARM  :infile=/export/proc/tmp.ascdsl3/prs_run/tmp//L3AMRF____5ASC00067",
               "HISTORY  CONT  :87231988n944/output/acisf05017_000N022_r0001b_psf3.fits[ASC00068",
               "HISTORY  CONT  :acisf05017_000N022_r0001b_psf3.fits][BINPSF]            ASC00069",
               "HISTORY  PARM  :outfile=/export/proc/tmp.ascdsl3/prs_run/tmp//L3AMRF____ASC00070",
               "HISTORY  CONT  :587231988n944/output/acisf05017_000N022_r0001b_psf3_tmp.ASC00071",
               "HISTORY  CONT  :fits                                                    ASC00072",
               "HISTORY  PARM  :verbose=0                                               ASC00073",
               "HISTORY  PARM  :ARDLIB Version: 0.7.1-4                                 ASC00028",
               "HISTORY  PARM  :File used for CALDB info: /state/partition1/tmp.ascdsl3/ASC00029",
               "HISTORY  CONT  :L3ASRC____338268443n247/output/acisf01878_000N001_r0100_ASC00030",
               "HISTORY  CONT  :wmap3.fits                                              ASC00031",
               "HISTORY  PARM  :Note: CTI_APP = PPPPPBPBPP                              ASC00032",
               "HISTORY  PARM  :Parameter file: /state/partition1/tmp.ascdsl3/L3ASRC____ASC00033",
               "HISTORY  CONT  :338268443n247/output/acisf01878_000N001_r0100_ardlib3.paASC00034",
               "HISTORY  CONT  :r                                                       ASC00035",
               "HISTORY  PARM  :Vignetting File: /state/partition1/local/install.CAT3.0/ASC00036",
               "HISTORY  CONT  :CALDB/data/chandra/tel/hrma/bcf/vignet/hrmaD1996-12-20viASC00037",
               "HISTORY  CONT  :gnetN0003.fits[AXAF_VIGNET1]                            ASC00038",
               "HISTORY  PARM  :Onaxis Area File: /state/partition1/local/install.CAT3.0ASC00039",
               "HISTORY  CONT  :/CALDB/data/chandra/tel/hrma/bcf/effarea/hrmaD1996-12-20ASC00040",
               "HISTORY  CONT  :axeffaN0007.fits[AXAF_AXEFFA1]                          ASC00041",
               "HISTORY  PARM  :ACIS QE File: /state/partition1/local/install.CAT3.0/CALASC00042",
               "HISTORY  CONT  :DB/data/chandra/acis/bcf/qe/acisD1997-04-17qeN0006.fits[ASC00043",
               "HISTORY  CONT  :AXAF_QE3]                                               ASC00044",
               "HISTORY  PARM  :ACIS Uniformity File: /state/partition1/local/install.CAASC00045",
               "HISTORY  CONT  :T3.0/CALDB/data/chandra/acis/bcf/qe/acisD2000-01-29qeuN0ASC00046",
               "HISTORY  CONT  :006.fits[AXAF_QEU3]                                     ASC00047",
               "HISTORY  PARM  :ACIS Contamination File: /state/partition1/local/installASC00048",
               "HISTORY  CONT  :.CAT3.0/CALDB/data/chandra/acis/bcf/contam/acisD1999-08-ASC00049",
               "HISTORY  CONT  :13contamN0004.fits[AXAF_CONTAM3]                        ASC00050",
               "HISTORY  PARM  :ACIS 2 Badpix File: /state/partition1/tmp.ascdsl3/L3ASRCASC00051",
               "HISTORY  CONT  :____338268443n247/input/acisf01878_000N001_bpix3.fits[BAASC00052",
               "HISTORY  CONT  :DPIX2]                                                  ASC00053",
               "HISTORY  PARM  :File used for CALDB info: /state/partition1/tmp.ascdsl3/ASC00054",
               "HISTORY  CONT  :L3ASRC____338268443n247/output/acisf01878_000N001_r0100_ASC00055",
               "HISTORY  CONT  :wmap3.fits                                              ASC00056",
               "HISTORY  PARM  :Note: CTI_APP = PPPPPBPBPP                              ASC00057",
               "HISTORY  PARM  :File used for CALDB info: /state/partition1/tmp.ascdsl3/ASC00058",
               "HISTORY  CONT  :L3ASRC____338268443n247/output/acisf01878_000N001_r0100_ASC00059",
               "HISTORY  CONT  :wmap3.fits                                              ASC00060",
               "HISTORY  PARM  :Note: CTI_APP = PPPPPBPBPP                              ASC00061",
               "COMMENT                                                                         ",
               "HISTORY  PARM  :PIXLIB Version: 4.0.0                                   ASC00015",
               "HISTORY  PARM  :******     PIXLIB Parameter File      *****             ASC00016",
               "HISTORY  PARM  :/home/ascds/DS.l3/param/geom.par:                       ASC00017",
               "HISTORY  PARM  :instruments  = /export/CALDB/level3/data/chandra/defaultASC00018",
               "HISTORY  CONT  :/geom/telD1999-07-23geomN0006.fits(CALDB)               ASC00019",
               "HISTORY  PARM  :aimpoints    = /export/CALDB/level3/data/chandra/defaultASC00020",
               "HISTORY  CONT  :/aimpts/telD1999-07-23aimptsN0002.fits(CALDB)           ASC00021",
               "HISTORY  PARM  :tdet         = /export/CALDB/level3/data/chandra/defaultASC00022",
               "HISTORY  CONT  :/tdet/telD1999-07-23tdetN0001.fits(CALDB)               ASC00023",
               "HISTORY  PARM  :sky          = /export/CALDB/level3/data/chandra/defaultASC00024",
               "HISTORY  CONT  :/sky/telD1999-07-23skyN0002.fits(CALDB)                 ASC00025",
               "HISTORY  PARM  :shell        = /export/CALDB/level3/data/chandra/defaultASC00026",
               "HISTORY  CONT  :/sgeom/telD1999-07-23sgeomN0001.fits(CALDB)             ASC00027",
               "HISTORY  PARM  :obsfile      = nowT00:00:00()                           ASC00028",
               "HISTORY  TOOL  :dmhedit  2016-08-11T20:43:33                            ASC00870",
               "HISTORY  PARM  :infile=@/this/is/a/super/loooooooooooooong/directory/namASC00871",
               "HISTORY  CONT  :e/but/wait/there/is/lots/lots/lots/mooooooooooooore/infiASC00872",
               "HISTORY  CONT  :le.lis                                                  ASC00873",
               "HISTORY  STCK  :/this/is/a/super/loooooooooooooong/directory/name/stack1ASC00874",
               "HISTORY  CONT  :.fits                                                   ASC00875",
               "HISTORY  STCK  :/this/is/a/super/loooooooooooooong/directory/name/stack2ASC00876",
               "HISTORY  CONT  :.fits                                                   ASC00877",
               "HISTORY  STCK  :/this/is/a/super/loooooooooooooong/directory/name/stack3ASC00878",
               "HISTORY  CONT  :.fits                                                   ASC00879",
               "HISTORY  STCK  :/this/is/a/super/loooooooooooooong/directory/name//but/wASC00880",
               "HISTORY  CONT  :ait/there/is/lots/lots/lots/mooooooooooooore/stack4.fitsASC00881",
               "HISTORY  CONT  :                                                        ASC00882",
               "HISTORY  STCK  :/this/is/a/super/loooooooooooooong/directory/name/stack5ASC00883",
               "HISTORY  CONT  :.fits                                                   ASC00884",
               "HISTORY  PARM  :outfile=/tmp/dir/outfile.fits                           ASC00885",
               "HISTORY  This is a non-ASCFITS compliant history record                         "
               ]

    # Content2 contains examples of:
    #    - ASCFITS compliant history record without date
    #    - ASCFITS compliant history record with '@@' clearcase element
    #    - ASCFITS compliant history record containing multiple parameter stacks
    #    - ASCFITS compliant history record containing stack files with filters
    #    - ASCFITS compliant history record with non-standard infile
    content2 = [
               "HISTORY  TOOL  :ade                                                     ASC00001",
               "HISTORY  PARM  :infile=/home/ascdsrap/ap/sdp/opus/prs_run/tmp//TP_ADE___ASC00002",
               "HISTORY  CONT  :_086490403n255/input/acisf059969572N002_SR0.strip       ASC00003",
               "HISTORY  PARM  :template=/vobs/ASC_DR_TLM/src/dr/tlm/template_dir/acis_sASC00004",
               "HISTORY  CONT  :trip_file_info.dat@@/main/2                             ASC00005",
               "HISTORY  PARM  :template=/vobs/ASC_DR_TLM/src/dr/tlm/template_dir/acis_fASC00006",
               "HISTORY  CONT  :ile_info.dat@@/main/12                                  ASC00007",
               "HISTORY  PARM  :template=/vobs/ASC_DR_TLM/src/dr/tlm/template_dir/acis_cASC00008",
               "HISTORY  CONT  :onfig_file.dat@@/main/2                                 ASC00009",
               "HISTORY  PARM  :template=/vobs/ASC_DR_TLM/src/dr/tlm/template_dir/acis_gASC00010",
               "HISTORY  CONT  :roup_info.dat@@/main/12                                 ASC00011",
               "HISTORY  PARM  :template=/vobs/ASC_DR_TLM/src/dr/tlm/template_dir/acis_dASC00012",
               "HISTORY  CONT  :p_info.dat@@/main/19                                    ASC00013",
               "HISTORY  PARM  :template=/vobs/ASC_DR_TLM/src/dr/tlm/template_dir/acis_cASC00014",
               "HISTORY  CONT  :ommon_dp_info.dat@@/main/9                              ASC00015",
               "HISTORY  TOOL  :acis_format_events   2000-09-29T23:57:53                ASC00001",
               "HISTORY  PARM  :infile=@/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_LASC00002",
               "HISTORY  CONT  :1_086557597n455/input/acisf01463_000N002_evt0.lis       ASC00003",
               "HISTORY  STCK  :/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557ASC00004",
               "HISTORY  CONT  :597n455/input/acisf059969672N002_1_evt0.fits[time=599687ASC00005",
               "HISTORY  CONT  :97.4852730:59993398.5111620]                            ASC00006",
               "HISTORY  STCK  :/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557ASC00007",
               "HISTORY  CONT  :597n455/input/acisf059969672N002_2_evt0.fits[time=599687ASC00008",
               "HISTORY  CONT  :97.4852730:59993398.5111620]                            ASC00009",
               "HISTORY  STCK  :/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557ASC00010",
               "HISTORY  CONT  :597n455/input/acisf059969672N002_3_evt0.fits[time=599687ASC00011",
               "HISTORY  CONT  :97.4852730:59993398.5111620]                            ASC00012",
               "HISTORY  STCK  :/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557ASC00013",
               "HISTORY  CONT  :597n455/input/acisf059969672N002_4_evt0.fits[time=599687ASC00014",
               "HISTORY  CONT  :97.4852730:59993398.5111620]                            ASC00015",
               "HISTORY  STCK  :/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557ASC00016",
               "HISTORY  CONT  :597n455/input/acisf059969672N002_5_evt0.fits[time=599687ASC00017",
               "HISTORY  CONT  :97.4852730:59993398.5111620]                            ASC00018",
               "HISTORY  PARM  :biasfile=@/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_FASC00019",
               "HISTORY  CONT  :_L1_086557597n455/input/acisf01463_000N002_bias0.lis    ASC00020",
               "HISTORY  STCK  :/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557ASC00021",
               "HISTORY  CONT  :597n455/input/acisf059904456N002_1_bias0.fits           ASC00022",
               "HISTORY  STCK  :/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557ASC00023",
               "HISTORY  CONT  :597n455/input/acisf059904456N002_2_bias0.fits           ASC00024",
               "HISTORY  STCK  :/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557ASC00025",
               "HISTORY  CONT  :597n455/input/acisf059904456N002_3_bias0.fits           ASC00026",
               "HISTORY  STCK  :/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557ASC00027",
               "HISTORY  CONT  :597n455/input/acisf059904456N002_4_bias0.fits           ASC00028",
               "HISTORY  STCK  :/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557ASC00029",
               "HISTORY  CONT  :597n455/input/acisf059904456N002_5_bias0.fits           ASC00030",
               "HISTORY  PARM  :exrfile=@/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_ASC00031",
               "HISTORY  CONT  :L1_086557597n455/input/acisf01463_000N002_exr0.lis      ASC00032",
               "HISTORY  STCK  :/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557ASC00033",
               "HISTORY  CONT  :597n455/input/acisf059969672N002_1_exr0.fits[time=599687ASC00034",
               "HISTORY  CONT  :97.4852730:59993398.5111620]                            ASC00035",
               "HISTORY  STCK  :/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557ASC00036",
               "HISTORY  CONT  :597n455/input/acisf059969672N002_2_exr0.fits[time=599687ASC00037",
               "HISTORY  CONT  :97.4852730:59993398.5111620]                            ASC00038",
               "HISTORY  STCK  :/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557ASC00039",
               "HISTORY  CONT  :597n455/input/acisf059969672N002_3_exr0.fits[time=599687ASC00040",
               "HISTORY  CONT  :97.4852730:59993398.5111620]                            ASC00041",
               "HISTORY  STCK  :/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557ASC00042",
               "HISTORY  CONT  :597n455/input/acisf059969672N002_4_exr0.fits[time=599687ASC00043",
               "HISTORY  CONT  :97.4852730:59993398.5111620]                            ASC00044",
               "HISTORY  STCK  :/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557ASC00045",
               "HISTORY  CONT  :597n455/input/acisf059969672N002_5_exr0.fits[time=599687ASC00046",
               "HISTORY  CONT  :97.4852730:59993398.5111620]                            ASC00047",
               "HISTORY  PARM  :outfile=/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_LASC00048",
               "HISTORY  CONT  :1_086557597n455/output/acisf01463_000N002_epr1.fits     ASC00049",
               "HISTORY  PARM  :outbias=/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_LASC00050",
               "HISTORY  CONT  :1_086557597n455/output/acisf01463_000N002               ASC00051",
               "HISTORY  PARM  :expstatsfile=/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIASC00052",
               "HISTORY  CONT  :S_F_L1_086557597n455/output/acisf01463_000N002_stat1.fitASC00053",
               "HISTORY  CONT  :s                                                       ASC00054",
               "HISTORY  PARM  :obsfile=/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_LASC00055",
               "HISTORY  CONT  :1_086557597n455/input/axaff01463_000N002_obs0a.par      ASC00056",
               "HISTORY  PARM  :logfile=/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_LASC00057",
               "HISTORY  CONT  :1_086557597n455/output/acis_format_events.log           ASC00058",
               "HISTORY  PARM  :bias_correct=yes                                        ASC00059",
               "HISTORY  PARM  :oc_correct=yes                                          ASC00060",
               "HISTORY  PARM  :min_dlta_oc=-200                                        ASC00061",
               "HISTORY  PARM  :max_dlta_oc=200                                         ASC00062",
               "HISTORY  PARM  :eventdef={d:time,i:expno,s:chipx,s:chipy,s:phas,s:ccd_idASC00063",
               "HISTORY  CONT  :,s:node_id,x:status}                                    ASC00064",
               "HISTORY  PARM  :telev1={d:time,i:expno,s:chipx,s:chipy,s:phas,s:ccd_id,sASC00065",
               "HISTORY  CONT  ::node_id,x:status}                                      ASC00066",
               "HISTORY  PARM  :vflev1={d:time,i:expno,s:chipx,s:chipy,s:phas,s:ccd_id,sASC00067",
               "HISTORY  TOOL  :acis_process_events   2000-09-30T00:34:41               ASC00083",
               "HISTORY  PARM  :infile=/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1ASC00084",
               "HISTORY  CONT  :_086557597n455/output/acisf01463_000N002_tim1.fits      ASC00085",
               "HISTORY  PARM  :outfile=/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_LASC00086",
               "HISTORY  CONT  :1_086557597n455/output/acisf01463_000N002_evt1.fits     ASC00087",
               "HISTORY  PARM  :acaofffile=@/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACISASC00088",
               "HISTORY  CONT  :_F_L1_086557597n455/input/pcadf01463_000N002_asol1.lis  ASC00089",
               "HISTORY  STCK  :/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557ASC00090",
               "HISTORY  CONT  :597n455/input/pcadf059968984N002_asol1.fits[time=5996879ASC00091",
               "HISTORY  CONT  :7.4852730:59993398.5111620]                             ASC00092",
               "HISTORY  PARM  :alignmentfile=@/home/ascdsrap/ap/sdp/opus/prs_run/tmp//AASC00093",
               "HISTORY  CONT  :CIS_F_L1_086557597n455/input/pcadf01463_000N002_asol1.liASC00094",
               "HISTORY  CONT  :s                                                       ASC00095",
               "HISTORY  STCK  :/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557ASC00096",
               "HISTORY  CONT  :597n455/input/pcadf059968984N002_asol1.fits[time=5996879ASC00097",
               "HISTORY  CONT  :7.4852730:59993398.5111620]                             ASC00098",
               "HISTORY  PARM  :obsfile=/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_LASC00099",
               "HISTORY  CONT  :1_086557597n455/input/axaff01463_000N002_obs0a.par      ASC00100",
               "HISTORY  PARM  :logfile=/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_LASC00101",
               "HISTORY  CONT  :1_086557597n455/output/acis_process_events.log          ASC00102",
               "HISTORY  PARM  :gradefile=/home/ascds/DS.rap/data/asca_grades.fits      ASC00103",
               "HISTORY  PARM  :gainfile=/data/CALDB/data/chandra/acis/bcf/gain/acisD199ASC00104",
               "HISTORY  CONT  :9-09-16gainN0004.fits                                   ASC00105",
               "HISTORY  PARM  :badpixfile=/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_ASC00106",
               "HISTORY  CONT  :F_L1_086557597n455/output/acisf01463_000N002_bpix1.fits ASC00107",
               "HISTORY  PARM  :threshfile=NONE                                         ASC00108",
               "HISTORY  PARM  :eventdef={d:time,s:ccd_id,s:node_id,i:expno,s:chip,s:tdeASC00109",
               "HISTORY  CONT  :t,f:det,f:sky,s:phas,l:pha,f:energy,l:pi,s:fltgrade,s:grASC00110",
               "HISTORY  CONT  :ade,x:status}                                           ASC00111",
               "HISTORY  PARM  :doevtgrade=yes                                          ASC00112",
               "HISTORY  PARM  :spthresh=13                                             ASC00113",
               "HISTORY  PARM  :time_offset=0                                           ASC00114",
               "HISTORY  PARM  :docentroid=no                                           ASC00115",
               "HISTORY  PARM  :calculate_pi=yes                                        ASC00116",
               "HISTORY  PARM  :pi_bin_width=14.6                                       ASC00117",
               "HISTORY  PARM  :pi_num_bins=1024                                        ASC00118",
               "HISTORY  PARM  :cc_chipy=564.1341161932397                              ASC00119",
               "HISTORY  PARM  :tstart=TSTART                                           ASC00120",
               "HISTORY  PARM  :tstop=TSTOP                                             ASC00121",
               "HISTORY  PARM  :clobber=no                                              ASC00122",
               "HISTORY  PARM  :verbose=0                                               ASC00123",
               "HISTORY  PARM  :stop=sky                                                ASC00124",
               "HISTORY  PARM  :instrume=acis                                           ASC00125",
               "HISTORY  PARM  :rand_seed=1                                             ASC00126",
               "HISTORY  PARM  :rand_pix_size=0.5                                       ASC00127",
               "HISTORY  PARM  :stdlev1={d:time,s:ccd_id,s:node_id,i:expno,s:chip,s:tdetASC00128",
               "HISTORY  CONT  :,f:det,f:sky,s:phas,l:pha,f:energy,l:pi,s:fltgrade,s:graASC00129",
               "HISTORY  CONT  :de,x:status}                                            ASC00130",
               "HISTORY  PARM  :grdlev1={d:time,s:ccd_id,s:node_id,i:expno,s:chip,s:tdetASC00131",
               "HISTORY  CONT  :,f:det,f:sky,l:pha,s:corn_pha,f:energy,l:pi,s:fltgrade,sASC00132",
               "HISTORY  CONT  ::grade,x:status}                                        ASC00133",
               "HISTORY  PARM  :cclev1={d:time,s:ccd_id,s:node_id,i:expno,s:chip,s:tdet,ASC00134",
               "HISTORY  CONT  :f:det,f:sky,f:sky_1d,s:phas,l:pha,f:energy,l:pi,s:fltgraASC00135",
               "HISTORY  CONT  :de,s:grade,x:status}                                    ASC00136",
               "HISTORY  PARM  :ccgrdlev1={d:time,s:ccd_id,s:node_id,i:expno,s:chip,s:tdASC00137",
               "HISTORY  CONT  :et,f:det,f:sky,f:sky_1d,l:pha,f:energy,l:pi,s:fltgrade,sASC00138",
               "HISTORY  CONT  ::grade,x:status}                                        ASC00139",
               "HISTORY  TOOL  :dmmerge   2000-09-30T02:21:03                           ASC00156",
               "HISTORY  PARM  :infile= File # 1 : /home/ascdsrap/ap/sdp/opus/prs_run/tmASC00157",
               "HISTORY  CONT  :p//ACIS_L2___086565466n511/input/acisf01463_000N002_evt1ASC00158",
               "HISTORY  CONT  :.fits[@/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_L2__ASC00159",
               "HISTORY  CONT  :_086565466n511/input/acisf01463_000N002_flt1.fits][cols ASC00160",
               "HISTORY  CONT  :!PHAS,!CORN_PHA]                                        ASC00161"
        ]

    def test_01(self):
        # create CXCHistory object from content list 
        try:
            cxchist = CXCHistory(self.content)
        except Exception as ex:
            print(str(ex))
            raise Exception("create CXCHistory from content list FAILED")

        # check if completely blank line was read in correctly
        self.assertEqual(cxchist.records[4]._is_blank, True, "read completely blank line FAILED")

        expected = "Tool:  PIXLIB Version: 4.0.0\n" + "Date:  \n" + "Params:\n" + "   ******     PIXLIB Parameter File      *****\n" + "   /home/ascds/DS.l3/param/geom.par:\n" + "   instruments   =  /export/CALDB/level3/data/chandra/default/geom/telD1999-07-23geomN0006.fits(CALDB)\n" + "   aimpoints     =  /export/CALDB/level3/data/chandra/default/aimpts/telD1999-07-23aimptsN0002.fits(CALDB)\n" + "   tdet          =  /export/CALDB/level3/data/chandra/default/tdet/telD1999-07-23tdetN0001.fits(CALDB)\n" + "   sky           =  /export/CALDB/level3/data/chandra/default/sky/telD1999-07-23skyN0002.fits(CALDB)\n" + "   shell         =  /export/CALDB/level3/data/chandra/default/sgeom/telD1999-07-23sgeomN0001.fits(CALDB)\n" + "   obsfile       =  nowT00:00:00()\n" + "ASCNUM:  15\n"

        # check if pixlib format was read in correctly        
        result = str(cxchist.records[8])
        self.assertIn(result, expected, "read pixlib history FAILED")

        expected = "Tool:  ARDLIB Version: 0.7.1-4\n" + "Date:  \n" + "Params:\n" + "   File used for CALDB info: /state/partition1/tmp.ascdsl3/L3ASRC____338268443n247/output/acisf01878_000N001_r0100_wmap3.fits\n" + "   Note: CTI_APP = PPPPPBPBPP\n" + "   Parameter file: /state/partition1/tmp.ascdsl3/L3ASRC____338268443n247/output/acisf01878_000N001_r0100_ardlib3.par\n" + "   Vignetting File: /state/partition1/local/install.CAT3.0/CALDB/data/chandra/tel/hrma/bcf/vignet/hrmaD1996-12-20vignetN0003.fits[AXAF_VIGNET1]\n" + "   Onaxis Area File: /state/partition1/local/install.CAT3.0/CALDB/data/chandra/tel/hrma/bcf/effarea/hrmaD1996-12-20axeffaN0007.fits[AXAF_AXEFFA1]\n" + "   ACIS QE File: /state/partition1/local/install.CAT3.0/CALDB/data/chandra/acis/bcf/qe/acisD1997-04-17qeN0006.fits[AXAF_QE3]\n" + "   ACIS Uniformity File: /state/partition1/local/install.CAT3.0/CALDB/data/chandra/acis/bcf/qe/acisD2000-01-29qeuN0006.fits[AXAF_QEU3]\n" + "   ACIS Contamination File: /state/partition1/local/install.CAT3.0/CALDB/data/chandra/acis/bcf/contam/acisD1999-08-13contamN0004.fits[AXAF_CONTAM3]\n" + "   ACIS 2 Badpix File: /state/partition1/tmp.ascdsl3/L3ASRC____338268443n247/input/acisf01878_000N001_bpix3.fits[BADPIX2]\n" + "   File used for CALDB info: /state/partition1/tmp.ascdsl3/L3ASRC____338268443n247/output/acisf01878_000N001_r0100_wmap3.fits\n" + "   Note: CTI_APP = PPPPPBPBPP\n" + "   File used for CALDB info: /state/partition1/tmp.ascdsl3/L3ASRC____338268443n247/output/acisf01878_000N001_r0100_wmap3.fits\n" + "   Note: CTI_APP = PPPPPBPBPP\n" + "ASCNUM:  28\n"

        # check if ardlib format was read in correctly        
        result = str(cxchist.records[6])
        self.assertIn(result, expected, "read ardlib history FAILED")

        # check HISTNUM calculation
#        self.assertEqual(cxchist.histnum, 50, "histnum calculation FAILED")
        self.assertEqual(cxchist.histnum, 50)

    def test_02(self):
        # Construct empty CXCHistory and create records from content array
        try:
            cxchist = CXCHistory()
        except Exception as ex:
            print(str(ex))
            raise Exception("create empty CXCHistory FAILED")

        try:
            cxchist._create_records(self.content2, "AXIS")
        except Exception as ex:
            print(str(ex))
            raise Exception("create_records() FAILED")

        # check afterkey is correct
        self.assertEqual(cxchist.records[0]._afterkey, "AXIS", "set afterkey FAILED")

        expected = "Tool:  dmmerge\n" + "Date:  2000-09-30T02:21:03\n" + "Params:\n" + "   infile =  File # 1 : /home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_L2___086565466n511/input/acisf01463_000N002_evt1.fits[@/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_L2___086565466n511/input/acisf01463_000N002_flt1.fits][cols!PHAS,!CORN_PHA]\n" + "ASCNUM:  156\n"

        # check if fourth history record was read in correctly
        result = str(cxchist.records[3])
        self.assertEqual(result, expected, "history record w/ non-standard infile FAILED")

        expected = "Tool:  acis_format_events\n" + "Date:  2000-09-29T23:57:53\n" + "Params:\n" + "   infile = @/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557597n455/input/acisf01463_000N002_evt0.lis\n" + "      > /home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557597n455/input/acisf059969672N002_1_evt0.fits[time=59968797.4852730:59993398.5111620]\n" + "      > /home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557597n455/input/acisf059969672N002_2_evt0.fits[time=59968797.4852730:59993398.5111620]\n" + "      > /home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557597n455/input/acisf059969672N002_3_evt0.fits[time=59968797.4852730:59993398.5111620]\n" + "      > /home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557597n455/input/acisf059969672N002_4_evt0.fits[time=59968797.4852730:59993398.5111620]\n" + "      > /home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557597n455/input/acisf059969672N002_5_evt0.fits[time=59968797.4852730:59993398.5111620]\n" + "   biasfile = @/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557597n455/input/acisf01463_000N002_bias0.lis\n" + "      > /home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557597n455/input/acisf059904456N002_1_bias0.fits\n" + "      > /home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557597n455/input/acisf059904456N002_2_bias0.fits\n" + "      > /home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557597n455/input/acisf059904456N002_3_bias0.fits\n" + "      > /home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557597n455/input/acisf059904456N002_4_bias0.fits\n" + "      > /home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557597n455/input/acisf059904456N002_5_bias0.fits\n" + "   exrfile = @/home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557597n455/input/acisf01463_000N002_exr0.lis\n" + "      > /home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557597n455/input/acisf059969672N002_1_exr0.fits[time=59968797.4852730:59993398.5111620]\n" + "      > /home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557597n455/input/acisf059969672N002_2_exr0.fits[time=59968797.4852730:59993398.5111620]\n" + "      > /home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557597n455/input/acisf059969672N002_3_exr0.fits[time=59968797.4852730:59993398.5111620]\n" + "      > /home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557597n455/input/acisf059969672N002_4_exr0.fits[time=59968797.4852730:59993398.5111620]\n" + "      > /home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557597n455/input/acisf059969672N002_5_exr0.fits[time=59968797.4852730:59993398.5111620]\n" + "   outfile = /home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557597n455/output/acisf01463_000N002_epr1.fits\n" + "   outbias = /home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557597n455/output/acisf01463_000N002\n" + "   expstatsfile = /home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557597n455/output/acisf01463_000N002_stat1.fits\n" + "   obsfile = /home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557597n455/input/axaff01463_000N002_obs0a.par\n" + "   logfile = /home/ascdsrap/ap/sdp/opus/prs_run/tmp//ACIS_F_L1_086557597n455/output/acis_format_events.log\n" + "   bias_correct = yes\n" + "   oc_correct = yes\n" + "   min_dlta_oc = -200\n" + "   max_dlta_oc = 200\n" + "   eventdef = {d:time,i:expno,s:chipx,s:chipy,s:phas,s:ccd_id,s:node_id,x:status}\n" + "   telev1 = {d:time,i:expno,s:chipx,s:chipy,s:phas,s:ccd_id,s:node_id,x:status}\n" + "   vflev1 = {d:time,i:expno,s:chipx,s:chipy,s:phas,s:ccd_id,s\n" + "ASCNUM:  1\n"

        # check if second history record with expanded stacks was read in correctly
        result = str(cxchist.history[1])
        self.assertEqual(result, expected, "create_records() FAILED")

        # check if correct number of comment records after reading
        self.assertEqual(cxchist.ncomments, 0, "get_ncomments() FAILED")

        # check if correct number of history records after reading
        self.assertEqual(cxchist.nhistory, 4, "get_nhistory() FAILED")     

        # check delete history records function
        cxchist.delete_history()
        self.assertEqual(cxchist.nrecords, 0,"delete_history() FAILED")
        self.assertEqual(cxchist.nhistory, 0,"delete_history() FAILED")


    def test_03(self):

        # try creating CXCHistory with CXCHistory object
        try:
            hist = CXCHistory()
            hist2 = CXCHistory(hist)
        except Exception as ex:
            if "'content' argument must be string type or list of string type" not in str(ex):
                raise Exception("create CXCHistory w/ content of invalid datatype FAILED ")

        
        # try adding multiple records
        content = ['HISTORY dmcopy infile=/export/proc/tmp.ascdsl3/prs_run/tmp//L3AMRF____587231988n',
                   'HISTORY 944/output/acisf05017_000N022_r0001b_rayevt3.fits[sky=bounds(region(/exp',
                   'HISTORY ort/proc/tmp.ascdsl3/prs_run/tmp//L3AMRF____587231988n944/input/acisfJ03',
                   'HISTORY 31514m274138_001N021_r0001_srbreg3.fits[bkgreg]))][bin sky=1][opt type=i',
                   'HISTORY 4] outfile=/export/proc/tmp.ascdsl3/prs_run/tmp//L3AMRF____587231988n944',
                   'HISTORY /output/acisf05017_000N022_r0001b_fbinpsf3.fits kernel=default option=im',
                   'HISTORY age verbose=0 clobber=yes                                               ']

        # check that output is the same when using constructor and using empty object + create_records()
        try:
            hist = CXCHistory(content)
        except Exception as ex:
            print(str(ex))
            raise
        try:
            hist2 = CXCHistory()
            hist2.create_records(content)    
        except Exception as ex:
            print(str(ex))
            raise
        self.assertEqual(str(hist), str(hist2), "constructor output equals create_records() output FAILED")


        # Try adding multiple History and Comment records with add_record()
        try:
            hist2.add_record("HISTORY", content)
        except Exception as ex:
            if "Cannot create more than one history record" not in str(ex):
                print(str(ex))
                raise Exception("add multiple History records test FAILED")
        try:
            hist2.add_record("COMMENT", content)
        except Exception as ex:
            if "'content' argument must be string type" not in str(ex):
                raise Exception("add multiple Comment records test FAILED")


        # Construct empty CXCHistory and add records/history/comments
        try:
            history = CXCHistory()
        except Exception as ex:
            print(str(ex))
            raise Exception("create empty CXCHistory FAILED")

        histlist = ["HISTORY  TOOL  :dmcopy  2016-08-11T20:27:22                             ASC00041",        
                    "HISTORY  PARM  :infile=/export/proc/tmp.ascdsl3/prs_run/tmp//L3AMRF____5ASC00042",
                    "HISTORY  CONT  :87231988n944/output/acisf05017_000N022_r0001b_rayevt3.fiASC00043",
                    "HISTORY  CONT  :ts[sky=bounds(region(/export/proc/tmp.ascdsl3/prs_run/tmASC00044",
                    "HISTORY  CONT  :p//L3AMRF____587231988n944/input/acisfJ0331514m274138_00ASC00045",
                    "HISTORY  CONT  :1N021_r0001_srbreg3.fits[bkgreg]))][bin sky=1][opt type=ASC00046",
                    "HISTORY  CONT  :i4]                                                     ASC00047",
                    "HISTORY  PARM  :outfile=/export/proc/tmp.ascdsl3/prs_run/tmp//L3AMRF____ASC00048",
                    "HISTORY  CONT  :587231988n944/output/acisf05017_000N022_r0001b_fbinpsf3.ASC00049",
                    "HISTORY  CONT  :fits                                                    ASC00050",
                    "HISTORY  PARM  :kernel=default                                          ASC00051",
                    "HISTORY  PARM  :option=image                                            ASC00052",
                    "HISTORY  PARM  :verbose=0                                               ASC00053",
                    "HISTORY  PARM  :clobber=yes                                             ASC00054"]

        # try adding content with a non-valid tag
        try:
            history.add_record("COMMENTARY", "yada yada yada")
        except Exception as ex:
            if "'tag' value is invalid" not in str(ex):
                print(str(ex))
                raise Exception("add record w/ invalid tag FAILED")

        # add record where comment is a List 
        try:
            history.add_record("COMMENT", histlist)
        except Exception as ex:
            if "'content' argument must be string type" not in str(ex):
                print(str(ex))
                raise Exception("add_record(<list>) test FAILED")

        # add ASCFITS compliant history record
        try:
            history.add_record("HISTORY", histlist)
        except Exception as ex:
            print(str(ex))
            raise Exception("add_record(HISTORY, <list of strings>) FAILED")

        # add non-ASCFITS compliant history record
        try:
            history.add_record("HISTORY", "This is a non-ASCFITS compliant history record")
        except Exception as ex:
            print(str(ex))
            raise Exception("add_record(HISTORY, <string>) FAILED")

        # add non-ASCFITS compliant history record
        try:
            history.add_record("HISTORY", ["This is another non-ASCFITS compliant history record"])
        except Exception as ex:
            print(str(ex))
            raise Exception("add_record(HISTORY, [<string>]) FAILED")

        # add comment record
        try:
            history.add_record("COMMENT", "blah blah blah")
        except Exception as ex:
            print(str(ex))
            raise Exception("add_record(COMMENT, <string>) FAILED")
        
        histlist = [
            "HISTORY  TOOL  :dmappend                                                ASC00066",
            "HISTORY  PARM  :infile=/export/proc/tmp.ascdsl3/prs_run/tmp//L3AMRF____5ASC00067",
            "HISTORY  CONT  :87231988n944/output/acisf05017_000N022_r0001b_psf3.fits[ASC00068",
            "HISTORY  CONT  :acisf05017_000N022_r0001b_psf3.fits][BINPSF]            ASC00069",
            "HISTORY  PARM  :outfile=/export/proc/tmp.ascdsl3/prs_run/tmp//L3AMRF____ASC00070",
            "HISTORY  CONT  :587231988n944/output/acisf05017_000N022_r0001b_psf3_tmp.ASC00071",
            "HISTORY  CONT  :fits                                                    ASC00072",
            "HISTORY  PARM  :verbose=0                                               ASC00073",
            ]

        # add history record without datetime    
        try:
            history.add_record("HISTORY", histlist)
        except Exception as ex:
            print(str(ex))
            raise Exception("another add_record(HISTORY, <list of strings>) FAILED")

        try:
            history.add_record("HISTORY", ["a string", "another string", 480 , "one more string"])
        except Exception as ex:
            if "'content' argument must be string type or list of string type" not in str(ex):
                print(str(ex))
                raise Exception("add_record() with invalid HISTORY list input FAILED")

        try:
            history.add_record("HISTORY", 3400245)
        except Exception as ex:
            if "'content' argument must be string type or list of string type" not in str(ex):
                print(str(ex))
                raise Exception("add_record() with invalid HISTORY input FAILED")

        try:
            history.add_record("COMMENT", 3400245)
        except Exception as ex:
            if "'content' argument must be string type or list of string type" not in str(ex):
                print(str(ex))
                raise Exception("add_record() with invalid COMMENT input FAILED")

        # add history record with an @.lis record and no corresponding stack
        try:
            history.add_history_record("dmsomething", "2017-12-01T14:00:00", ["infile", "outfile", "tol"], ["@in.lis", "out.fits", "tolerance"], [], 77 )
        except Exception as ex:
            if "Parameter stacks list must be the same length as names and values lists" not in str(ex):
                raise Exception("test bad param stack FAILED ")

        # add history record with an @.lis record with stack
        try:
            history.add_history_record("dmsomething", "2017-12-01T14:00:00", ["infile", "outfile", "tol"], ["@in.lis", "out.fits", "tolerance"], [["stack1.fits", "stack2.fits"],[],[]], 77 )
        except Exception as ex:
            print(str(ex))
            raise Exception("add_history_record() with stack FAILED")

        # add completely blank line
        try:
            history.add_comment_record(None, is_blank=True)
        except Exception as ex:
            print(str(ex))
            raise Exception("add completely blank line FAILED")

        # add blank comment record
        try:
            history.add_comment_record("")
        except Exception as ex:
            print(str(ex))
            raise Exception("add comment with empty content FAILED")

        expected = "==========  Record[0]: HISTORY  ==========\n" + "Tool:  dmcopy\n" + "Date:  2016-08-11T20:27:22\n" + "Params:\n" + "   infile = /export/proc/tmp.ascdsl3/prs_run/tmp//L3AMRF____587231988n944/output/acisf05017_000N022_r0001b_rayevt3.fits[sky=bounds(region(/export/proc/tmp.ascdsl3/prs_run/tmp//L3AMRF____587231988n944/input/acisfJ0331514m274138_001N021_r0001_srbreg3.fits[bkgreg]))][bin sky=1][opt type=i4]\n" + "   outfile = /export/proc/tmp.ascdsl3/prs_run/tmp//L3AMRF____587231988n944/output/acisf05017_000N022_r0001b_fbinpsf3.fits\n" + "   kernel = default\n" + "   option = image\n" + "   verbose = 0\n" + "   clobber = yes\n" + "ASCNUM:  41\n" + "\n" + "==========  Record[1]: HISTORY  ==========\n" + "Content:    'This is a non-ASCFITS compliant history record'\n" + "\n" + "==========  Record[2]: HISTORY  ==========\n" + "Content:    'This is another non-ASCFITS compliant history record'\n" + "\n" + "==========  Record[3]: COMMENT  ==========\n" + "Content:    'blah blah blah'\n" + "\n" + "==========  Record[4]: HISTORY  ==========\n" + "Tool:  dmappend\n" + "Date:  \n" + "Params:\n" + "   infile = /export/proc/tmp.ascdsl3/prs_run/tmp//L3AMRF____587231988n944/output/acisf05017_000N022_r0001b_psf3.fits[acisf05017_000N022_r0001b_psf3.fits][BINPSF]\n" + "   outfile = /export/proc/tmp.ascdsl3/prs_run/tmp//L3AMRF____587231988n944/output/acisf05017_000N022_r0001b_psf3_tmp.fits\n" + "   verbose = 0\n" + "ASCNUM:  66\n" + "\n" + "==========  Record[5]: HISTORY  ==========\n" + "Tool:  dmsomething\n" + "Date:  2017-12-01T14:00:00\n" + "Params:\n" + "   infile = @in.lis\n" + "      > stack1.fits\n" + "      > stack2.fits\n" + "   outfile = out.fits\n" + "   tol = tolerance\n" + "ASCNUM:  77\n" + "\n" + "==========  Record[6]: COMMENT  ==========\n" + "Content:    <Completely BLANK Line>\n" + "\n" + "==========  Record[7]: COMMENT  ==========\n" + "Content:    ''\n\n" 

        # check str/repr output
        result = str(history)
        self.assertEqual(result, expected, "cxchistory str/repr FAILED" )

        # check if correct number of comments records after reading
        self.assertEqual( history.ncomments, 3, "get_ncomments() FAILED")

        # check if correct number of history records after reading
        self.assertEqual(history.nhistory, 5,"get_nhistory() FAILED" )

        # check if correct number of records after reading
        self.assertEqual(history.nrecords, (history.nhistory + history.ncomments),"get_nrecords() FAILED")

        # check delete comment records function
        history.delete_comments()
        self.assertEqual( history.nrecords,  5, "delete_comments() FAILED")
        self.assertEqual( history.ncomments, 0, "delete_comments() FAILED" )

        # check delete history records function
        history.delete_history()
        self.assertEqual(history.nrecords, 0, "delete_history() FAILED")


    def test_04(self):
        # ---------------------------------------------------------------------------------------
        # Tests for add_history_record(self, tool, date, param_names, param_values, param_stacks )
        # ---------------------------------------------------------------------------------------

        # Construct empty CXCHistory and add records/history/comments
        try:
            history = CXCHistory()
        except Exception as ex:
            print(str(ex))
            raise Exception("create empty CXCHistory FAILED")

        # Call add_history_record() with various argument sets.

        # o no arguments
        try:
            history.add_history_record()
        except Exception as ex:
            if "takes at least 2 arguments" in str(ex): # Python 2 message
                pass
            elif "missing 1 required positional argument" in str(ex): # Python 3 message
                pass
            else:
                print(str(ex))
                raise Exception("add_history_record() - no argument test FAILED")


        # o missing date and param arguments; date=default; param defaults make empty lists
        try:
            history.add_history_record( "myTool" )
        except Exception as ex:
            print(str(ex))
            raise Exception("add_history_record( tool ) FAILED")
        self.assertEqual( history.records[0].as_command(), 'myTool ', "add_history_record( tool ) FAILED"  )
        

        # o missing param arguments: OK.. defaults make empty lists
        try:
            history.add_history_record( "myTool", date=None )
        except Exception as ex:
            print(str(ex))
            raise Exception("add_history_record( tool, date ) FAILED")
        self.assertEqual( history.records[1].as_command(), 'myTool ', "add_history_record( tool, date ) FAILED"  )


        # o missing param_names: 
        try:
            history.add_history_record( "myTool", date=None, param_values=["@indata.lis"] )
        except Exception as ex:
            if "Parameter names list is required" not in str(ex):
                print(str(ex))
                raise Exception("add_history_record( tool, date, param_values ) FAILED")

        # o missing param_values
        try:
            history.add_history_record( "myTool", date=None, param_names=["infile"] )
        except Exception as ex:
            if "Parameter values list is required" not in str(ex):
                print(str(ex))
                raise Exception("add_history_record( tool, date, param_values ) FAILED")

        # o even number of parameter list entries (stacks auto-handled)
        try:
            history.add_history_record( "myTool", date=None, param_names=["infile"], param_values=["@indata.lis"] )
        except Exception as ex:
            print(str(ex))
            raise Exception("add_history_record( tool, date, names, values ) - good, FAILED")
        expected = 'myTool infile=@indata.lis '
        self.assertEqual( history.records[2].as_command(), expected , "add_history_record(tool, date, names, values ) - good, FAILED"  )

        # o even number of parameter list entries
        try:
            history.add_history_record( "myTool", date=None, param_names=["infile"], param_values=["@indata.lis"], param_stacks=[["file1","file2"]] )
        except Exception as ex:
            print(str(ex))
            raise Exception("add_history_record( tool, date, names, values, stacks ) - good, FAILED")
        expected = 'myTool infile=@indata.lis '
        self.assertEqual( history.records[3].as_command(), expected , "add_history_record(tool, date, names, values, stacks ) - good, FAILED"  )

        # o uneven number of parameter list entries (stacks auto-handled)
        try:
            history.add_history_record( "myTool", date=None, param_names=["infile", "outfile" ], param_values=["indata.fits"] )
        except Exception as ex:
            if "Parameter names and values lists must be the same length" not in str(ex):
                print(str(ex))
                raise Exception("add_history_record( tool, date, param_values ) FAILED")

        # o uneven number of parameter list entries
        pnames = ["infile", "outfile" ]
        pvals  = ["@infiles.lis", "outdata.fits"]
        pstack = [["indt001.fits","indt002.fits"]]
        try:
            history.add_history_record( "myTool", date=None, param_names=pnames, param_values=pvals, param_stacks=pstack  )
        except Exception as ex:
            if "Parameter stacks list must be the same length as names and values lists" not in str(ex):
                print(str(ex))
                raise Exception("add_history_record( tool, date, param_values ) FAILED")

        # o parameter values of varying type (stacks not involved)
        pnames = ["infile", "sigma", "clobber" ]
        pvals  = ["indata.fits", 6, True ]
        pstack = None
        try:
            history.add_history_record( "myTool", date=None, param_names=pnames, param_values=pvals, param_stacks=pstack  )
        except Exception as ex:
            print(str(ex))
            raise Exception("add_history_record() - parameter values of varying type, FAILED")
        expected = 'myTool infile=indata.fits sigma=6 clobber=True '
        self.assertEqual( history.records[4].as_command(), expected , "add_history_record() - parameter values of varying type, FAILED" )



if __name__ == '__main__':
    unittest.main(verbosity=5)
