Index: branches/release-35/t/20-setup.t
===================================================================
--- branches/release-35/t/20-setup.t (revision 1458)
+++ branches/release-35/t/20-setup.t (revision 1927)
@@ -39,4 +39,5 @@
 ObjectDriver DBI::sqlite
 PluginPath ../plugins
+PluginPath plugins
 CFG
     close $fh;
Index: branches/release-35/t/22-author.t
===================================================================
--- branches/release-35/t/22-author.t (revision 1100)
+++ branches/release-35/t/22-author.t (revision 1927)
@@ -8,5 +8,5 @@
 use lib 'extlib';
 
-use Test::More tests => 54;
+use Test::More tests => 64;
 
 use MT;
@@ -34,6 +34,6 @@
 my $perm = $author->blog_perm(1);
 ok($perm, "$author->blog_perm(1)") || die;
-ok($author->can_edit_entry(1), 'can_edit_entry(1)');
-ok($author->can_edit_entry(2), 'can_edit_entry(2)');
+ok($author->can_edit_entry(1), 'Chuck D can edit entry #1');
+ok($author->can_edit_entry(2), 'Chuck D can edit entry #2');
 ok($perm->can_comment, 'can_comment');
 ok($perm->can_post, 'can_post');
@@ -58,4 +58,39 @@
 
 {
+diag('meta field tests');
+
+my $author = MT::Author->load({ name => 'Chuck D' });
+ok(eval { $author->widgets(); 1 }, 'Author obj has widgets accessor');
+ok(!defined $author->widgets, "Author's widgets are undefined by default");
+ok(!defined $author->favorite_blogs, "Author's favorite blogs are undefined by default");
+
+    # same as in MT::CMS::Dashboard, but that's not necessary
+    my $default_widgets = {
+        'blog_stats' =>
+          { param => { tab => 'entry' }, order => 1, set => 'main' },
+        'this_is_you-1' => { order => 1, set => 'sidebar' },
+        'mt_shortcuts'  => { order => 2, set => 'sidebar' },
+        'mt_news'       => { order => 3, set => 'sidebar' },
+    };
+
+my $fav_blogs = [1, 7];  # not actually a blog #7, but meh
+
+ok($author->widgets($default_widgets), "Author's widgets can be set");
+ok($author->favorite_blogs($fav_blogs), "Author's favorite blogs can be set");
+ok($author->save(), "Author with modified widgets can be saved");
+
+require MT::ObjectDriver::Driver::Cache::RAM;
+MT::ObjectDriver::Driver::Cache::RAM->clear_cache();
+
+$author = MT::Author->load({ name => 'Chuck D' });
+
+ok($author->widgets, "Modified author has widgets");
+is_deeply($author->widgets, $default_widgets, "Author's widgets survived being saved accurately");
+
+ok($author->favorite_blogs, "Modified author has favorite blogs");
+is_deeply($author->favorite_blogs, $fav_blogs, "Author's favorite blogs survived being saved accurately");
+}
+
+{
 my $author = MT::Author->load({ name => 'Bob D' });
 $author = MT::Author->load($author->id);  # silly ruse to force caching.... 
@@ -68,18 +103,18 @@
 ok( ! $author->can_view_log, 'can_view_log' );
 ok( ! $author->can_manage_plugins, 'can manage plugins');
-ok( ! $author->can_edit_entry(1), 'can_edit_entry(1)' );
-ok(   $author->can_edit_entry(2), 'can_edit_entry(2)' );
+ok( ! $author->can_edit_entry(1), 'Bob D can edit entry #1' );
+ok(   $author->can_edit_entry(2), 'Bob D can edit entry #2' );
 ok(   $perm->can_post, 'can_post' );
 ok(   $perm->can_create_post, 'can_create_post');
 ok(   $perm->can_publish_post, 'can_publish_post');
-ok( ! $perm->can_upload, 'can_upload' );
-ok( ! $perm->can_edit_all_posts, 'can_edit_all_posts' );
+ok(   $perm->can_upload, 'Bob D can *not* upload files' );
+ok( ! $perm->can_edit_all_posts, 'Bob D can *not* edit all posts' );
 ok( ! $perm->can_manage_pages, 'can_manage_pages');
-ok(   $perm->can_edit_templates, 'can_edit_templates' );
+ok( ! $perm->can_edit_templates, 'Bob D can *not* edit templates' );
 ok( ! $perm->can_edit_tags, 'can_edit_tags');
 ok( ! $perm->can_edit_config, 'can_edit_config' );
 ok( ! $perm->can_set_publish_paths, 'can_set_publish_paths');
 ok( ! $perm->can_rebuild, 'can_rebuild' );
-ok( ! $perm->can_send_notifications, 'can_send_notifications' );
+ok(   $perm->can_send_notifications, 'Bob D can send notifications' );
 ok( ! $perm->can_edit_categories, 'can_edit_categories' );
 ok( ! $perm->can_edit_notifications, 'can_edit_notifications' );
Index: branches/release-35/t/lib/MT/Test.pm
===================================================================
--- branches/release-35/t/lib/MT/Test.pm (revision 1652)
+++ branches/release-35/t/lib/MT/Test.pm (revision 1927)
@@ -6,4 +6,6 @@
 use File::Spec;
 use MT;
+
+use Test::More;
 
 BEGIN {
@@ -34,7 +36,15 @@
     my $pkg = shift;
     foreach my $opt (@_) {
-        $pkg->init_db() if $opt eq ':db';
-        $pkg->init_test_db() if $opt eq ':testdb';
-        $pkg->sample_data() if $opt eq ':data';
+        if ($opt eq ':db') {
+            diag "Initializing database";
+            $pkg->init_db();
+        }
+        elsif ($opt eq ':testdb') {
+            $pkg->init_test_db();
+        }
+        elsif ($opt eq ':data') {
+            diag "Initializing sample data";
+            $pkg->sample_data();
+        }
     }
 }
@@ -74,11 +84,16 @@
 
     my $types = MT->registry('object_types');
-    my @classes = map { $types->{$_} } grep { $_ !~ /\./ } keys %$types;
+    $types->{$_} = MT->model($_) for
+        grep { MT->model($_) }
+        map  { $_ . ':meta' }
+        grep { MT->model($_)->meta_pkg }
+        sort keys %$types;
+    my @classes = map { $types->{$_} } grep { $_ !~ /\./ } sort keys %$types;
     foreach my $class (@classes) {
         if (ref($class) eq 'ARRAY') {
             next; #TODO for now - it won't hurt when we do driver-tests.
         }
-        else {
-            eval 'require '.$class or die $@;
+        elsif (!defined *{ $class . '::__properties' }) {
+            eval '# line ' . __LINE__ . ' ' . __FILE__ . "\n" . 'require '.$class or die $@;
         }
     }
@@ -109,4 +124,5 @@
     );
     eval {
+        # line __LINE__ __FILE__
         MT::Entry->remove;
         MT::Comment->remove;
@@ -151,4 +167,5 @@
     $blog->commenter_authenticators('enabled_TypeKey');
     $blog->save() or die "Couldn't save blog 1: ". $blog->errstr;
+    diag "Saved blog";
 
     require MT::Entry;
@@ -169,4 +186,5 @@
     $chuckd->save()
         or die "Couldn't save author record 2: " . $chuckd->errstr;
+    diag "Saved user Chuck D";
 
     my $bobd = MT::Author->new();
@@ -181,4 +199,5 @@
     $bobd->id(3);
     $bobd->save() or die "Couldn't save author record 3: " . $bobd->errstr;
+    diag "Saved user Bob D";
 
     my $johnd = MT::Author->new();
@@ -193,4 +212,5 @@
     $johnd->id(4);
     $johnd->save() or die "Couldn't save author record 4: " . $johnd->errstr;
+    diag "Saved user John Doe";
 
     my $hiro = MT::Author->new();
@@ -206,4 +226,9 @@
     $hiro->status(2);
     $hiro->save() or die "Couldn't save author record 5: " . $hiro->errstr;
+    diag "Saved user Hiro";
+
+    require MT::Role;
+    my ($admin_role, $author_role) = map { MT::Role->load({ name => $_ }) }
+        ('Blog Administrator', 'Author');
 
     require MT::Association;
@@ -211,5 +236,5 @@
     $assoc->author_id($chuckd->id);
     $assoc->blog_id(1);
-    $assoc->role_id(3);
+    $assoc->role_id($admin_role->id);
     $assoc->type(1);
     $assoc->save();
@@ -218,5 +243,5 @@
     $assoc->author_id($bobd->id);
     $assoc->blog_id(1);
-    $assoc->role_id(4);
+    $assoc->role_id($author_role->id);
     $assoc->type(1);
     $assoc->save();
@@ -225,5 +250,5 @@
     $assoc->author_id($hiro->id);
     $assoc->blog_id(1);
-    $assoc->role_id(3);
+    $assoc->role_id($admin_role->id);
     $assoc->type(1);
     $assoc->save();
@@ -255,4 +280,5 @@
         $entry->tags('rain', 'grandpa', 'strolling');
         $entry->save() or die "Couldn't save entry record 1: ".$entry->errstr;
+        diag "Saved entry #1";
     }
 
@@ -275,4 +301,5 @@
         $entry->id(2);
         $entry->save() or die "Couldn't save entry record 2: ".$entry->errstr;
+        diag "Saved entry #2";
     }
 
