tests/plover-gtk/test-transactionhelper.c
author J. Ali Harlow <ali@juiblex.co.uk>
Fri Jun 08 14:48:00 2018 +0100 (2018-06-08)
changeset 75 6575679d2e8e
parent 42 419a02fa70db
permissions -rw-r--r--
Fix bug causing a transaction without a base to be treated as a programming error
     1 /*
     2  * Copyright (C) 2016  J. Ali Harlow <ali@juiblex.co.uk>
     3  *
     4  * This program is free software; you can redistribute it and/or modify
     5  * it under the terms of the GNU General Public License as published by
     6  * the Free Software Foundation; either version 2 of the License, or
     7  * (at your option) any later version.
     8  *
     9  * This program is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License along
    15  * with this program; if not, write to the Free Software Foundation, Inc.,
    16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    17  */
    18 
    19 #include <stdlib.h>
    20 #include <string.h>
    21 #include <locale.h>
    22 #include <sys/stat.h>
    23 #include <glib.h>
    24 #include <gdk/gdk.h>
    25 #include <gtk/gtk.h>
    26 #include <plover/plover.h>
    27 #include <plover-gtk/transactionhelper.h>
    28 
    29 GtkBuilder *ui;
    30 gboolean manual_mode=FALSE;
    31 
    32 #if 0
    33 static void complete_changed(GtkWidget *page,GParamSpec *child_property,
    34   PloverTransactionHelper *helper)
    35 {
    36     g_message("complete child property for %s now %s",
    37       gtk_buildable_get_name(GTK_BUILDABLE(page)),
    38       gtk_assistant_get_page_complete(helper->assistant,page)?"TRUE":"FALSE");
    39 }
    40 #endif
    41 
    42 PloverTransactionHelper *get_transaction_helper(void)
    43 {
    44     const char *dir;
    45     gchar *s;
    46     GError *err=NULL;
    47     PloverTransactionHelper *helper;
    48     dir=g_getenv("gtk_srcdir");
    49     s=g_build_filename(dir,"software-installation.ui",NULL);
    50     ui=gtk_builder_new();
    51     if (!gtk_builder_add_from_file(ui,s,&err))
    52 	g_error("%s: %s",s,err->message);
    53     g_free(s);
    54     helper=plover_transaction_helper_new(ui);
    55     g_object_unref(ui);
    56 #if 0
    57     if (helper->assistant)
    58     {
    59 	GtkWidget *page;
    60 	int i;
    61 	for(i=gtk_assistant_get_n_pages(helper->assistant)-1;i>=0;i--)
    62 	{
    63 	    page=gtk_assistant_get_nth_page(helper->assistant,i);
    64 	    g_signal_connect(page,"child-notify::complete",
    65 	      G_CALLBACK(complete_changed),helper);
    66 	    g_message("complete child property for %s initially %s",
    67 	      gtk_buildable_get_name(GTK_BUILDABLE(page)),
    68 	      gtk_assistant_get_page_complete(helper->assistant,page)?
    69 	      "TRUE":"FALSE");
    70 	}
    71     }
    72 #endif
    73     return helper;
    74 }
    75 
    76 static void test_init(void)
    77 {
    78     PloverTransactionHelper *helper;
    79     helper=get_transaction_helper();
    80     g_object_unref(helper);
    81 }
    82 
    83 static void test_basic_properties(void)
    84 {
    85     const char *prefix;
    86     char *uri;
    87     gchar *default_prefix;
    88     GError *err=NULL;
    89     struct comps *comps;
    90     PloverTransactionHelper *helper;
    91     PloverPackageSet *installed;
    92     PloverRepository *upstream;
    93     upstream=plover_repository_new_from_yum("../yum-repo-test-dir",&err);
    94     if (!upstream)
    95 	g_error("../yum-repo-test-dir: %s",err->message);
    96     uri=razor_path_to_uri("../razor-test-dir");
    97     installed=plover_package_set_new_from_installed(uri,&err);
    98     free(uri);
    99     if (!installed)
   100 	g_error("../razor-test-dir: %s",err->message);
   101     helper=get_transaction_helper();
   102     g_assert(!plover_transaction_helper_get_visible(helper));
   103     plover_transaction_helper_set_installed(helper,installed);
   104     g_assert(plover_transaction_helper_get_installed(helper)==installed);
   105     plover_transaction_helper_set_upstream(helper,upstream);
   106     g_assert(plover_transaction_helper_get_upstream(helper,&err)==upstream);
   107     g_assert(!err);
   108     plover_transaction_helper_set_base(helper,"../yum-repo-test-dir");
   109     g_assert_cmpstr(plover_transaction_helper_get_base(helper),==,"../yum-repo-test-dir");
   110     comps=plover_transaction_helper_get_comps(helper,&err);
   111     g_assert(!err);
   112     g_assert(plover_comps_lookup_group(comps,"base"));
   113     prefix=plover_transaction_helper_get_prefix(helper,&err);
   114     g_assert(!err);
   115     comps=plover_comps_new();
   116     plover_comps_set_vendor(comps,"Acme Corporation");
   117     default_prefix=plover_comps_get_default_prefix(comps);
   118     plover_comps_free(comps);
   119     g_assert_cmpstr(prefix,==,default_prefix);
   120     g_free(default_prefix);
   121     g_assert(!plover_transaction_helper_get_visible(helper));
   122     g_assert(!plover_transaction_helper_get_error(helper,NULL));
   123     g_object_unref(upstream);
   124     g_object_unref(installed);
   125     g_object_unref(helper);
   126 }
   127 
   128 static void test_install_group(void)
   129 {
   130     gchar *root;
   131     GError *err=NULL;
   132     char *uri;
   133     PloverPackageSet *installed;
   134     PloverTransactionHelper *helper;
   135     root=g_strdup("razor-test-dir-XXXXXX");
   136     g_assert(mkdtemp(root));
   137     uri=razor_path_to_uri(root);
   138     g_free(root);
   139     g_setenv("RAZOR_ROOT",uri,TRUE);
   140     free(uri);
   141     helper=get_transaction_helper();
   142     uri=razor_path_to_uri("../razor-test-dir");
   143     installed=plover_package_set_new_from_installed(uri,&err);
   144     free(uri);
   145     if (!installed)
   146 	g_error("../razor-test-dir: %s",err->message);
   147     plover_transaction_helper_set_installed(helper,installed);
   148     g_object_unref(installed);
   149     plover_transaction_helper_set_base(helper,"../yum-repo-test-dir");
   150     if (!plover_transaction_helper_install_group(helper,"base",&err))
   151 	g_error("base: %s",err->message);
   152     g_assert(!err);
   153     g_object_unref(helper);
   154     g_unsetenv("RAZOR_ROOT");
   155 }
   156 
   157 static void test_remove_group(void)
   158 {
   159     gchar *root;
   160     char *uri;
   161     GError *err=NULL;
   162     PloverPackageSet *installed;
   163     PloverTransactionHelper *helper;
   164     struct plover_vector *packages;
   165     char *pkgs[]={"zip",NULL};
   166     root=g_strdup("razor-test-dir-XXXXXX");
   167     g_assert(mkdtemp(root));
   168     uri=razor_path_to_uri(root);
   169     g_setenv("RAZOR_ROOT",uri,TRUE);
   170     helper=get_transaction_helper();
   171     plover_transaction_helper_set_base(helper,"../yum-repo-test-dir");
   172     packages=plover_transaction_helper_group_get_default_packages(helper,
   173       "zappy",&err);
   174     if (!packages)
   175 	g_error("zappy: %s",err->message);
   176     if (!plover_install("../yum-repo-test-dir",NULL,packages->strings,&err))
   177 	g_error("plover_install: %s",err->message);
   178     plover_vector_free(packages);
   179     installed=plover_package_set_new_from_installed(uri,&err);
   180     if (!installed)
   181 	g_error("%s: %s",root,err->message);
   182     plover_transaction_helper_set_installed(helper,installed);
   183     g_object_unref(installed);
   184     if (!plover_transaction_helper_remove_group(helper,"zappy",&err))
   185 	g_error("zappy: %s",err->message);
   186     g_assert(!err);
   187     g_object_unref(helper);
   188     g_unsetenv("RAZOR_ROOT");
   189     free(uri);
   190     g_free(root);
   191 }
   192 
   193 static void test_update(void)
   194 {
   195     gchar *root;
   196     char *uri;
   197     GError *err=NULL;
   198     PloverPackageSet *installed;
   199     PloverTransactionHelper *helper;
   200     root=g_strdup("razor-test-dir-XXXXXX");
   201     g_assert(mkdtemp(root));
   202     uri=razor_path_to_uri(root);
   203     g_setenv("RAZOR_ROOT",uri,TRUE);
   204     g_free(uri);
   205     helper=get_transaction_helper();
   206     uri=razor_path_to_uri("../razor-test-dir");
   207     installed=plover_package_set_new_from_installed(uri,&err);
   208     free(uri);
   209     if (!installed)
   210 	g_error("../razor-test-dir: %s",err->message);
   211     plover_transaction_helper_set_installed(helper,installed);
   212     g_object_unref(installed);
   213     plover_transaction_helper_set_base(helper,"../yum-repo-test-dir");
   214     if (plover_transaction_helper_update(helper,&err))
   215 	g_error("plover_transaction_helper_update reports work to be done");
   216     g_assert_error(err,PLOVER_GENERAL_ERROR,PLOVER_GENERAL_ERROR_NO_WORK);
   217     g_object_unref(helper);
   218     g_unsetenv("RAZOR_ROOT");
   219 }
   220 
   221 struct run_install_baton {
   222     enum {
   223 	RI_STATE_INIT = 0,
   224 	RI_STATE_SUMMARY,
   225 	RI_STATE_PROGRESS,
   226 	RI_STATE_PROGRESS_DELAY,
   227 	RI_STATE_DONE,
   228 	RI_STATE_FINISH
   229     } state;
   230     guint eid;		/* event ID (or 0) */
   231     PloverTransactionHelper *helper;
   232 };
   233 
   234 gboolean run_install_tick(gpointer data)
   235 {
   236     gboolean retval=TRUE;
   237     struct run_install_baton *baton=data;
   238     GtkWidget *page;
   239     GtkAssistant *assistant=baton->helper->assistant;
   240 #if 0
   241     page=gtk_assistant_get_nth_page(assistant,
   242       gtk_assistant_get_current_page(assistant));
   243     g_message("run_install_tick: state is %s, on page %s",
   244       baton->state==RI_STATE_INIT?"INIT":
   245       baton->state==RI_STATE_SUMMARY?"SUMMARY":
   246       baton->state==RI_STATE_PROGRESS?"PROGRESS":
   247       baton->state==RI_STATE_PROGRESS_DELAY?"PROGRESS_DELAY":
   248       baton->state==RI_STATE_DONE?"DONE":
   249       baton->state==RI_STATE_FINISH?"FINISH":
   250       "Unknown",
   251       gtk_buildable_get_name(GTK_BUILDABLE(page)));
   252 #endif
   253     switch(baton->state)
   254     {
   255 	case RI_STATE_INIT:
   256 	    if (!assistant || !gtk_widget_get_visible(GTK_WIDGET(assistant)))
   257 		return TRUE;
   258 	    if (!manual_mode)
   259 		gtk_button_clicked(GTK_BUTTON(assistant->forward));
   260 	    break;
   261 	case RI_STATE_SUMMARY:
   262 	    if (gtk_assistant_get_current_page(assistant)<1)
   263 		return TRUE;
   264 	    g_assert(gtk_widget_is_sensitive(assistant->apply));
   265 	    if (!manual_mode)
   266 		gtk_button_clicked(GTK_BUTTON(assistant->apply));
   267 	    break;
   268 	case RI_STATE_PROGRESS:
   269 	    if (gtk_assistant_get_current_page(assistant)<2)
   270 		return TRUE;
   271 	    page=gtk_assistant_get_nth_page(assistant,2);
   272 	    baton->eid=g_timeout_add_seconds(1,run_install_tick,baton);
   273 	    if (!gtk_assistant_get_page_complete(assistant,page))
   274 		return FALSE;
   275 	    else
   276 		retval=FALSE;
   277 	    break;
   278 	case RI_STATE_PROGRESS_DELAY:
   279 	    retval=FALSE;
   280 	    baton->eid=g_idle_add_full(G_PRIORITY_LOW,run_install_tick,baton,
   281 	      NULL);
   282 	    if (!manual_mode)
   283 		gtk_button_clicked(GTK_BUTTON(assistant->forward));
   284 	    break;
   285 	case RI_STATE_DONE:
   286 	    if (gtk_assistant_get_current_page(assistant)<3)
   287 		return TRUE;
   288 	    if (!manual_mode)
   289 		gtk_button_clicked(GTK_BUTTON(assistant->close));
   290 	    break;
   291 	case RI_STATE_FINISH:
   292 	    if (assistant && gtk_widget_get_visible(GTK_WIDGET(assistant)))
   293 		return TRUE;
   294 	    gtk_main_quit();
   295 	    baton->eid=0;
   296 	    return FALSE;
   297     }
   298     baton->state++;
   299     return retval;
   300 }
   301 
   302 static void test_run_install(void)
   303 {
   304     gchar *root;
   305     char *uri;
   306     GError *err=NULL;
   307     struct plover_vector *packages;
   308     PloverPackageSet *installed;
   309     PloverTransactionHelper *helper;
   310     struct run_install_baton baton={0,};
   311     root=g_strdup("razor-test-dir-XXXXXX");
   312     g_assert(mkdtemp(root));
   313     uri=razor_path_to_uri(root);
   314     g_setenv("RAZOR_ROOT",uri,TRUE);
   315     helper=get_transaction_helper();
   316     installed=plover_package_set_new();
   317     if (!plover_package_set_open(installed,uri,TRUE,&err))
   318 	g_error("%s: %s",root,err->message);
   319     plover_transaction_helper_set_installed(helper,installed);
   320     g_object_unref(installed);
   321     plover_transaction_helper_set_base(helper,"../yum-repo-test-dir");
   322     packages=plover_vector_new();
   323     plover_vector_append(packages,"zappy-tools");
   324     if (!plover_transaction_helper_install_packages(helper,packages,&err))
   325 	g_error("zappy-tools: %s",err->message);
   326     g_assert(!err);
   327     plover_vector_free(packages);
   328     plover_transaction_helper_present(helper);
   329     baton.helper=helper;
   330     baton.eid=g_idle_add_full(G_PRIORITY_LOW,run_install_tick,&baton,NULL);
   331     gtk_main();
   332     g_object_unref(helper);
   333     g_unsetenv("RAZOR_ROOT");
   334     free(uri);
   335     g_free(root);
   336 }
   337 
   338 struct run_remove_baton {
   339     enum {
   340 	RR_STATE_INIT = 0,
   341 	RR_STATE_SUMMARY,
   342 	RR_STATE_PROGRESS,
   343 	RR_STATE_PROGRESS_DELAY,
   344 	RR_STATE_DONE,
   345 	RR_STATE_FINISH
   346     } state;
   347     guint eid;		/* event ID (or 0) */
   348     PloverTransactionHelper *helper;
   349 };
   350 
   351 gboolean run_remove_tick(gpointer data)
   352 {
   353     gboolean retval=TRUE;
   354     struct run_remove_baton *baton=data;
   355     GtkWidget *page;
   356     GtkAssistant *assistant=baton->helper->assistant;
   357     switch(baton->state)
   358     {
   359 	case RR_STATE_INIT:
   360 	    if (!assistant || !gtk_widget_get_visible(GTK_WIDGET(assistant)))
   361 		return TRUE;
   362 	    if (!manual_mode)
   363 		gtk_button_clicked(GTK_BUTTON(assistant->forward));
   364 	    break;
   365 	case RR_STATE_SUMMARY:
   366 	    if (gtk_assistant_get_current_page(assistant)<1)
   367 		return TRUE;
   368 	    g_assert(gtk_widget_is_sensitive(assistant->apply));
   369 	    if (!manual_mode)
   370 		gtk_button_clicked(GTK_BUTTON(assistant->apply));
   371 	    break;
   372 	case RR_STATE_PROGRESS:
   373 	    if (gtk_assistant_get_current_page(assistant)<2)
   374 		return TRUE;
   375 	    page=gtk_assistant_get_nth_page(assistant,2);
   376 	    baton->eid=g_timeout_add_seconds(1,run_remove_tick,baton);
   377 	    if (!gtk_assistant_get_page_complete(assistant,page))
   378 		return FALSE;
   379 	    else
   380 		retval=FALSE;
   381 	    break;
   382 	case RR_STATE_PROGRESS_DELAY:
   383 	    retval=FALSE;
   384 	    baton->eid=g_idle_add_full(G_PRIORITY_LOW,run_remove_tick,baton,
   385 	      NULL);
   386 	    if (!manual_mode)
   387 		gtk_button_clicked(GTK_BUTTON(assistant->forward));
   388 	    break;
   389 	case RR_STATE_DONE:
   390 	    if (gtk_assistant_get_current_page(assistant)<3)
   391 		return TRUE;
   392 	    if (!manual_mode)
   393 		gtk_button_clicked(GTK_BUTTON(assistant->close));
   394 	    break;
   395 	case RR_STATE_FINISH:
   396 	    if (assistant && gtk_widget_get_visible(GTK_WIDGET(assistant)))
   397 		return TRUE;
   398 	    gtk_main_quit();
   399 	    baton->eid=0;
   400 	    return FALSE;
   401     }
   402     baton->state++;
   403     return retval;
   404 }
   405 
   406 static void test_run_remove(void)
   407 {
   408     gchar *root;
   409     char *uri;
   410     GError *err=NULL;
   411     struct plover_vector *packages;
   412     PloverPackageSet *installed;
   413     PloverTransactionHelper *helper;
   414     struct run_remove_baton baton={0,};
   415     root=g_strdup("razor-test-dir-XXXXXX");
   416     g_assert(mkdtemp(root));
   417     uri=razor_path_to_uri(root);
   418     g_setenv("RAZOR_ROOT",uri,TRUE);
   419     helper=get_transaction_helper();
   420     plover_transaction_helper_set_base(helper,"../yum-repo-test-dir");
   421     packages=
   422       plover_transaction_helper_group_get_default_packages(helper,"zappy",&err);
   423     if (!packages)
   424 	g_error("zappy: %s",err->message);
   425     if (!plover_install("../yum-repo-test-dir",NULL,packages->strings,&err))
   426 	g_error("plover_install: %s",err->message);
   427     plover_vector_free(packages);
   428     installed=plover_package_set_new();
   429     if (!plover_package_set_open(installed,uri,TRUE,&err))
   430 	g_error("%s: %s",root,err->message);
   431     plover_transaction_helper_set_installed(helper,installed);
   432     g_object_unref(installed);
   433     if (!plover_transaction_helper_remove_group(helper,"zappy",&err))
   434 	g_error("zappy: %s",err->message);
   435     g_assert(!err);
   436     plover_transaction_helper_present(helper);
   437     baton.helper=helper;
   438     baton.eid=g_idle_add_full(G_PRIORITY_LOW,run_remove_tick,&baton,NULL);
   439     gtk_main();
   440     g_object_unref(helper);
   441     g_unsetenv("RAZOR_ROOT");
   442     free(uri);
   443     g_free(root);
   444 }
   445 
   446 struct run_update_baton {
   447     enum {
   448 	RU_STATE_INIT = 0,
   449 	RU_STATE_SUMMARY,
   450 	RU_STATE_PROGRESS,
   451 	RU_STATE_PROGRESS_DELAY,
   452 	RU_STATE_DONE,
   453 	RU_STATE_FINISH
   454     } state;
   455     guint eid;		/* event ID (or 0) */
   456     PloverTransactionHelper *helper;
   457 };
   458 
   459 gboolean run_update_tick(gpointer data)
   460 {
   461     gboolean retval=TRUE;
   462     struct run_update_baton *baton=data;
   463     GtkWidget *page;
   464     GtkAssistant *assistant=baton->helper->assistant;
   465     switch(baton->state)
   466     {
   467 	case RU_STATE_INIT:
   468 	    if (!assistant || !gtk_widget_get_visible(GTK_WIDGET(assistant)))
   469 		return TRUE;
   470 	    if (!manual_mode)
   471 		gtk_button_clicked(GTK_BUTTON(assistant->forward));
   472 	    break;
   473 	case RU_STATE_SUMMARY:
   474 	    if (gtk_assistant_get_current_page(assistant)<1)
   475 		return TRUE;
   476 	    g_assert(gtk_widget_is_sensitive(assistant->apply));
   477 	    if (!manual_mode)
   478 		gtk_button_clicked(GTK_BUTTON(assistant->apply));
   479 	    break;
   480 	case RU_STATE_PROGRESS:
   481 	    if (gtk_assistant_get_current_page(assistant)<2)
   482 		return TRUE;
   483 	    page=gtk_assistant_get_nth_page(assistant,2);
   484 	    baton->eid=g_timeout_add_seconds(1,run_update_tick,baton);
   485 	    if (!gtk_assistant_get_page_complete(assistant,page))
   486 		return FALSE;
   487 	    else
   488 		retval=FALSE;
   489 	    break;
   490 	case RU_STATE_PROGRESS_DELAY:
   491 	    retval=FALSE;
   492 	    baton->eid=g_idle_add_full(G_PRIORITY_LOW,run_update_tick,baton,
   493 	      NULL);
   494 	    if (!manual_mode)
   495 		gtk_button_clicked(GTK_BUTTON(assistant->forward));
   496 	    break;
   497 	case RU_STATE_DONE:
   498 	    if (gtk_assistant_get_current_page(assistant)<3)
   499 		return TRUE;
   500 	    if (!manual_mode)
   501 		gtk_button_clicked(GTK_BUTTON(assistant->close));
   502 	    break;
   503 	case RU_STATE_FINISH:
   504 	    if (assistant && gtk_widget_get_visible(GTK_WIDGET(assistant)))
   505 		return TRUE;
   506 	    gtk_main_quit();
   507 	    baton->eid=0;
   508 	    return FALSE;
   509     }
   510     baton->state++;
   511     return retval;
   512 }
   513 
   514 static void test_run_update(void)
   515 {
   516     gchar *root;
   517     char *uri;
   518     GError *err=NULL;
   519     struct razor_importer *importer;
   520     struct razor_set *downgraded;
   521     struct razor_atomic *atomic;
   522     struct plover_vector *packages;
   523     PloverPackageSet *installed;
   524     PloverTransactionHelper *helper;
   525     struct run_update_baton baton={0,};
   526     root=g_strdup("razor-test-dir-XXXXXX");
   527     g_assert(mkdtemp(root));
   528     uri=razor_path_to_uri(root);
   529     g_setenv("RAZOR_ROOT",uri,TRUE);
   530     helper=get_transaction_helper();
   531     plover_transaction_helper_set_base(helper,"../yum-repo-test-dir");
   532     installed=plover_package_set_new();
   533     if (!plover_package_set_open(installed,uri,TRUE,&err))
   534 	g_error("%s: %s",root,err->message);
   535     importer=razor_importer_create();
   536     razor_importer_begin_package(importer,"zappy","0-1","noarch");
   537     razor_importer_add_details(importer,"","","","");
   538     razor_importer_add_property(importer,"zappy",RAZOR_PROPERTY_PROVIDES,"0-1");
   539     razor_importer_finish_package(importer);
   540     downgraded=razor_importer_finish(importer);
   541     atomic=razor_atomic_open("Add downgraded packages");
   542     if (!plover_package_set_update(installed,downgraded,atomic) ||
   543       razor_atomic_commit(atomic))
   544 	g_error("%s: %s",root,razor_atomic_get_error_msg(atomic));
   545     razor_atomic_destroy(atomic);
   546     razor_set_unref(downgraded);
   547     plover_transaction_helper_set_installed(helper,installed);
   548     g_object_unref(installed);
   549     if (!plover_transaction_helper_update(helper,&err))
   550 	g_error("update: %s",err->message);
   551     g_assert(!err);
   552     plover_transaction_helper_present(helper);
   553     baton.helper=helper;
   554     baton.eid=g_idle_add_full(G_PRIORITY_LOW,run_update_tick,&baton,NULL);
   555     gtk_main();
   556     g_object_unref(helper);
   557     g_unsetenv("RAZOR_ROOT");
   558     free(uri);
   559     g_free(root);
   560 }
   561 
   562 struct check_vendor_baton {
   563     enum {
   564 	CV_STATE_INIT = 0,
   565 	CV_STATE_SUMMARY,
   566 	CV_STATE_PROGRESS,
   567 	CV_STATE_PROGRESS_DELAY,
   568 	CV_STATE_DONE,
   569 	CV_STATE_FINISH
   570     } state;
   571     guint eid;		/* event ID (or 0) */
   572     PloverTransactionHelper *helper;
   573 };
   574 
   575 gboolean check_vendor_tick(gpointer data)
   576 {
   577     gboolean retval=TRUE;
   578     struct check_vendor_baton *baton=data;
   579     GtkWidget *page,*w;
   580     GtkAssistant *assistant=baton->helper->assistant;
   581     switch(baton->state)
   582     {
   583 	case CV_STATE_INIT:
   584 	    if (!assistant || !gtk_widget_get_visible(GTK_WIDGET(assistant)))
   585 		return TRUE;
   586 	    if (!manual_mode)
   587 		gtk_button_clicked(GTK_BUTTON(assistant->forward));
   588 	    break;
   589 	case CV_STATE_SUMMARY:
   590 	    if (gtk_assistant_get_current_page(assistant)<1)
   591 		return TRUE;
   592 	    g_assert(!gtk_widget_is_sensitive(assistant->apply));
   593 	    w=GTK_WIDGET(gtk_builder_get_object(ui,"SIRemoveExisting"));
   594 	    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w),TRUE);
   595 	    g_assert(gtk_widget_is_sensitive(assistant->apply));
   596 	    if (!manual_mode)
   597 		gtk_button_clicked(GTK_BUTTON(assistant->apply));
   598 	    break;
   599 	case CV_STATE_PROGRESS:
   600 	    if (gtk_assistant_get_current_page(assistant)<2)
   601 		return TRUE;
   602 	    page=gtk_assistant_get_nth_page(assistant,2);
   603 	    baton->eid=g_timeout_add_seconds(1,check_vendor_tick,baton);
   604 	    if (!gtk_assistant_get_page_complete(assistant,page))
   605 		return FALSE;
   606 	    else
   607 		retval=FALSE;
   608 	    break;
   609 	case CV_STATE_PROGRESS_DELAY:
   610 	    retval=FALSE;
   611 	    baton->eid=g_idle_add_full(G_PRIORITY_LOW,check_vendor_tick,baton,
   612 	      NULL);
   613 	    if (!manual_mode)
   614 		gtk_button_clicked(GTK_BUTTON(assistant->forward));
   615 	    break;
   616 	case CV_STATE_DONE:
   617 	    if (gtk_assistant_get_current_page(assistant)<3)
   618 		return TRUE;
   619 	    if (!manual_mode)
   620 		gtk_button_clicked(GTK_BUTTON(assistant->close));
   621 	    break;
   622 	case CV_STATE_FINISH:
   623 	    if (assistant && gtk_widget_get_visible(GTK_WIDGET(assistant)))
   624 		return TRUE;
   625 	    gtk_main_quit();
   626 	    baton->eid=0;
   627 	    return FALSE;
   628     }
   629     baton->state++;
   630     return retval;
   631 }
   632 
   633 static void test_check_vendor(void)
   634 {
   635     int fh;
   636     gchar *root,*s;
   637     char *uri;
   638     GError *err=NULL;
   639     struct razor_importer *importer;
   640     struct razor_set *downgraded;
   641     struct razor_atomic *atomic;
   642     struct plover_vector *packages;
   643     PloverPackageSet *installed;
   644     PloverTransactionHelper *helper;
   645     struct check_vendor_baton baton={0,};
   646     g_setenv("PLOVER_VENDOR_PREFIX","/srv",TRUE);
   647     root=g_strdup("razor-test-dir-XXXXXX");
   648     g_assert(mkdtemp(root));
   649     uri=razor_path_to_uri(root);
   650     g_setenv("RAZOR_ROOT",uri,TRUE);
   651     helper=get_transaction_helper();
   652     plover_transaction_helper_set_check_vendor(helper,TRUE);
   653     plover_transaction_helper_set_base(helper,"../yum-repo-test-dir");
   654     installed=plover_package_set_new();
   655     if (!plover_package_set_open(installed,uri,TRUE,&err))
   656 	g_error("%s: %s",root,err->message);
   657     importer=razor_importer_create();
   658     razor_importer_begin_package(importer,"zappy","0-1","noarch");
   659     razor_importer_add_details(importer,"","","","");
   660     razor_importer_add_property(importer,"zappy",RAZOR_PROPERTY_PROVIDES,"0-1");
   661     razor_importer_add_install_prefix(importer,"/test");
   662     razor_importer_add_file(importer,"/test/bin/zappy");
   663     razor_importer_finish_package(importer);
   664     downgraded=razor_importer_finish(importer);
   665     atomic=razor_atomic_open("Add downgraded packages");
   666     razor_atomic_make_dirs(atomic,uri,"/test/bin/zappy");
   667     s=g_build_filename(uri,"test/bin/zappy",NULL);
   668     fh=razor_atomic_create_file(atomic,s,S_IRWXU|S_IRWXG|S_IRWXO);
   669     g_free(s);
   670     razor_atomic_close(atomic,fh);
   671     if (!plover_package_set_update(installed,downgraded,atomic) ||
   672       razor_atomic_commit(atomic))
   673 	g_error("%s: %s",root,razor_atomic_get_error_msg(atomic));
   674     razor_atomic_destroy(atomic);
   675     razor_set_unref(downgraded);
   676     plover_transaction_helper_set_installed(helper,installed);
   677     g_object_unref(installed);
   678     if (!plover_transaction_helper_update(helper,&err))
   679 	g_error("update: %s",err->message);
   680     g_assert(!err);
   681     plover_transaction_helper_present(helper);
   682     baton.helper=helper;
   683     baton.eid=g_idle_add_full(G_PRIORITY_LOW,check_vendor_tick,&baton,NULL);
   684     gtk_main();
   685     g_object_unref(helper);
   686     g_unsetenv("RAZOR_ROOT");
   687     g_free(root);
   688     free(uri);
   689     g_unsetenv("PLOVER_VENDOR_PREFIX");
   690 }
   691 
   692 static gchar *create_new_root_and_install(gchar **prefix_p,char **pkgs)
   693 {
   694     gchar *root,*prefix;
   695     char *uri;
   696     GError *err=NULL;
   697     struct comps *comps;
   698     PloverTransaction *transaction;
   699     root=g_strdup("razor-test-dir-XXXXXX");
   700     g_assert(mkdtemp(root));
   701     uri=razor_path_to_uri(root);
   702     g_setenv("RAZOR_ROOT",uri,TRUE);
   703     free(uri);
   704     uri=razor_path_to_uri("../yum-repo-test-dir/repodata/comps.xml");
   705     comps=plover_comps_new_from_uri(uri,&err);
   706     free(uri);
   707     if (!comps)
   708 	g_error("../yum-repo-test-dir/repodata/comps.xml: %s",err->message);
   709     prefix=plover_comps_get_default_prefix(comps);
   710     plover_comps_free(comps);
   711     transaction=plover_transaction_new_install("../yum-repo-test-dir",prefix,
   712       pkgs,&err);
   713     if (!transaction)
   714 	g_error("../yum-repo-test-dir: %s",err->message);
   715     g_assert(plover_transaction_commit(transaction,NULL,NULL));
   716     g_object_unref(transaction);
   717     fflush(stdout);
   718     if (prefix_p)
   719 	*prefix_p=prefix;
   720     else
   721 	g_free(prefix);
   722     return root;
   723 }
   724 
   725 static check_file(const char *root,const char *path)
   726 {
   727     gchar *s;
   728     s=g_build_filename(root,path,NULL);
   729     g_assert(g_file_test(s,G_FILE_TEST_EXISTS));
   730     g_free(s);
   731 }
   732 
   733 static check_no_file(const char *root,const char *path)
   734 {
   735     gchar *s;
   736     s=g_build_filename(root,path,NULL);
   737     g_assert(!g_file_test(s,G_FILE_TEST_EXISTS));
   738     g_free(s);
   739 }
   740 
   741 /*
   742  * Test that installing from a repository which is marked as distribution-local
   743  * on top of an existing global installation works if prefix is NULL
   744  * (which is the case on UNIX if PLOVER_VENDOR_PREFIX is not set).
   745  */
   746 static void test_unprefixed_distribution_local(void)
   747 {
   748     gchar *root;
   749     GError *err=NULL;
   750     char *pkgs[]={"zap",NULL};
   751     struct plover_vector *packages;
   752     PloverPackageSet *installed;
   753     PloverTransactionHelper *helper;
   754     struct run_install_baton baton={0,};
   755     g_unsetenv("PLOVER_VENDOR_PREFIX");
   756     root=create_new_root_and_install(NULL,pkgs);
   757     check_file(root,"/usr/bin/zap");
   758     helper=get_transaction_helper();
   759     plover_transaction_helper_set_check_vendor(helper,TRUE);
   760     plover_transaction_helper_set_base(helper,"../distribution-local-test-dir");
   761     packages=plover_vector_new();
   762     plover_vector_append(packages,"zappy");
   763     if (!plover_transaction_helper_install_packages(helper,packages,&err))
   764 	g_error("zappy: %s",err->message);
   765     g_assert(!err);
   766     plover_vector_free(packages);
   767     plover_transaction_helper_present(helper);
   768     baton.helper=helper;
   769     baton.eid=g_idle_add_full(G_PRIORITY_LOW,run_install_tick,&baton,NULL);
   770     gtk_main();
   771     g_object_unref(helper);
   772     check_file(root,"/usr/bin/zappy");
   773     g_free(root);
   774     g_unsetenv("RAZOR_ROOT");
   775 }
   776 
   777 /*
   778  * Test that installing from a repository which is marked as distribution-local
   779  * on top of an existing global installation requires removing the existing
   780  * installation if prefix is non-NULL (which is the case if PLOVER_VENDOR_PREFIX
   781  * is set).
   782  */
   783 static void test_prefixed_distribution_local(void)
   784 {
   785     gchar *root,*s;
   786     gchar *prefix;
   787     GError *err=NULL;
   788     char *pkgs[]={"zap",NULL};
   789     struct plover_vector *packages;
   790     PloverPackageSet *installed;
   791     PloverTransactionHelper *helper;
   792     struct check_vendor_baton baton={0,};
   793     g_setenv("PLOVER_VENDOR_PREFIX","/srv",TRUE);
   794     helper=get_transaction_helper();
   795     plover_transaction_helper_set_check_vendor(helper,TRUE);
   796     plover_transaction_helper_set_base(helper,"../distribution-local-test-dir");
   797     root=create_new_root_and_install(&prefix,pkgs);
   798     s=g_build_filename(prefix,"bin/zap",NULL);
   799     check_file(root,s);
   800     g_free(s);
   801     packages=plover_vector_new();
   802     plover_vector_append(packages,"filesystem");
   803     if (!plover_transaction_helper_install_packages(helper,packages,&err))
   804 	g_error("filesystem: %s",err->message);
   805     g_assert(!err);
   806     plover_vector_free(packages);
   807     plover_transaction_helper_present(helper);
   808     baton.helper=helper;
   809     baton.eid=g_idle_add_full(G_PRIORITY_LOW,check_vendor_tick,&baton,NULL);
   810     gtk_main();
   811     g_object_unref(helper);
   812     s=g_build_filename(prefix,"bin/zap",NULL);
   813     check_no_file(root,s);
   814     g_free(s);
   815     check_no_file(root,"/media");
   816     g_free(root);
   817     g_free(prefix);
   818     g_unsetenv("RAZOR_ROOT");
   819 }
   820 
   821 struct set_error_baton {
   822     enum {
   823 	SE_STATE_INIT = 0,
   824 	SE_STATE_FINISH
   825     } state;
   826     PloverTransactionHelper *helper;
   827 };
   828 
   829 /*
   830  * This handler may be called as either an event (ie., idle or timeout)
   831  * or as a (swapped) signal. In the latter case, the return is ignored.
   832  */
   833 gboolean set_error_tick(gpointer data)
   834 {
   835     struct set_error_baton *baton=data;
   836     GtkDialog *dlg;
   837     GtkWidget *button;
   838     dlg=GTK_DIALOG(baton->helper->error_dialog);
   839     switch(baton->state)
   840     {
   841 	case SE_STATE_INIT:
   842 	    if (!dlg || !gtk_widget_get_visible(GTK_WIDGET(dlg)))
   843 		return TRUE;
   844 	    button=gtk_dialog_get_widget_for_response(dlg,GTK_RESPONSE_CLOSE);
   845 	    if (!manual_mode)
   846 		gtk_button_clicked(GTK_BUTTON(button));
   847 	    break;
   848 	case SE_STATE_FINISH:
   849 	    if (dlg && gtk_widget_get_visible(GTK_WIDGET(dlg)))
   850 		return TRUE;
   851 	    gtk_main_quit();
   852 	    return FALSE;
   853     }
   854     baton->state++;
   855     return TRUE;
   856 }
   857 
   858 static void test_set_error(void)
   859 {
   860     gchar *root;
   861     char *uri;
   862     const char *errmsg;
   863     GError *err=NULL;
   864     const GError *err2=NULL;
   865     PloverPackageSet *installed;
   866     PloverTransactionHelper *helper;
   867     struct set_error_baton baton={0,};
   868     root=g_strdup("razor-test-dir-XXXXXX");
   869     g_assert(mkdtemp(root));
   870     uri=razor_path_to_uri(root);
   871     g_free(root);
   872     g_setenv("RAZOR_ROOT",uri,TRUE);
   873     free(uri);
   874     helper=get_transaction_helper();
   875     uri=razor_path_to_uri("../razor-test-dir");
   876     installed=plover_package_set_new_from_installed(uri,&err);
   877     free(uri);
   878     if (!installed)
   879 	g_error("../razor-test-dir: %s",err->message);
   880     plover_transaction_helper_set_installed(helper,installed);
   881     g_object_unref(installed);
   882     plover_transaction_helper_set_base(helper,"../yum-repo-test-dir");
   883     if (!plover_transaction_helper_update(helper,&err))
   884 	plover_transaction_helper_set_error(helper,err,"Expected error");
   885     g_assert(plover_transaction_helper_get_visible(helper));
   886     errmsg=plover_transaction_helper_get_error(helper,&err2);
   887     g_assert_cmpstr(errmsg,==,"Expected error");
   888     g_assert_error(err2,err->domain,err->code);
   889     plover_transaction_helper_present(helper);
   890     baton.helper=helper;
   891     g_idle_add_full(G_PRIORITY_LOW,set_error_tick,&baton,NULL);
   892     g_error_free(err);
   893     gtk_main();
   894     g_object_unref(helper);
   895     g_unsetenv("RAZOR_ROOT");
   896 }
   897 
   898 int main(int argc,char **argv)
   899 {
   900     int retval;
   901     GError *err=NULL;
   902     /*
   903      * Note that because g_test_init() handles --help,
   904      * these options will not appear in the output.
   905      */
   906     GOptionEntry options[]={
   907 	{"manual",0,0,G_OPTION_ARG_NONE,&manual_mode,
   908 	  "Disable automatic mode",NULL},
   909 	{NULL}
   910     };
   911     g_test_init(&argc,&argv,NULL);
   912     g_setenv("GTK_MODULES","",TRUE);
   913     g_setenv("GTK2_RC_FILES","/dev/null",TRUE);
   914     gtk_disable_setlocale();
   915     setlocale(LC_ALL,"C");
   916     g_test_bug_base("mailto:ali@juiblex.co.uk");
   917     if (!gtk_init_with_args(&argc,&argv,NULL,options,NULL,&err))
   918     {
   919 	g_printf("%s\n",err->message);
   920 	exit(0);
   921     }
   922     g_test_add_func("/transactionhelper/init",test_init);
   923     g_test_add_func("/transactionhelper/basic-properties",
   924       test_basic_properties);
   925     g_test_add_func("/transactionhelper/install-group",test_install_group);
   926     g_test_add_func("/transactionhelper/remove-group",test_remove_group);
   927     g_test_add_func("/transactionhelper/update",test_update);
   928     g_test_add_func("/transactionhelper/run-install",test_run_install);
   929     g_test_add_func("/transactionhelper/run-remove",test_run_remove);
   930     g_test_add_func("/transactionhelper/run-update",test_run_update);
   931     g_test_add_func("/transactionhelper/check-vendor",test_check_vendor);
   932     g_test_add_func("/transactionhelper/unprefixed-distribution-local",
   933       test_unprefixed_distribution_local);
   934     g_test_add_func("/transactionhelper/prefixed-distribution-local",
   935       test_prefixed_distribution_local);
   936     g_test_add_func("/transactionhelper/set-error",test_set_error);
   937     retval=g_test_run();
   938     return retval;
   939 }