Index: tests/millennium_basic_functions.test
--- tests/millennium_basic_functions.test No Base Revision
+++ tests/millennium_basic_functions.test Locally New
@@ -0,0 +1,213 @@
+<?php
+// $Id$
+/**
+ * @file
+ * Tests for Millennium Integration module
+ */
+
+/**
+ * Millennium: Basic functions tests
+ */
+class DrupalMillenniumBasicTests extends DrupalWebTestCase {
+  function getInfo() {
+    return array(
+      'name' => 'Millennium: Basic functions tests',
+      'description' => 'Verify MARC record parsing and other basic functions.',
+      'group' => 'Millennium'
+    );
+  }
+
+  // These functions are expensive: they set up a database copy with a random
+  // prefix to use during tests. Do not use unless changing the database.
+  function setUp() {
+    parent::setUp('taxonomy', 'millennium');
+  }
+  function tearDown() {
+    parent::tearDown();
+  }
+
+  private $marc_tests = array(
+    array(
+      'marc_text' => 'LEADER 00000nam  2200000 i 4500
+001    88351368
+008    770712s1988    hu a     b    00010 eng
+020    9686127232
+050    SB 191.W5|bS5 1988
+100 1  Simmonds, N. W
+245 10 Breeding strategies for resistance to the rusts of wheat /
+       |cN. W. Simmonds and S. Rajaram
+260 0  Mexico :|bCIMMYT,|c1988
+300    151 p. :|bill. &#59;|c25 cm
+504    Includes bibliographical references and index
+650  0 Mejoramiento selectivo del trigo
+700 1  Rajaram, S ',
+      'biblio_data' => array(
+        'title' => 'Breeding strategies for resistance to the rusts of wheat',
+        'lcc' => 'SB 191.W5 S5 1988',
+        'authors' => 'Simmonds, N. W; Rajaram, S',
+        // TODO: Add more fields to compare
+      )
+    ),
+    array (
+      'marc_text' => 'LEADER 00000cam  2200337Ia 4500
+001    tec012110346
+003    MX-MoT
+008    090325s2008    caua          001 0 eng d
+020    9781430209898
+020    1430209895
+050  4 TK5105.8885.D78|bV36 2008
+100 1  VanDyk, John K.
+245 10 Pro Drupal development /|cJohn K. VanDyk.
+250    2nd ed.
+260    Berkeley, [Calif.] :|bApress,|cc2008.
+300    xxxiii, 667 p. :|bil. ;|c24 cm.
+490 1  Expert\'s voice in open source
+500    "Now covers Drupal 6"--Cubierta.
+500    Incluye índice.
+650  0 Drupal (Computer program language)
+650  0 Web site development.
+650  4 Drupal (Lenguaje de programación para computadora)
+650  4 Desarrollo de sitios web.
+929    mty /|bmtyvescamil ;|zcemlcarrouch',
+      'biblio_data' => array(
+        'title' => 'Pro Drupal development',
+        'lcc' => 'TK5105.8885.D78 V36 2008',
+        'authors' => 'VanDyk, John K',
+        // TODO: Add more fields to compare
+      )
+    )
+  );
+
+  // Helper function to test for identical arrays (keys and values)
+  private function array_identical($a, $b) {
+    return (is_array($a) && is_array($b) && array_diff_assoc($a, $b) === array_diff_assoc($b, $a));
+  }
+
+  function testBasicFunctions() {
+
+    // Test MARC parsing
+    foreach ($this->marc_tests as $testnum => $testcase) {
+      $biblio_data = millennium_marc_to_biblio($testcase['marc_text']);
+      // Check marc was parsed correctly
+      foreach ($testcase['biblio_data'] as $fieldname => $fieldvalue) {
+        if ($fieldname) {
+          if (!is_array($fieldvalue)) {
+            $this->assertEqual($fieldvalue, $biblio_data[$fieldname], 
+              t("Test %testnum fieldname %fieldname: got value %got, expected %expected",
+                array(
+                  '%testnum' => $testnum, 
+                  '%fieldname' => $fieldname, 
+                  '%got' => var_export($biblio_data[$fieldname], TRUE), 
+                  '%expected' => var_export($fieldvalue, TRUE)
+                )
+              )
+            );
+          }
+          else {
+            // Compare array
+            $result = $this->array_identical($fieldvalue, $biblio_data[$fieldname]);
+            $this->assertTrue($result,
+              t("Test %testnum fieldname %fieldname: got value %got, expected %expected",
+                array(
+                  '%testnum' => $testnum,
+                  '%fieldname' => $fieldname,
+                  '%got' => var_export($biblio_data[$fieldname], TRUE),
+                  '%expected' => var_export($fieldvalue, TRUE)
+                )
+              )
+            );
+          }
+        }
+      }
+    }
+
+
+    // Test the get_real_baseurl parser
+    // Bad URLs
+    $bad_urls = explode('|', 'http:/example.com|example.com|ftp://example.com');
+    foreach ($bad_urls as $bad_url) {
+      $this->assertFalse(millennium_get_real_baseurl($bad_url), "Bad base URL");
+    }
+    // Good URLs
+    $this->assertEqual(millennium_get_real_baseurl("http://example.com"), "http://example.com", "Good base URL");
+    $this->assertEqual(millennium_get_real_baseurl("http://example.com:2082/"), "http://example.com:2082", "Good base URL");
+    $this->assertEqual(millennium_get_real_baseurl("https://example.com:2082/foo/bar"), "https://example.com:2082", "Good base URL");
+
+    
+    // Test the OPAC pinging function
+    $opacs_baseurls = array(
+      'http://millennium.itesm.mx',
+      'http://library.dcccd.edu',
+      'http://irma.aadl.org',
+      'http://catalog.nypl.org',
+      'http://www.consuls.org',
+      'http://www.helmet.fi',
+      'http://eleanor.lib.gla.ac.uk',
+    );
+    foreach ($opacs_baseurls as $base_url) {
+      $this->assertTrue(millennium_ping($base_url), "Pinging $base_url");
+    }
+
+    // Test the OPAC search result scraping function
+    require_once(drupal_get_path('module', 'millennium') . '/millennium.import.inc');
+    foreach ($opacs_baseurls as $base_url) {
+      $records = millennium_query_scrape("test OR how", $base_url, 10);
+      $this->assertEqual(sizeof($records), 10, "Scraping query at $base_url");
+    }
+  }
+  
+  /*
+  function testTaxonomyAssign() {
+    // Create a node type to import records into
+    $test_node_type = $this->DrupalCreateContentType();
+    $this->assertEqual(1, 1, var_export($test_node_type, TRUE));
+    
+    // Create a tags taxonomy
+    $vocabulary = array(
+      'name' => 'Millennium simpletest vocabulary',
+      'description' => '',
+      'help' => '',
+      'nodes' => array($test_node_type->type => TRUE), // Use the newly-created node type
+      'hierarchy' => 0,
+      'relations' => 1, // allow related terms
+      'tags' => 1,
+      'multiple' => 0,
+      'required' => 0,
+      'weight' => 0,
+      'module' => 'taxonomy',
+      'type' => array($test_node_type->type),
+    );
+    taxonomy_save_vocabulary($vocabulary);
+    $test_vid = $vocabulary['vid'];
+    $this->assertEqual(1, 1, var_export($vocabulary, TRUE));
+
+    // Set up sources
+    $test_base_url = 'http://example.com';
+    $sources = array(
+      $test_base_url => array('name' => 'OPAC Name')
+    );
+    $millennium_sources_bak = variable_get('millennium_sources', array());
+    variable_set('millennium_sources', $sources);
+    $this->assertEqual(1, 1, var_export($sources, TRUE));
+    
+    // Build a new node
+    $node = $this->drupalCreateNode(array('type' => $test_node_type->type));
+
+    // Test opacname taxonomy assignment
+    $node_tmp = $node;
+    millennium_add_taxonomy_opacname_to_node($node_tmp, 'http://example.com');
+    $millennium_opacname_vid_bak = variable_get('millennium_opacname_vid', -1);
+    variable_set('millennium_opacname_vid', $test_vid);
+    dpm($node_tmp);
+    $this->assertEqual('"' . $sources[$test_base_url]['name'] . '"', $node_tmp->taxonomy['tags'][$test_vid],
+      "Name = " . $sources[$test_base_url]['name'] . " Tags = " . var_export($node_tmp, TRUE));
+
+    // Delete taxonomy
+    taxonomy_del_vocabulary($test_vid);
+
+    // Restore sources
+    variable_set('millennium_sources', $millennium_sources_bak);
+    variable_set('millennium_opacname_vid', $millennium_opacname_vid_bak);
+  }
+  */
+}
Index: tests/millennium_crawling_functions.test
--- tests/millennium_crawling_functions.test No Base Revision
+++ tests/millennium_crawling_functions.test Locally New
@@ -0,0 +1,53 @@
+<?php
+// $Id$
+/**
+ * @file
+ * Tests for Millennium Integration module
+ */
+
+/**
+ * Millennium: Crawling functions tests
+ */
+class DrupalMillenniumCrawlingTests extends DrupalWebTestCase {
+  function getInfo() {
+    return array(
+      'name' => 'Millennium: Crawling functions tests',
+      'description' => 'Verify result list scraping, mass record fetching from book cart and other functions.',
+      'group' => 'Millennium'
+    );
+  }
+
+  function testCrawling() {
+    // Include needed files
+    require_once(drupal_get_path("module", "millennium") . "/millennium.import.inc");
+    
+    // Some known OPAC base urls
+    $opacs_baseurls = array(
+      'http://millennium.itesm.mx',
+      'http://catalog.nypl.org',
+      'http://www.consuls.org',
+      'http://www.helmet.fi',
+      'http://eleanor.lib.gla.ac.uk',
+    );
+
+    // Test the OPAC search result scraping function
+    foreach ($opacs_baseurls as $base_url) {
+      $records[$base_url] = millennium_query_scrape("mattype:mattypea", $base_url, 10);
+      $record_count = sizeof($records[$base_url]);
+      $this->assertTrue(($record_count == 10), "Scraping query for at least 10 records at $base_url");
+    }
+
+
+    // Test the book cart fetching function
+    foreach ($records as $base_url => $recnums) {
+       // Only use successful fetches (10 out of 10) from the earlier tests
+       if (sizeof($recnums) != 10) {
+         continue;
+       }
+       $result = millennium_fetch_records_via_bookcart($recnums, false, $base_url);
+       $count_found = sizeof($result['found']);
+       $this->assertTrue(($count_found >= 9), "Bookcart fetch $count_found out of 10 records at $base_url");
+    }
+  }
+
+}
\ No newline at end of file