@@ -297,4 +324,5 @@
         $entry->tags('anemones');
         $entry->save() or die "Couldn't save entry record 3: ".$entry->errstr;
+        diag "Saved entry #3";
     }
 
@@ -327,4 +355,5 @@
         $ping->visible(1);
         $ping->save or die "Couldn't save TBPing record 1: " . $ping->errstr;
+        diag "Saved a trackback ping";
     }
 
@@ -355,4 +384,5 @@
         $cat->id(1);
         $cat->save or die "Couldn't save category record 1: ". $cat->errstr;
+        diag "Saved category foo";
     }
 
@@ -367,4 +397,5 @@
         $cat->id(2);
         $cat->save or die "Couldn't save category record 2: ". $cat->errstr;
+        diag "Saved category bar";
     }
 
@@ -379,4 +410,5 @@
         $tb->id(2);
         $tb->save or die "Couldn't save Trackback record 2: " . $tb->errstr;;
+        diag "Saved category bar's trackback target";
     }
 
@@ -391,4 +423,5 @@
         $cat->id(3);
         $cat->save or die "Couldn't save category record 3: ". $cat->errstr;
+        diag "Saved subcategory subfoo";
     }
 
@@ -427,4 +460,5 @@
                 $place->save
                     or die "Couldn't save placement record: ".$place->errstr;
