diff options
-rwxr-xr-x | tools/testing/ktest/ktest.pl | 452 |
1 files changed, 226 insertions, 226 deletions
diff --git a/tools/testing/ktest/ktest.pl b/tools/testing/ktest/ktest.pl index c34f0dedad2d..52f558efdb0a 100755 --- a/tools/testing/ktest/ktest.pl +++ b/tools/testing/ktest/ktest.pl | |||
@@ -2784,12 +2784,17 @@ my %dependency; | |||
2784 | sub assign_configs { | 2784 | sub assign_configs { |
2785 | my ($hash, $config) = @_; | 2785 | my ($hash, $config) = @_; |
2786 | 2786 | ||
2787 | doprint "Reading configs from $config\n"; | ||
2788 | |||
2787 | open (IN, $config) | 2789 | open (IN, $config) |
2788 | or dodie "Failed to read $config"; | 2790 | or dodie "Failed to read $config"; |
2789 | 2791 | ||
2790 | while (<IN>) { | 2792 | while (<IN>) { |
2793 | chomp; | ||
2791 | if (/^((CONFIG\S*)=.*)/) { | 2794 | if (/^((CONFIG\S*)=.*)/) { |
2792 | ${$hash}{$2} = $1; | 2795 | ${$hash}{$2} = $1; |
2796 | } elsif (/^(# (CONFIG\S*) is not set)/) { | ||
2797 | ${$hash}{$2} = $1; | ||
2793 | } | 2798 | } |
2794 | } | 2799 | } |
2795 | 2800 | ||
@@ -2841,53 +2846,97 @@ sub get_dependencies { | |||
2841 | return @deps; | 2846 | return @deps; |
2842 | } | 2847 | } |
2843 | 2848 | ||
2849 | sub save_config { | ||
2850 | my ($pc, $file) = @_; | ||
2851 | |||
2852 | my %configs = %{$pc}; | ||
2853 | |||
2854 | doprint "Saving configs into $file\n"; | ||
2855 | |||
2856 | open(OUT, ">$file") or dodie "Can not write to $file"; | ||
2857 | |||
2858 | foreach my $config (keys %configs) { | ||
2859 | print OUT "$configs{$config}\n"; | ||
2860 | } | ||
2861 | close(OUT); | ||
2862 | } | ||
2863 | |||
2844 | sub create_config { | 2864 | sub create_config { |
2845 | my @configs = @_; | 2865 | my ($name, $pc) = @_; |
2846 | 2866 | ||
2847 | open(OUT, ">$output_config") or dodie "Can not write to $output_config"; | 2867 | doprint "Creating old config from $name configs\n"; |
2848 | 2868 | ||
2849 | foreach my $config (@configs) { | 2869 | save_config $pc, $output_config; |
2850 | print OUT "$config_set{$config}\n"; | 2870 | |
2851 | my @deps = get_dependencies $config; | 2871 | make_oldconfig; |
2852 | foreach my $dep (@deps) { | 2872 | } |
2853 | print OUT "$config_set{$dep}\n"; | 2873 | |
2874 | # compare two config hashes, and return configs with different vals. | ||
2875 | # It returns B's config values, but you can use A to see what A was. | ||
2876 | sub diff_config_vals { | ||
2877 | my ($pa, $pb) = @_; | ||
2878 | |||
2879 | # crappy Perl way to pass in hashes. | ||
2880 | my %a = %{$pa}; | ||
2881 | my %b = %{$pb}; | ||
2882 | |||
2883 | my %ret; | ||
2884 | |||
2885 | foreach my $item (keys %a) { | ||
2886 | if (defined($b{$item}) && $b{$item} ne $a{$item}) { | ||
2887 | $ret{$item} = $b{$item}; | ||
2854 | } | 2888 | } |
2855 | } | 2889 | } |
2856 | 2890 | ||
2857 | # turn off configs to keep off | 2891 | return %ret; |
2858 | foreach my $config (keys %config_off) { | 2892 | } |
2859 | print OUT "# $config is not set\n"; | ||
2860 | } | ||
2861 | 2893 | ||
2862 | # turn off configs that should be off for now | 2894 | # compare two config hashes and return the configs in B but not A |
2863 | foreach my $config (@config_off_tmp) { | 2895 | sub diff_configs { |
2864 | print OUT "# $config is not set\n"; | 2896 | my ($pa, $pb) = @_; |
2865 | } | 2897 | |
2898 | my %ret; | ||
2899 | |||
2900 | # crappy Perl way to pass in hashes. | ||
2901 | my %a = %{$pa}; | ||
2902 | my %b = %{$pb}; | ||
2866 | 2903 | ||
2867 | foreach my $config (keys %config_ignore) { | 2904 | foreach my $item (keys %b) { |
2868 | print OUT "$config_ignore{$config}\n"; | 2905 | if (!defined($a{$item})) { |
2906 | $ret{$item} = $b{$item}; | ||
2907 | } | ||
2869 | } | 2908 | } |
2870 | close(OUT); | ||
2871 | 2909 | ||
2872 | make_oldconfig; | 2910 | return %ret; |
2873 | } | 2911 | } |
2874 | 2912 | ||
2913 | # return if two configs are equal or not | ||
2914 | # 0 is equal +1 b has something a does not | ||
2915 | # +1 if a and b have a different item. | ||
2916 | # -1 if a has something b does not | ||
2875 | sub compare_configs { | 2917 | sub compare_configs { |
2876 | my (%a, %b) = @_; | 2918 | my ($pa, $pb) = @_; |
2877 | 2919 | ||
2878 | foreach my $item (keys %a) { | 2920 | my %ret; |
2879 | if (!defined($b{$item})) { | 2921 | |
2880 | print "diff $item\n"; | 2922 | # crappy Perl way to pass in hashes. |
2923 | my %a = %{$pa}; | ||
2924 | my %b = %{$pb}; | ||
2925 | |||
2926 | foreach my $item (keys %b) { | ||
2927 | if (!defined($a{$item})) { | ||
2928 | return 1; | ||
2929 | } | ||
2930 | if ($a{$item} ne $b{$item}) { | ||
2881 | return 1; | 2931 | return 1; |
2882 | } | 2932 | } |
2883 | delete $b{$item}; | ||
2884 | } | 2933 | } |
2885 | 2934 | ||
2886 | my @keys = keys %b; | 2935 | foreach my $item (keys %a) { |
2887 | if ($#keys) { | 2936 | if (!defined($b{$item})) { |
2888 | print "diff2 $keys[0]\n"; | 2937 | return -1; |
2938 | } | ||
2889 | } | 2939 | } |
2890 | return -1 if ($#keys >= 0); | ||
2891 | 2940 | ||
2892 | return 0; | 2941 | return 0; |
2893 | } | 2942 | } |
@@ -2923,253 +2972,204 @@ sub process_failed { | |||
2923 | doprint "***************************************\n\n"; | 2972 | doprint "***************************************\n\n"; |
2924 | } | 2973 | } |
2925 | 2974 | ||
2926 | sub run_config_bisect { | 2975 | # used for config bisecting |
2976 | my $good_config; | ||
2977 | my $bad_config; | ||
2927 | 2978 | ||
2928 | my @start_list = keys %config_list; | 2979 | sub process_new_config { |
2980 | my ($tc, $nc, $gc, $bc) = @_; | ||
2929 | 2981 | ||
2930 | if ($#start_list < 0) { | 2982 | my %tmp_config = %{$tc}; |
2931 | doprint "No more configs to test!!!\n"; | 2983 | my %good_configs = %{$gc}; |
2932 | return -1; | 2984 | my %bad_configs = %{$bc}; |
2933 | } | ||
2934 | 2985 | ||
2935 | doprint "***** RUN TEST ***\n"; | 2986 | my %new_configs; |
2936 | my $type = $config_bisect_type; | ||
2937 | my $ret; | ||
2938 | my %current_config; | ||
2939 | 2987 | ||
2940 | my $count = $#start_list + 1; | 2988 | my $runtest = 1; |
2941 | doprint " $count configs to test\n"; | 2989 | my $ret; |
2942 | 2990 | ||
2943 | my $half = int($#start_list / 2); | 2991 | create_config "tmp_configs", \%tmp_config; |
2992 | assign_configs \%new_configs, $output_config; | ||
2944 | 2993 | ||
2945 | do { | 2994 | $ret = compare_configs \%new_configs, \%bad_configs; |
2946 | my @tophalf = @start_list[0 .. $half]; | 2995 | if (!$ret) { |
2996 | doprint "New config equals bad config, try next test\n"; | ||
2997 | $runtest = 0; | ||
2998 | } | ||
2947 | 2999 | ||
2948 | # keep the bottom half off | 3000 | if ($runtest) { |
2949 | if ($half < $#start_list) { | 3001 | $ret = compare_configs \%new_configs, \%good_configs; |
2950 | @config_off_tmp = @start_list[$half + 1 .. $#start_list]; | 3002 | if (!$ret) { |
2951 | } else { | 3003 | doprint "New config equals good config, try next test\n"; |
2952 | @config_off_tmp = (); | 3004 | $runtest = 0; |
2953 | } | 3005 | } |
3006 | } | ||
2954 | 3007 | ||
2955 | create_config @tophalf; | 3008 | %{$nc} = %new_configs; |
2956 | read_current_config \%current_config; | ||
2957 | |||
2958 | $count = $#tophalf + 1; | ||
2959 | doprint "Testing $count configs\n"; | ||
2960 | my $found = 0; | ||
2961 | # make sure we test something | ||
2962 | foreach my $config (@tophalf) { | ||
2963 | if (defined($current_config{$config})) { | ||
2964 | logit " $config\n"; | ||
2965 | $found = 1; | ||
2966 | } | ||
2967 | } | ||
2968 | if (!$found) { | ||
2969 | # try the other half | ||
2970 | doprint "Top half produced no set configs, trying bottom half\n"; | ||
2971 | |||
2972 | # keep the top half off | ||
2973 | @config_off_tmp = @tophalf; | ||
2974 | @tophalf = @start_list[$half + 1 .. $#start_list]; | ||
2975 | |||
2976 | create_config @tophalf; | ||
2977 | read_current_config \%current_config; | ||
2978 | foreach my $config (@tophalf) { | ||
2979 | if (defined($current_config{$config})) { | ||
2980 | logit " $config\n"; | ||
2981 | $found = 1; | ||
2982 | } | ||
2983 | } | ||
2984 | if (!$found) { | ||
2985 | doprint "Failed: Can't make new config with current configs\n"; | ||
2986 | foreach my $config (@start_list) { | ||
2987 | doprint " CONFIG: $config\n"; | ||
2988 | } | ||
2989 | return -1; | ||
2990 | } | ||
2991 | $count = $#tophalf + 1; | ||
2992 | doprint "Testing $count configs\n"; | ||
2993 | } | ||
2994 | 3009 | ||
2995 | $ret = run_config_bisect_test $type; | 3010 | return $runtest; |
2996 | if ($bisect_manual) { | 3011 | } |
2997 | $ret = answer_bisect; | ||
2998 | } | ||
2999 | if ($ret) { | ||
3000 | process_passed %current_config; | ||
3001 | return 0; | ||
3002 | } | ||
3003 | 3012 | ||
3004 | doprint "This config had a failure.\n"; | 3013 | sub run_config_bisect { |
3005 | doprint "Removing these configs that were not set in this config:\n"; | 3014 | my ($pgood, $pbad) = @_; |
3006 | doprint "config copied to $outputdir/config_bad\n"; | ||
3007 | run_command "cp -f $output_config $outputdir/config_bad"; | ||
3008 | 3015 | ||
3009 | # A config exists in this group that was bad. | 3016 | my $type = $config_bisect_type; |
3010 | foreach my $config (keys %config_list) { | ||
3011 | if (!defined($current_config{$config})) { | ||
3012 | doprint " removing $config\n"; | ||
3013 | delete $config_list{$config}; | ||
3014 | } | ||
3015 | } | ||
3016 | 3017 | ||
3017 | @start_list = @tophalf; | 3018 | my %good_configs = %{$pgood}; |
3019 | my %bad_configs = %{$pbad}; | ||
3018 | 3020 | ||
3019 | if ($#start_list == 0) { | 3021 | my %diff_configs = diff_config_vals \%good_configs, \%bad_configs; |
3020 | process_failed $start_list[0]; | 3022 | my %b_configs = diff_configs \%good_configs, \%bad_configs; |
3021 | return 1; | 3023 | my %g_configs = diff_configs \%bad_configs, \%good_configs; |
3022 | } | ||
3023 | 3024 | ||
3024 | # remove half the configs we are looking at and see if | 3025 | my @diff_arr = keys %diff_configs; |
3025 | # they are good. | 3026 | my $len_diff = $#diff_arr + 1; |
3026 | $half = int($#start_list / 2); | ||
3027 | } while ($#start_list > 0); | ||
3028 | 3027 | ||
3029 | # we found a single config, try it again unless we are running manually | 3028 | my @b_arr = keys %b_configs; |
3029 | my $len_b = $#b_arr + 1; | ||
3030 | 3030 | ||
3031 | if ($bisect_manual) { | 3031 | my @g_arr = keys %g_configs; |
3032 | process_failed $start_list[0]; | 3032 | my $len_g = $#g_arr + 1; |
3033 | return 1; | ||
3034 | } | ||
3035 | 3033 | ||
3036 | my @tophalf = @start_list[0 .. 0]; | 3034 | my $runtest = 1; |
3035 | my %new_configs; | ||
3036 | my $ret; | ||
3037 | 3037 | ||
3038 | $ret = run_config_bisect_test $type; | 3038 | # First, lets get it down to a single subset. |
3039 | if ($ret) { | 3039 | # Is the problem with a difference in values? |
3040 | process_passed %current_config; | 3040 | # Is the problem with a missing config? |
3041 | return 0; | 3041 | # Is the problem with a config that breaks things? |
3042 | } | ||
3043 | 3042 | ||
3044 | process_failed $start_list[0]; | 3043 | # Enable all of one set and see if we get a new bad |
3045 | return 1; | 3044 | # or good config. |
3046 | } | ||
3047 | 3045 | ||
3048 | sub config_bisect { | 3046 | # first set the good config to the bad values. |
3049 | my ($i) = @_; | ||
3050 | 3047 | ||
3051 | my $start_config = $config_bisect; | 3048 | doprint "d=$len_diff g=$len_g b=$len_b\n"; |
3052 | 3049 | ||
3053 | my $tmpconfig = "$tmpdir/use_config"; | 3050 | # first lets enable things in bad config that are enabled in good config |
3054 | 3051 | ||
3055 | if (defined($config_bisect_good)) { | 3052 | if ($len_diff > 0) { |
3056 | process_config_ignore $config_bisect_good; | 3053 | if ($len_b > 0 || $len_g > 0) { |
3057 | } | 3054 | my %tmp_config = %bad_configs; |
3058 | 3055 | ||
3059 | # Make the file with the bad config and the min config | 3056 | doprint "Set tmp config to be bad config with good config values\n"; |
3060 | if (defined($minconfig)) { | 3057 | foreach my $item (@diff_arr) { |
3061 | # read the min config for things to ignore | 3058 | $tmp_config{$item} = $good_configs{$item}; |
3062 | run_command "cp $minconfig $tmpconfig" or | 3059 | } |
3063 | dodie "failed to copy $minconfig to $tmpconfig"; | ||
3064 | } else { | ||
3065 | unlink $tmpconfig; | ||
3066 | } | ||
3067 | 3060 | ||
3068 | if (-f $tmpconfig) { | 3061 | $runtest = process_new_config \%tmp_config, \%new_configs, |
3069 | load_force_config($tmpconfig); | 3062 | \%good_configs, \%bad_configs; |
3070 | process_config_ignore $tmpconfig; | 3063 | } |
3071 | } | 3064 | } |
3072 | 3065 | ||
3073 | # now process the start config | 3066 | if (!$runtest && $len_diff > 0) { |
3074 | run_command "cp $start_config $output_config" or | ||
3075 | dodie "failed to copy $start_config to $output_config"; | ||
3076 | 3067 | ||
3077 | # read directly what we want to check | 3068 | if ($len_diff == 1) { |
3078 | my %config_check; | 3069 | doprint "The bad config setting is: $diff_arr[0]\n"; |
3079 | open (IN, $output_config) | 3070 | return 1; |
3080 | or dodie "failed to open $output_config"; | 3071 | } |
3072 | my %tmp_config = %bad_configs; | ||
3081 | 3073 | ||
3082 | while (<IN>) { | 3074 | my $half = int($#diff_arr / 2); |
3083 | if (/^((CONFIG\S*)=.*)/) { | 3075 | my @tophalf = @diff_arr[0 .. $half]; |
3084 | $config_check{$2} = $1; | 3076 | |
3077 | doprint "Settings bisect with top half:\n"; | ||
3078 | doprint "Set tmp config to be bad config with some good config values\n"; | ||
3079 | foreach my $item (@tophalf) { | ||
3080 | $tmp_config{$item} = $good_configs{$item}; | ||
3085 | } | 3081 | } |
3086 | } | ||
3087 | close(IN); | ||
3088 | 3082 | ||
3089 | # Now run oldconfig with the minconfig | 3083 | $runtest = process_new_config \%tmp_config, \%new_configs, |
3090 | make_oldconfig; | 3084 | \%good_configs, \%bad_configs; |
3091 | 3085 | ||
3092 | # check to see what we lost (or gained) | 3086 | if (!$runtest) { |
3093 | open (IN, $output_config) | 3087 | my %tmp_config = %bad_configs; |
3094 | or dodie "Failed to read $start_config"; | ||
3095 | 3088 | ||
3096 | my %removed_configs; | 3089 | doprint "Try bottom half\n"; |
3097 | my %added_configs; | ||
3098 | 3090 | ||
3099 | while (<IN>) { | 3091 | my @bottomhalf = @diff_arr[$half+1 .. $#diff_arr]; |
3100 | if (/^((CONFIG\S*)=.*)/) { | 3092 | |
3101 | # save off all options | 3093 | foreach my $item (@bottomhalf) { |
3102 | $config_set{$2} = $1; | 3094 | $tmp_config{$item} = $good_configs{$item}; |
3103 | if (defined($config_check{$2})) { | ||
3104 | if (defined($config_ignore{$2})) { | ||
3105 | $removed_configs{$2} = $1; | ||
3106 | } else { | ||
3107 | $config_list{$2} = $1; | ||
3108 | } | ||
3109 | } elsif (!defined($config_ignore{$2})) { | ||
3110 | $added_configs{$2} = $1; | ||
3111 | $config_list{$2} = $1; | ||
3112 | } | 3095 | } |
3113 | } elsif (/^# ((CONFIG\S*).*)/) { | ||
3114 | # Keep these configs disabled | ||
3115 | $config_set{$2} = $1; | ||
3116 | $config_off{$2} = $1; | ||
3117 | } | ||
3118 | } | ||
3119 | close(IN); | ||
3120 | 3096 | ||
3121 | my @confs = keys %removed_configs; | 3097 | $runtest = process_new_config \%tmp_config, \%new_configs, |
3122 | if ($#confs >= 0) { | 3098 | \%good_configs, \%bad_configs; |
3123 | doprint "Configs overridden by default configs and removed from check:\n"; | ||
3124 | foreach my $config (@confs) { | ||
3125 | doprint " $config\n"; | ||
3126 | } | 3099 | } |
3127 | } | 3100 | } |
3128 | @confs = keys %added_configs; | 3101 | |
3129 | if ($#confs >= 0) { | 3102 | if ($runtest) { |
3130 | doprint "Configs appearing in make oldconfig and added:\n"; | 3103 | $ret = run_config_bisect_test $type; |
3131 | foreach my $config (@confs) { | 3104 | if ($ret) { |
3132 | doprint " $config\n"; | 3105 | doprint "NEW GOOD CONFIG\n"; |
3106 | %good_configs = %new_configs; | ||
3107 | run_command "mv $good_config ${good_config}.last"; | ||
3108 | save_config \%good_configs, $good_config; | ||
3109 | %{$pgood} = %good_configs; | ||
3110 | } else { | ||
3111 | doprint "NEW BAD CONFIG\n"; | ||
3112 | %bad_configs = %new_configs; | ||
3113 | run_command "mv $bad_config ${bad_config}.last"; | ||
3114 | save_config \%bad_configs, $bad_config; | ||
3115 | %{$pbad} = %bad_configs; | ||
3133 | } | 3116 | } |
3117 | return 0; | ||
3134 | } | 3118 | } |
3135 | 3119 | ||
3136 | my %config_test; | 3120 | fail "Hmm, need to do a mix match?\n"; |
3137 | my $once = 0; | 3121 | return -1; |
3122 | } | ||
3138 | 3123 | ||
3139 | @config_off_tmp = (); | 3124 | sub config_bisect { |
3125 | my ($i) = @_; | ||
3140 | 3126 | ||
3141 | # Sometimes kconfig does weird things. We must make sure | 3127 | my $type = $config_bisect_type; |
3142 | # that the config we autocreate has everything we need | ||
3143 | # to test, otherwise we may miss testing configs, or | ||
3144 | # may not be able to create a new config. | ||
3145 | # Here we create a config with everything set. | ||
3146 | create_config (keys %config_list); | ||
3147 | read_current_config \%config_test; | ||
3148 | foreach my $config (keys %config_list) { | ||
3149 | if (!defined($config_test{$config})) { | ||
3150 | if (!$once) { | ||
3151 | $once = 1; | ||
3152 | doprint "Configs not produced by kconfig (will not be checked):\n"; | ||
3153 | } | ||
3154 | doprint " $config\n"; | ||
3155 | delete $config_list{$config}; | ||
3156 | } | ||
3157 | } | ||
3158 | my $ret; | ||
3159 | 3128 | ||
3160 | if (defined($config_bisect_check) && $config_bisect_check) { | 3129 | $bad_config = $config_bisect; |
3161 | doprint " Checking to make sure bad config with min config fails\n"; | 3130 | |
3162 | create_config keys %config_list; | 3131 | if (defined($config_bisect_good)) { |
3163 | $ret = run_config_bisect_test $config_bisect_type; | 3132 | $good_config = $config_bisect_good; |
3164 | if ($ret) { | 3133 | } elsif (defined($minconfig)) { |
3165 | doprint " FAILED! Bad config with min config boots fine\n"; | 3134 | $good_config = $minconfig; |
3166 | return -1; | 3135 | } else { |
3136 | doprint "No config specified, checking if defconfig works"; | ||
3137 | my $ret = run_bisect_test $type, "defconfig"; | ||
3138 | if (!$ret) { | ||
3139 | fail "Have no good config to compare with, please set CONFIG_BISECT_GOOD"; | ||
3140 | return 1; | ||
3167 | } | 3141 | } |
3168 | doprint " Bad config with min config fails as expected\n"; | 3142 | $good_config = $output_config; |
3169 | } | 3143 | } |
3170 | 3144 | ||
3145 | # we don't want min configs to cause issues here. | ||
3146 | doprint "Disabling 'MIN_CONFIG' for this test\n"; | ||
3147 | undef $minconfig; | ||
3148 | |||
3149 | my %good_configs; | ||
3150 | my %bad_configs; | ||
3151 | my %tmp_configs; | ||
3152 | |||
3153 | doprint "Run good configs through make oldconfig\n"; | ||
3154 | assign_configs \%tmp_configs, $good_config; | ||
3155 | create_config "$good_config", \%tmp_configs; | ||
3156 | assign_configs \%good_configs, $output_config; | ||
3157 | |||
3158 | doprint "Run bad configs through make oldconfig\n"; | ||
3159 | assign_configs \%tmp_configs, $bad_config; | ||
3160 | create_config "$bad_config", \%tmp_configs; | ||
3161 | assign_configs \%bad_configs, $output_config; | ||
3162 | |||
3163 | $good_config = "$tmpdir/good_config"; | ||
3164 | $bad_config = "$tmpdir/bad_config"; | ||
3165 | |||
3166 | save_config \%good_configs, $good_config; | ||
3167 | save_config \%bad_configs, $bad_config; | ||
3168 | |||
3169 | my $ret; | ||
3170 | |||
3171 | do { | 3171 | do { |
3172 | $ret = run_config_bisect; | 3172 | $ret = run_config_bisect \%good_configs, \%bad_configs; |
3173 | } while (!$ret); | 3173 | } while (!$ret); |
3174 | 3174 | ||
3175 | return $ret if ($ret < 0); | 3175 | return $ret if ($ret < 0); |