001package edu.pdx.cs.joy.family;
002
003import org.junit.jupiter.api.Test;
004import org.junit.jupiter.api.io.TempDir;
005
006import java.io.File;
007import java.io.PrintWriter;
008import java.io.StringWriter;
009import java.lang.reflect.Field;
010import java.lang.reflect.Modifier;
011import java.util.StringTokenizer;
012
013import static org.junit.jupiter.api.Assertions.fail;
014
015/**
016 * This class tests the behavior of the {@link AddPerson} program to
017 * ensure that I don't again suffer the kind of embarrassment I
018 * suffered in the Spring of 2002 when my students found a bunch of
019 * bugs in my code.
020 */
021public class AddPersonTest {
022
023  private static final boolean DEBUG =
024    Boolean.getBoolean("AddPersonTest.DEBUG");
025
026  /**
027   * Invokes the main method of AddPerson with the given command line
028   * string 
029   */
030  private void addPerson(String cmdLine) {
031    if (DEBUG) {
032      System.out.println("\n" + cmdLine + "\n");
033    }
034
035    // Create an array of Strings to send to main
036    StringTokenizer st = new StringTokenizer(cmdLine);
037    String[] args = new String[st.countTokens()];
038    for (int i = 0; st.hasMoreTokens(); i++) {
039      args[i] = st.nextToken();
040    }
041
042    AddPerson.main(args);
043    reset(AddPerson.class);
044  }
045
046  /**
047   * "Resets" all of the static fields in a given class to their
048   * default value
049   */
050  private static void reset(Class c) {
051    Field[] fields = c.getDeclaredFields();
052    for (int i = 0; i < fields.length; i++) {
053      Field field = fields[i];
054      if (!Modifier.isFinal(field.getModifiers())) {
055        field.setAccessible(true);
056        try {
057          reset(field);
058
059        } catch (IllegalAccessException ex) {
060          StringWriter sw = new StringWriter();
061          sw.write("While accessing field " + field + ": ");
062          ex.printStackTrace(new PrintWriter(sw, true));
063          fail(sw.toString());
064        }
065      }
066    }
067  }
068
069  /**
070   * "Resets" the value of the given static field to its default value
071   */
072  private static void reset(Field field)
073    throws IllegalAccessException {
074
075    Class type = field.getType();
076    if (type.equals(boolean.class)) {
077      field.set(null, Boolean.FALSE);
078
079    } else if (type.equals(char.class)) {
080      field.set(null, '\0' );
081
082    } else if (type.equals(byte.class)) {
083      field.set(null, (byte) 0 );
084
085    } else if (type.equals(short.class)) {
086      field.set(null, (short) 0 );
087
088    } else if (type.equals(int.class)) {
089      field.set(null, 0 );
090
091    } else if (type.equals(long.class)) {
092      field.set(null, 0L );
093
094    } else if (type.equals(float.class)) {
095      field.set(null, 0.0f );
096
097    } else if (type.equals(double.class)) {
098      field.set(null, 0.0 );
099
100    } else {
101      assert Object.class.isAssignableFrom(type) : type;
102      field.set(null, null);
103    }
104  }
105  
106  /**
107   * Invokes the main method of NoteMarriage with the given command line
108   * string 
109   */
110  private void noteMarriage(String cmdLine) {
111    if (DEBUG) {
112      System.out.println("\n" + cmdLine + "\n");
113    }
114
115    // Create an array of Strings to send to main
116    StringTokenizer st = new StringTokenizer(cmdLine);
117    String[] args = new String[st.countTokens()];
118    for (int i = 0; st.hasMoreTokens(); i++) {
119      args[i] = st.nextToken();
120    }
121
122    NoteMarriage.main(args);
123    reset(NoteMarriage.class);
124  }
125  
126  /**
127   * Create a family tree that describes Dave's family.
128   *
129   * @param fileOption
130   *        The kind of file to use
131   */
132  private void createDavesFamily(File tempDir, String fileOption) {
133    // Create a temp file to write the family tree to
134    File file = new File(tempDir, "DavesFamily" + fileOption);
135
136    // XML parser complains about empty file, so delete it before we
137    // start
138    file.delete();
139
140    String fileName = file.getAbsolutePath();
141
142    
143    addPerson(fileOption + fileName +
144              " 1 male David Michael Whitlock");
145    
146    addPerson(fileOption + "-parentOf 1 " + fileName + 
147              " 2 male Stanley Jay Whitlock Feb 27, 1948");
148
149    addPerson(fileOption + "-parentOf 1 " + fileName + 
150              " 3 female Carolyn Joyce Granger May 17, 1945");
151
152    noteMarriage(fileOption + "-date Jul 12, 1969 " + fileName +
153                 " 2 3 ");
154
155    // If we get this far, delete the file
156    file.delete();
157  }
158
159  ////////  Test cases
160
161  @Test
162  public void testText(@TempDir File tempDir) {
163    createDavesFamily(tempDir, "");
164  }
165
166  @Test
167  public void testXml(@TempDir File tempDir) {
168    createDavesFamily(tempDir, "-xml ");
169  }
170}