+                diag "Placed entry Verse 3 in category foo";
             }
             if ($i == 4) {
@@ -436,4 +470,5 @@
                 $place->save
                     or die "Couldn't save placement record: ".$place->errstr;
+                diag "Placed entry Verse 4 in category subfoo";
             }
         }
@@ -458,4 +493,5 @@
         $cmt->id(1);
         $cmt->save() or die "Couldn't save comment record 1: ".$cmt->errstr;
+        diag "Saved comment #1";
 
         $cmt->id(11);
@@ -465,4 +501,5 @@
         $cmt->parent_id(1);
         $cmt->save() or die "Couldn't save comment record 11: ".$cmt->errstr;
+        diag "Saved child comment #11";
 
         $cmt->id(12);
@@ -472,4 +509,5 @@
         $cmt->parent_id(11);
         $cmt->save() or die "Couldn't save comment record 12: ".$cmt->errstr;
+        diag "Saved child comment #12";
     }
     # entry id 5 - 1 comment, commenting is off (closed)
@@ -587,4 +625,5 @@
     $tmpl->type('custom');
     $tmpl->save or die "Couldn't save template record 1: ".$tmpl->errstr;
+    diag "Saved blog-name template";
 
     ### Asset
@@ -600,4 +639,5 @@
     $asset->file_ext('jpg');
     $asset->image_width(640);
+    diag "Set image asset's width metadata field";
     $asset->image_height(480);
     $asset->mime_type('image/jpeg');
@@ -606,5 +646,7 @@
     $asset->created_by(1);
     $asset->tags('alpha', 'beta', 'gamma');
-    $asset->save;
+    diag "Tagged image asset";
+    $asset->save or die "Couldn't save asset record 1: " . $asset->errstr;
+    diag "Saved image asset";
 
     $asset->set_score('unit test', $bobd, 5, 1);
@@ -624,5 +666,6 @@
     $asset->created_on('19780131074500');
     $asset->tags('beta');
-    $asset->save;
+    $asset->save or die "Couldn't save file asset record: " . $asset->errstr;
+    diag "Saved file asset";
 
     $asset->set_score('unit test', $chuckd, 2, 1);
@@ -642,4 +685,5 @@
     $e4->set_score('unit test', $chuckd, 2, 1);
     $e4->set_score('unit test', $johnd, 3, 1);
+    diag "Saved scores for entry #4";
 
     ## Page
@@ -672,4 +716,5 @@
     $folder->id(20);
     $folder->save or die "Could'n sae folder record 20:" . $folder->errstr;
+    diag "Saved folder #20";
 
     $folder = MT::Folder->new();
Index: branches/release-35/t/09-image.t
===================================================================
--- branches/release-35/t/09-image.t (revision 1100)
+++ branches/release-35/t/09-image.t (revision 1927)
@@ -25,5 +25,7 @@
     );
     @drivers = qw( ImageMagick NetPBM );
-    plan tests => scalar @Img + scalar @Img * scalar @drivers * 17;
+    plan tests => scalar @Img                           # file exists
+                + (scalar @Img * scalar @drivers * 18)  # 18 tests each for every image and driver
+                ;
 }
 
@@ -38,5 +40,6 @@
 
 for my $rec (@Img) {
-    my $img_file = File::Spec->catfile($BASE, 't', 'images', $rec->[0]);
+    my ($img_filename, $img_width, $img_height) = @$rec;
+    my $img_file = File::Spec->catfile($BASE, 't', 'images', $img_filename);
     ok(-B $img_file, "$img_file looks like a binary file");
 
@@ -46,29 +49,33 @@
 SKIP : {
         skip("no $driver image", 17) unless $img;
-        isa_ok($img, 'MT::Image::' . $driver);
+        isa_ok($img, 'MT::Image::' . $driver, "driver $driver with image $img_file is an MT::Image::$driver");
 #        diag( MT::Image->errstr ) if MT::Image->errstr;
 
-        is($img->{width}, $rec->[1], "width is $rec->[1]");
-        is($img->{height}, $rec->[2], "height is $rec->[2]");
-        my($w, $h) = $img->get_dimensions;
-        is($w, $rec->[1], "width is $rec->[1]");
-        is($h, $rec->[2], "height is $rec->[2]");
+        is($img->{width},  $img_width,  "$driver says $img_filename is $img_width px wide");
+        is($img->{height}, $img_height, "$driver says $img_filename is $img_height px high");
+        my($w, $h) = $img->get_dimensions();
+        is($w, $img_width,  "${driver}'s get_dimensions says $img_filename is $img_width px wide");
+        is($h, $img_height, "${driver}'s get_dimensions says $img_filename is $img_height px high");
 
         ($w, $h) = $img->get_dimensions(Scale => 50);
-        my($x, $y) = (int($img->{width} / 2), int($img->{height} / 2));
-        is($w, $x, "width is $x");
-        is($h, $y, "height is $y");
+        my($x, $y) = (int($img_width / 2), int($img_height / 2));
+        is($w, $x, "$driver says $img_filename at 50\% scale is $x px wide");
+        is($h, $y, "$driver says $img_filename at 50\% scale is $y px high");
+
+        ($w, $h) = $img->get_dimensions();
+        is($w, $img_width,  "${driver}'s get_dimensions says $img_filename is still $img_width px wide after theoretical scaling");
+        is($h, $img_height, "${driver}'s get_dimensions says $img_filename is still $img_height px high after theoretical scaling");
 
         ($w, $h) = $img->get_dimensions(Width => 50);
-        is($w, 50, 'width is 50');
+        is($w, 50, "$driver says $img_filename scaled to 50 px wide is 50 px wide");
 
         ($w, $h) = $img->get_dimensions(Width => 50, Height => 100);
-        is($w, 50, 'width is 50');
-        is($h, 100, 'height is 100');
+        is($w, 50,  "$driver says $img_filename scaled to 50x100 is 50 px wide");
+        is($h, 100, "$driver says $img_filename scaled to 50x100 is 100 px high");
 
         (my($blob), $w, $h) = $img->scale(Scale => 50);
-        ($x, $y) = (int($img->{width} / 2), int($img->{height} / 2));
-        is($w, $x, "width is $x");
-        is($h, $y, "height is $y");
+        ($x, $y) = (int($img_width / 2), int($img_height / 2));
+        is($w, $x, "result of scaling $img_filename to 50\% with $driver is $x px wide");
+        is($h, $y, "result of scaling $img_filename to 50\% with $driver is $y px high");
 
         open FH, $img_file or die $!;
@@ -80,9 +87,9 @@
         isa_ok($img, 'MT::Image::' . $driver);
 #            diag( MT::Image->errstr ) if MT::Image->errstr;
-        is($img->{width}, $rec->[1], "width is $rec->[1]");
-        is($img->{height}, $rec->[2], "height is $rec->[2]");
+        is($img->{width},  $img_width,  "$driver says $img_filename from blob is $img_width px wide");
+        is($img->{height}, $img_height, "$driver says $img_filename from blob is $img_height px high");
         ($w, $h) = $img->get_dimensions;
-        is($w, $rec->[1], "width is $rec->[1]");
-        is($h, $rec->[2], "height is $rec->[2]");
+        is($w, $img_width,  "${driver}'s get_dimensions says $img_filename from blob is $img_width px wide");
+        is($h, $img_height, "${driver}'s get_dimensions says $img_filename from blob is $img_height px high");
 } # END SKIP
     }
Index: branches/release-35/t/plugins/Awesome/config.yaml
===================================================================
--- branches/release-35/t/plugins/Awesome/config.yaml (revision 1927)
+++ branches/release-35/t/plugins/Awesome/config.yaml (revision 1927)
@@ -0,0 +1,8 @@
+name: Awesome
+key:  awesome
+id:   awesome
+
+object_types:
+    awesome:       MT::Awesome
+    awesome_image: MT::Awesome::Image
+
Index: branches/release-35/t/plugins/Awesome/lib/MT/Awesome/Image.pm
===================================================================
--- branches/release-35/t/plugins/Awesome/lib/MT/Awesome/Image.pm (revision 1927)
+++ branches/release-35/t/plugins/Awesome/lib/MT/Awesome/Image.pm (revision 1927)
@@ -0,0 +1,13 @@
+package MT::Awesome::Image;
+
+our @ISA = qw( MT::Awesome );
+
+__PACKAGE__->install_properties({
+    class_type => 'image',
+    column_defs => {
+        'width' => 'integer meta',
+        'height' => 'integer meta indexed',
+    },
+});
+
+1;
Index: branches/release-35/t/plugins/Awesome/lib/MT/Awesome.pm
===================================================================
--- branches/release-35/t/plugins/Awesome/lib/MT/Awesome.pm (revision 1927)
+++ branches/release-35/t/plugins/Awesome/lib/MT/Awesome.pm (revision 1927)
@@ -0,0 +1,19 @@
+
+package MT::Awesome;
+
+our @ISA = qw( MT::Object );
+
+__PACKAGE__->install_properties({
+    column_defs => {
+        id => 'integer not null auto_increment',
+        title => 'string(255)',
+        file => 'string(255)',
+        mime_type => 'string meta',
+    },
+    meta => 1,
+    class_type => 'foo',
+    datasource => 'awesome',
+    primary_key => 'id',
+});
+
+1;
Index: branches/release-35/t/64-objectmeta.t
===================================================================
--- branches/release-35/t/64-objectmeta.t (revision 1548)
+++ branches/release-35/t/64-objectmeta.t (revision 1927)
@@ -2,54 +2,47 @@
 
 use strict;
-use lib 'extlib', 'lib';
+use lib 't/lib', 'extlib', 'lib';
 
 use Data::Dumper;
-use Test::More tests => 13;
+use Test::More tests => 26;
 
 use MT;
 use MT::Object;
 
+use vars qw( $DB_DIR $T_CFG );
+use MT::Test qw(:db);
+
 my $mt = MT->instance;  # plugins are go!
 
+require MT::Awesome;
+require MT::Awesome::Image;
 
-package MT::Awesome;
+my $file  = MT::Awesome->new;
+my $image = MT::Awesome::Image->new;
 
-our @ISA = qw( MT::Object );
+#ok($file->has_column('meta'), 'having meta auto-adds meta column');
 
-__PACKAGE__->install_properties({
-    column_defs => {
-        id => 'integer not null auto_increment',
-        title => 'string(255)',
-        file => 'string(255)',
-    },
-    meta => 1,
-    class_type => 'foo',
-});
-__PACKAGE__->install_meta({
-    columns => [ 'mime_type' ]
-});
+ok($file->is_meta_column('mime_type'), 'adding mime_type metadata field reports mime_type as a meta column');
+ok($file->has_column('mime_type'), 'adding mime_type metadata field reports mime_type as a column');
+ok(!defined $file->meta('mime_type'), 'unset metadata field is undefined');
 
-package MT::Awesome::Image;
-
-our @ISA = qw( MT::Awesome );
-
-__PACKAGE__->install_properties({
-    class_type => 'image',
-});
-__PACKAGE__->install_meta({
-    columns => [ 'width', 'height' ]
-});
-
-package main;
-
-my $file = new MT::Awesome;
-my $image = new MT::Awesome::Image;
-
-ok($file->has_column('meta'), 'having meta auto-adds meta column');
-ok(!defined $file->meta('mime_type'), 'unset metadata field is undefined');
 ok($file->meta('mime_type', 'archive/zip'), 'metadata field could be set');
 is($file->meta('mime_type'), 'archive/zip', 'new metadata value could be retrieved');
-ok($file->{changed_cols}{meta}, 'setting metadata field marked meta column as changed');
 is($file->mime_type, 'archive/zip', 'auto-installed metadata field method retrieved new value');
+
+diag('saving object');
+ok($file->save(), 'object with metadata could be saved');
+diag('object saved');
+ok($file->id, 'object with metadata received id when saved');
+is($file->meta('mime_type'), 'archive/zip', 'metadata value is still set after save');
+
+my $file_2 = MT::Awesome->load($file->id)
+    or diag('ERROR: ' . MT::Awesome->errstr);
+ok($file_2, 'object with metadata could be loaded');
+is($file_2->meta('mime_type'), 'archive/zip', 'metadata value is correct on loaded object');
+
+is($file_2->mime_type, 'archive/zip', 'metadata value as retrieved with auto-installed method is correct on loaded object');
+
+#ok($file->{changed_cols}{meta}, 'setting metadata field marked meta column as changed');
 ok(!$file->has_meta('width'), 'metadata field on subclass did not install on superclass');
 
@@ -57,6 +50,18 @@
 ok($image->width(300), 'metadata field on subclass could be set with auto-installed method');
 is($image->width, 300, 'auto-installed metadata field method retrieved new value for subclass');
-ok($image->{changed_cols}{meta}, 'setting metadata field on subclass with auto-installed method marked meta column as changed');
+#ok($image->{changed_cols}{meta}, 'setting metadata field on subclass with auto-installed method marked meta column as changed');
 ok($image->has_meta('width'), 'subclass has metadata field that was declared for subclass');
 ok($image->has_meta('mime_type'), 'subclass has metadata field that was declared for superclass');
+ok($image->mime_type('image/jpeg'), 'subclass object mime type set');
+ok($image->save(), 'image object saved');
 
+ok($image->id, 'image object with metadata received id when saved');
+
+my $image_2 = MT::Awesome->load($image->id);
+ok($image_2, 'subclass object could be loaded');
+is($image_2->mime_type, 'image/jpeg', 'metadata value as retrieved with auto-installed method is correct on loaded image object');
+
+ok(MT::Asset::Image->has_meta('image_width'), 'MT::Asset::Image has an image_width meta column.');
+ok(MT::Entry->has_meta, 'MT::Entry has a meta support.');
+ok(MT::Page->has_meta, 'MT::Page has a meta support.');
+
